From 3a273a10f155b74543e4a6c9a2e8894ac92dfb60 Mon Sep 17 00:00:00 2001 From: Yared888 Date: Wed, 21 Jan 2015 11:35:18 +0100 Subject: [PATCH 1/6] just some changes --- AMF/+AMF/@ModelResult/plot.m | 53 --------------------------------- AMF/+AMF/@ModelResult/plotAll.m | 28 ++++++++++++----- AMF/+AMF/runADAPT.m | 8 +++-- 3 files changed, 27 insertions(+), 62 deletions(-) delete mode 100644 AMF/+AMF/@ModelResult/plot.m diff --git a/AMF/+AMF/@ModelResult/plot.m b/AMF/+AMF/@ModelResult/plot.m deleted file mode 100644 index 49d5db2..0000000 --- a/AMF/+AMF/@ModelResult/plot.m +++ /dev/null @@ -1,53 +0,0 @@ -function this = plot(this, names, mode) - -if nargin < 3, mode = 'TRAJ'; end - -import AMF.utils.defineCustomColormap - -if isa(names, 'char') - names = {names}; -end - -n = length(names); -ns = sqrt(n); - -numIter = this.options.numIter; - -for i = 1:length(names) - subplot(ceil(ns),ceil(ns),i); hold on; - name = names{i}; - - comp = this.ref.(name); - - switch upper(mode) - case 'TRAJ' - colorMap = defineCustomColormap({[0.8 0.6 0.6] [0.8 0 0] [0.2 0 0]}, numIter); - plotTraj(this, comp, colorMap); - - case 'HIST' - colorMap = defineCustomColormap({[1 1 1] [0.8 0 0] [0.2 0 0]}, numIter); - plotHist(this, comp, colorMap); - - case 'HIST_LOG' - - % TODO: plot logarithmic histograms - - otherwise - error('Unknown plot mode %s', mode); - end - - xlabel([this.predictor.unitType, ' [', this.predictor.unit, ']']); - xlim([this.time(1) this.time(end)]); - - if comp.label - title(comp.label); - else - title(comp.name); - end - - if comp.unit - ylabel(sprintf('%s [%s]', comp.unitType, comp.unit)); - else - ylabel(comp.unitType); - end -end \ No newline at end of file diff --git a/AMF/+AMF/@ModelResult/plotAll.m b/AMF/+AMF/@ModelResult/plotAll.m index c2792a1..cbd97f3 100644 --- a/AMF/+AMF/@ModelResult/plotAll.m +++ b/AMF/+AMF/@ModelResult/plotAll.m @@ -1,6 +1,14 @@ -function this = plotAll(this, type, mode) +function this = plotAll(this, type, varargin) -if nargin < 3, mode = 'TRAJ'; end +if nargin < 3, mode = 'TRAJ'; +else mode = varargin{1}; +end + +if length(varargin)>1 + split = varargin{2}; +else + split = 9; +end import AMF.utils.defineCustomColormap @@ -9,15 +17,20 @@ comps = comps(logical([this.parameters.fit])); end + n = length(comps); -ns = sqrt(n); +ns = sqrt(split); +% ns = sqrt(n); numIter = this.options.numIter; figure('Name', upper(type)); for i = 1:n - subplot(ceil(ns),ceil(ns),i); hold on; + figure(ceil(i/split)); + counter = ceil(i/split); + subplot(ceil(ns),ceil(ns),i-(counter-1)*split); hold on; +% subplot(ceil(ns),ceil(ns),i); hold on; comp = comps(i); @@ -31,9 +44,10 @@ plotHist(this, comp, colorMap); case 'HIST_LOG' - - % TODO: plot logarithmic histograms - + % TODO: plot logarithmic histograms + case 'MAD' % median absolute deviation + plotMad(this, comp, 'g'); + otherwise error('Unknown plot mode %s', mode); end diff --git a/AMF/+AMF/runADAPT.m b/AMF/+AMF/runADAPT.m index 42224c8..7ca3d88 100644 --- a/AMF/+AMF/runADAPT.m +++ b/AMF/+AMF/runADAPT.m @@ -27,6 +27,7 @@ result = model.result; tic +utils.parfor_progress(numIter); parfor it = 1:numIter model2 = model; % parfor fix elt = 0; @@ -47,14 +48,17 @@ success = 1; catch err - % + disp(err.message); + utils.parfor_progress2; end end + utils.parfor_progress; - fprintf('Computed trajectory %d [%d] - %.2fs\n', it, max(model2.result.sse), elt); +% fprintf('Computed trajectory %d [%d] - %.2fs\n', it, max(model2.result.sse), elt); result(it) = model2.result; end +parfor_progress(0); toc result = AMF.ModelResult(model, result); From 22ce6d1898dea69a8c14258ebcae83c404f1dfc7 Mon Sep 17 00:00:00 2001 From: Yared888 Date: Wed, 21 Jan 2015 11:36:02 +0100 Subject: [PATCH 2/6] just some changes --- AMF/+AMF/+utils/parfor_progress.m | 82 ++++++++++++++++++++++++++++++ AMF/+AMF/+utils/parfor_progress2.m | 82 ++++++++++++++++++++++++++++++ AMF/+AMF/@ModelResult/plotMad.m | 22 ++++++++ AMF/+AMF/@ModelResult/plots.m | 71 ++++++++++++++++++++++++++ 4 files changed, 257 insertions(+) create mode 100644 AMF/+AMF/+utils/parfor_progress.m create mode 100644 AMF/+AMF/+utils/parfor_progress2.m create mode 100644 AMF/+AMF/@ModelResult/plotMad.m create mode 100644 AMF/+AMF/@ModelResult/plots.m diff --git a/AMF/+AMF/+utils/parfor_progress.m b/AMF/+AMF/+utils/parfor_progress.m new file mode 100644 index 0000000..07ec991 --- /dev/null +++ b/AMF/+AMF/+utils/parfor_progress.m @@ -0,0 +1,82 @@ +function percent = parfor_progress(N) +%PARFOR_PROGRESS Progress monitor (progress bar) that works with parfor. +% PARFOR_PROGRESS works by creating a file called parfor_progress.txt in +% your working directory, and then keeping track of the parfor loop's +% progress within that file. This workaround is necessary because parfor +% workers cannot communicate with one another so there is no simple way +% to know which iterations have finished and which haven't. +% +% PARFOR_PROGRESS(N) initializes the progress monitor for a set of N +% upcoming calculations. +% +% PARFOR_PROGRESS updates the progress inside your parfor loop and +% displays an updated progress bar. +% +% PARFOR_PROGRESS(0) deletes parfor_progress.txt and finalizes progress +% bar. +% +% To suppress output from any of these functions, just ask for a return +% variable from the function calls, like PERCENT = PARFOR_PROGRESS which +% returns the percentage of completion. +% +% Example: +% +% N = 100; +% parfor_progress(N); +% parfor i=1:N +% pause(rand); % Replace with real code +% parfor_progress; +% end +% parfor_progress(0); +% +% See also PARFOR. + +% By Jeremy Scheff - jdscheff@gmail.com - http://www.jeremyscheff.com/ + +% error(nargchk(0, 1, nargin, 'struct')); + +if nargin < 1 + N = -1; +end + +percent = 0; +w = 50; % Width of progress bar + +if N > 0 + f = fopen('parfor_progress.txt', 'w'); + if f<0 + error('Do you have write permissions for %s?', pwd); + end + fprintf(f, '%d\n', N); % Save N at the top of progress.txt + fclose(f); + + if nargout == 0 + disp([' 0%[>', repmat(' ', 1, w), ']']); + end +elseif N == 0 + delete('parfor_progress.txt'); + percent = 100; + + if nargout == 0 + disp([repmat(char(8), 1, (w+9)), char(10), '100%[', repmat('=', 1, w+1), ']']); + end +else + + if ~exist('parfor_progress.txt', 'file') + error('parfor_progress.txt not found. Run PARFOR_PROGRESS(N) before PARFOR_PROGRESS to initialize parfor_progress.txt.'); + end + + f = fopen('parfor_progress.txt', 'a'); + fprintf(f, '1\n'); + fclose(f); + + f = fopen('parfor_progress.txt', 'r'); + progress = fscanf(f, '%d'); + fclose(f); + percent = (length(progress)-1)/progress(1)*100; + + if nargout == 0 + perc = sprintf('%3.0f%%', percent); % 4 characters wide, percentage + disp([repmat(char(8), 1, (w+9)), char(10), perc, '[', repmat('=', 1, round(percent*w/100)), '>', repmat(' ', 1, w - round(percent*w/100)), ']']); + end +end diff --git a/AMF/+AMF/+utils/parfor_progress2.m b/AMF/+AMF/+utils/parfor_progress2.m new file mode 100644 index 0000000..2335bb6 --- /dev/null +++ b/AMF/+AMF/+utils/parfor_progress2.m @@ -0,0 +1,82 @@ +function percent = parfor_progress2(N) +%PARFOR_PROGRESS Progress monitor (progress bar) that works with parfor. +% PARFOR_PROGRESS works by creating a file called parfor_progress.txt in +% your working directory, and then keeping track of the parfor loop's +% progress within that file. This workaround is necessary because parfor +% workers cannot communicate with one another so there is no simple way +% to know which iterations have finished and which haven't. +% +% PARFOR_PROGRESS(N) initializes the progress monitor for a set of N +% upcoming calculations. +% +% PARFOR_PROGRESS updates the progress inside your parfor loop and +% displays an updated progress bar. +% +% PARFOR_PROGRESS(0) deletes parfor_progress.txt and finalizes progress +% bar. +% +% To suppress output from any of these functions, just ask for a return +% variable from the function calls, like PERCENT = PARFOR_PROGRESS which +% returns the percentage of completion. +% +% Example: +% +% N = 100; +% parfor_progress(N); +% parfor i=1:N +% pause(rand); % Replace with real code +% parfor_progress; +% end +% parfor_progress(0); +% +% See also PARFOR. + +% By Jeremy Scheff - jdscheff@gmail.com - http://www.jeremyscheff.com/ + +% error(nargchk(0, 1, nargin, 'struct')); + +if nargin < 1 + N = -1; +end + +percent = 0; +w = 50; % Width of progress bar + +if N > 0 + f = fopen('parfor_progress.txt', 'w'); + if f<0 + error('Do you have write permissions for %s?', pwd); + end + fprintf(f, '%d\n', N); % Save N at the top of progress.txt + fclose(f); + + if nargout == 0 + disp([' 0%[>', repmat(' ', 1, w), ']']); + end +elseif N == 0 + delete('parfor_progress.txt'); + percent = 100; + + if nargout == 0 + disp([repmat(char(8), 1, (w+9)), char(10), '100%[', repmat('=', 1, w+1), ']']); + end +else + + if ~exist('parfor_progress.txt', 'file') + error('parfor_progress.txt not found. Run PARFOR_PROGRESS(N) before PARFOR_PROGRESS to initialize parfor_progress.txt.'); + end + +% f = fopen('parfor_progress.txt', 'a'); +% fprintf(f, '1\n'); +% fclose(f); + + f = fopen('parfor_progress.txt', 'r'); + progress = fscanf(f, '%d'); + fclose(f); + percent = (length(progress)-1)/progress(1)*100; + + if nargout == 0 + perc = sprintf('%3.0f%%', percent); % 4 characters wide, percentage + disp([perc, '[', repmat('=', 1, round(percent*w/100)), '>', repmat(' ', 1, w - round(percent*w/100)), ']']); + end +end diff --git a/AMF/+AMF/@ModelResult/plotMad.m b/AMF/+AMF/@ModelResult/plotMad.m new file mode 100644 index 0000000..0bc42ce --- /dev/null +++ b/AMF/+AMF/@ModelResult/plotMad.m @@ -0,0 +1,22 @@ +function [hp1, hp2] = plotMad(this, comp, color) +% plot median absolute deviation +time_steps = this.options.numTimeSteps; +meta = zeros(time_steps,4); +for dt = 1:time_steps + y = quantile(comp.val(dt,:),[0.05 0.16 0.25 0.5 0.75 0.84 0.95], 2); + meta(dt,1) = y(4); + meta(dt,2) = median(abs(comp.val(dt,:)- meta(dt,1))); + meta(dt,3) = meta(dt,1)+meta(dt,2); + meta(dt,4) = meta(dt,1)-meta(dt,2); +end +time = 1:time_steps; +time = time*this.time(end)/time_steps; +X = [time fliplr(time)]; +Yupp = meta(:,3)'; +Ylwr = meta(:,4)'; +Y = [Ylwr fliplr(Yupp)]; +hp1 = fill(X, Y, color); +hp2 = plot(time, meta(:,1), '-k', 'LineWidth', 2); + +end + diff --git a/AMF/+AMF/@ModelResult/plots.m b/AMF/+AMF/@ModelResult/plots.m new file mode 100644 index 0000000..8ded1a4 --- /dev/null +++ b/AMF/+AMF/@ModelResult/plots.m @@ -0,0 +1,71 @@ +function this = plots(this, names, mode) + +if nargin < 3, mode = 'TRAJ'; end + +import AMF.utils.defineCustomColormap + +if isa(names, 'char') + names = {names}; +end + +n = length(names); +ns = sqrt(n); + +numIter = this.options.numIter; + +for i = 1:length(names) + subplot(ceil(ns),ceil(ns),i); hold on; + name = names{i}; + + comp = this.ref.(name); + + switch upper(mode) + case 'TRAJ' + colorMap = defineCustomColormap({[0.8 0.6 0.6] [0.8 0 0] [0.2 0 0]}, numIter); + plotTraj(this, comp, colorMap); + + case 'HIST' + colorMap = defineCustomColormap({[1 1 1] [0.8 0 0] [0.2 0 0]}, numIter); + plotHist(this, comp, colorMap); + + case 'HIST_LOG' + + % TODO: plot logarithmic histograms + case 'MAD' % median absolute deviation + time_steps = this.options.numTimeSteps; + meta = zeros(time_steps,4); + for dt = 1:time_steps + y = quantile(comp.val(dt,:),[0.05 0.16 0.25 0.5 0.75 0.84 0.95], 2); + meta(dt,1) = y(4); + meta(dt,2) = median(abs(comp.val(dt,:)- meta(dt,1))); + meta(dt,3) = meta(dt,1)+meta(dt,2); + meta(dt,4) = meta(dt,1)-meta(dt,2); + end + time = 1:time_steps; + time = time*this.time(end)/time_steps; + X = [time fliplr(time)]; + Yupp = meta(:,3)'; + Ylwr = meta(:,4)'; + Y = [Ylwr fliplr(Yupp)]; + hp = fill(X, Y, 'g'); + plot(time, meta(:,1), '-k', 'LineWidth', 2); + + otherwise + error('Unknown plot mode %s', mode); + end + + xlabel([this.predictor.unitType, ' [', this.predictor.unit, ']']); + xlim([this.time(1) this.time(end)]); + + if comp.label + title(comp.label); + else + title(comp.name); + end + + if comp.unit + ylabel(sprintf('%s [%s]', comp.unitType, comp.unit)); + else + ylabel(comp.unitType); + end +end \ No newline at end of file From f80dabea6610b102f820fcb644a4676e55c6ec3c Mon Sep 17 00:00:00 2001 From: yvonnerozendaal Date: Wed, 21 Jan 2015 11:49:47 +0100 Subject: [PATCH 3/6] progress bar --- AMF/+AMF/+utils/parfor_progress.m | 82 ++++++++++++++++++++++++++ AMF/+AMF/+utils/parfor_progress2.m | 82 ++++++++++++++++++++++++++ AMF/models/minGlucModel2/runMinGluc2.m | 10 ++-- 3 files changed, 170 insertions(+), 4 deletions(-) create mode 100644 AMF/+AMF/+utils/parfor_progress.m create mode 100644 AMF/+AMF/+utils/parfor_progress2.m diff --git a/AMF/+AMF/+utils/parfor_progress.m b/AMF/+AMF/+utils/parfor_progress.m new file mode 100644 index 0000000..07ec991 --- /dev/null +++ b/AMF/+AMF/+utils/parfor_progress.m @@ -0,0 +1,82 @@ +function percent = parfor_progress(N) +%PARFOR_PROGRESS Progress monitor (progress bar) that works with parfor. +% PARFOR_PROGRESS works by creating a file called parfor_progress.txt in +% your working directory, and then keeping track of the parfor loop's +% progress within that file. This workaround is necessary because parfor +% workers cannot communicate with one another so there is no simple way +% to know which iterations have finished and which haven't. +% +% PARFOR_PROGRESS(N) initializes the progress monitor for a set of N +% upcoming calculations. +% +% PARFOR_PROGRESS updates the progress inside your parfor loop and +% displays an updated progress bar. +% +% PARFOR_PROGRESS(0) deletes parfor_progress.txt and finalizes progress +% bar. +% +% To suppress output from any of these functions, just ask for a return +% variable from the function calls, like PERCENT = PARFOR_PROGRESS which +% returns the percentage of completion. +% +% Example: +% +% N = 100; +% parfor_progress(N); +% parfor i=1:N +% pause(rand); % Replace with real code +% parfor_progress; +% end +% parfor_progress(0); +% +% See also PARFOR. + +% By Jeremy Scheff - jdscheff@gmail.com - http://www.jeremyscheff.com/ + +% error(nargchk(0, 1, nargin, 'struct')); + +if nargin < 1 + N = -1; +end + +percent = 0; +w = 50; % Width of progress bar + +if N > 0 + f = fopen('parfor_progress.txt', 'w'); + if f<0 + error('Do you have write permissions for %s?', pwd); + end + fprintf(f, '%d\n', N); % Save N at the top of progress.txt + fclose(f); + + if nargout == 0 + disp([' 0%[>', repmat(' ', 1, w), ']']); + end +elseif N == 0 + delete('parfor_progress.txt'); + percent = 100; + + if nargout == 0 + disp([repmat(char(8), 1, (w+9)), char(10), '100%[', repmat('=', 1, w+1), ']']); + end +else + + if ~exist('parfor_progress.txt', 'file') + error('parfor_progress.txt not found. Run PARFOR_PROGRESS(N) before PARFOR_PROGRESS to initialize parfor_progress.txt.'); + end + + f = fopen('parfor_progress.txt', 'a'); + fprintf(f, '1\n'); + fclose(f); + + f = fopen('parfor_progress.txt', 'r'); + progress = fscanf(f, '%d'); + fclose(f); + percent = (length(progress)-1)/progress(1)*100; + + if nargout == 0 + perc = sprintf('%3.0f%%', percent); % 4 characters wide, percentage + disp([repmat(char(8), 1, (w+9)), char(10), perc, '[', repmat('=', 1, round(percent*w/100)), '>', repmat(' ', 1, w - round(percent*w/100)), ']']); + end +end diff --git a/AMF/+AMF/+utils/parfor_progress2.m b/AMF/+AMF/+utils/parfor_progress2.m new file mode 100644 index 0000000..2335bb6 --- /dev/null +++ b/AMF/+AMF/+utils/parfor_progress2.m @@ -0,0 +1,82 @@ +function percent = parfor_progress2(N) +%PARFOR_PROGRESS Progress monitor (progress bar) that works with parfor. +% PARFOR_PROGRESS works by creating a file called parfor_progress.txt in +% your working directory, and then keeping track of the parfor loop's +% progress within that file. This workaround is necessary because parfor +% workers cannot communicate with one another so there is no simple way +% to know which iterations have finished and which haven't. +% +% PARFOR_PROGRESS(N) initializes the progress monitor for a set of N +% upcoming calculations. +% +% PARFOR_PROGRESS updates the progress inside your parfor loop and +% displays an updated progress bar. +% +% PARFOR_PROGRESS(0) deletes parfor_progress.txt and finalizes progress +% bar. +% +% To suppress output from any of these functions, just ask for a return +% variable from the function calls, like PERCENT = PARFOR_PROGRESS which +% returns the percentage of completion. +% +% Example: +% +% N = 100; +% parfor_progress(N); +% parfor i=1:N +% pause(rand); % Replace with real code +% parfor_progress; +% end +% parfor_progress(0); +% +% See also PARFOR. + +% By Jeremy Scheff - jdscheff@gmail.com - http://www.jeremyscheff.com/ + +% error(nargchk(0, 1, nargin, 'struct')); + +if nargin < 1 + N = -1; +end + +percent = 0; +w = 50; % Width of progress bar + +if N > 0 + f = fopen('parfor_progress.txt', 'w'); + if f<0 + error('Do you have write permissions for %s?', pwd); + end + fprintf(f, '%d\n', N); % Save N at the top of progress.txt + fclose(f); + + if nargout == 0 + disp([' 0%[>', repmat(' ', 1, w), ']']); + end +elseif N == 0 + delete('parfor_progress.txt'); + percent = 100; + + if nargout == 0 + disp([repmat(char(8), 1, (w+9)), char(10), '100%[', repmat('=', 1, w+1), ']']); + end +else + + if ~exist('parfor_progress.txt', 'file') + error('parfor_progress.txt not found. Run PARFOR_PROGRESS(N) before PARFOR_PROGRESS to initialize parfor_progress.txt.'); + end + +% f = fopen('parfor_progress.txt', 'a'); +% fprintf(f, '1\n'); +% fclose(f); + + f = fopen('parfor_progress.txt', 'r'); + progress = fscanf(f, '%d'); + fclose(f); + percent = (length(progress)-1)/progress(1)*100; + + if nargout == 0 + perc = sprintf('%3.0f%%', percent); % 4 characters wide, percentage + disp([perc, '[', repmat('=', 1, round(percent*w/100)), '>', repmat(' ', 1, w - round(percent*w/100)), ']']); + end +end diff --git a/AMF/models/minGlucModel2/runMinGluc2.m b/AMF/models/minGlucModel2/runMinGluc2.m index 999e3ca..9c9898f 100644 --- a/AMF/models/minGlucModel2/runMinGluc2.m +++ b/AMF/models/minGlucModel2/runMinGluc2.m @@ -11,10 +11,11 @@ %% config -model.options.optimset.Display = 'off'; -model.options.useMex = 1; model.options.numIter = 500; model.options.numTimeSteps = 100; + +model.options.optimset.Display = 'off'; +model.options.useMex = 1; model.options.SSTime = 30; model.options.lab1 = .1; model.options.randPars = 0; @@ -25,10 +26,11 @@ %% run -% model.functions.reg = @minGlucReg; - result = runADAPT(model); + +%check whether AUC satisfies carbohydrate dose + %% plot close all From 3166a89d118e4a7c4e734362b249b1f62198abdc Mon Sep 17 00:00:00 2001 From: yvonnerozendaal Date: Wed, 21 Jan 2015 12:06:48 +0100 Subject: [PATCH 4/6] version 21-01-2015 --- +AMF/+utils/defineCustomColormap.m | 28 + +AMF/+utils/getHist.m | 14 + +AMF/+utils/mexify.m | 6 + +AMF/+utils/mexify2.m | 8 + +AMF/+utils/parfor_progress.m | 82 + +AMF/+utils/parfor_progress2.m | 82 + +AMF/+utils/writeFile.m | 5 + +AMF/+visualisation/define_custom_colormap.m | 28 + +AMF/+visualisation/define_figure_details.m | 59 + +AMF/+visualisation/errorbar_tick.m | 70 + +AMF/+visualisation/plot_results.m | 244 + +AMF/+visualisation/save_figure_to_file.m | 185 + +AMF/@DataComponent/DataComponent.m | 30 + +AMF/@DataComponent/filter.m | 3 + +AMF/@DataComponent/getStruct.m | 11 + +AMF/@DataComponent/isConstant.m | 8 + +AMF/@DataComponent/isObservable.m | 3 + +AMF/@DataComponent/plot.m | 7 + +AMF/@DataField/DataField.m | 24 + +AMF/@DataField/genSpline.m | 22 + +AMF/@DataField/interp.m | 72 + +AMF/@DataField/interpLinear.m | 9 + +AMF/@DataField/interpSpline.m | 13 + +AMF/@DataField/randomize.m | 9 + +AMF/@DataField/restore.m | 8 + +AMF/@DataFunction/DataFunction.m | 16 + +AMF/@DataSet/DataSet.m | 68 + +AMF/@DataSet/compileFunctions.m | 38 + +AMF/@DataSet/filter.m | 4 + +AMF/@DataSet/get.m | 7 + +AMF/@DataSet/getDataStruct.m | 9 + +AMF/@DataSet/getFitData.m | 25 + +AMF/@DataSet/getFitTime.m | 12 + +AMF/@DataSet/getInterpData.m | 11 + +AMF/@DataSet/interp.m | 7 + +AMF/@DataSet/loadGroup.m | 6 + +AMF/@DataSet/parseFields.m | 17 + +AMF/@DataSet/parseFunctions.m | 10 + +AMF/@DataSet/randomize.m | 5 + +AMF/@GridUI/GridUI.m | 15 + +AMF/@GridUI/draw.m | 16 + +AMF/@GridUI/render.m | 8 + +AMF/@GridUI/renderAxes.m | 9 + +AMF/@GridUI/renderControl.m | 15 + +AMF/@GridUI/renderEdit.m | 35 + +AMF/@GridUI/renderListBox.m | 35 + +AMF/@GridUI/size.m | 3 + +AMF/@Model/Model.m | 146 + +AMF/@Model/addComponents.m | 13 + +AMF/@Model/compile.m | 83 + +AMF/@Model/compileAll.m | 14 + +AMF/@Model/compileInputs.m | 24 + +AMF/@Model/compileMex.m | 17 + +AMF/@Model/compileODE.m | 53 + +AMF/@Model/compileODEMex.m | 56 + +AMF/@Model/compileReactions.m | 51 + +AMF/@Model/computeAll.m | 38 + +AMF/@Model/computeInputs.m | 12 + +AMF/@Model/computeReactions.m | 9 + +AMF/@Model/computeStates.m | 9 + +AMF/@Model/filter.m | 4 + +AMF/@Model/get.m | 7 + +AMF/@Model/getAll.m | 10 + +AMF/@Model/getInputStruct.m | 7 + +AMF/@Model/getInputStructMex.m | 14 + +AMF/@Model/getInputsMex.m | 6 + +AMF/@Model/getResiduals.m | 52 + +AMF/@Model/getResult.m | 22 + +AMF/@Model/getTime.m | 18 + +AMF/@Model/initializeObservables.m | 8 + +AMF/@Model/initiateExperiment.asv | 25 + +AMF/@Model/initiateExperiment.m | 29 + +AMF/@Model/parseAll.m | 10 + +AMF/@Model/parseConstants.m | 23 + +AMF/@Model/parseInputs.m | 46 + +AMF/@Model/parseParameters.m | 15 + +AMF/@Model/parseReactions.m | 3 + +AMF/@Model/parseStates.m | 15 + +AMF/@Model/plot.m | 52 + +AMF/@Model/plotAll.m | 10 + +AMF/@Model/randomizeData.m | 10 + +AMF/@Model/randomizeParameters.m | 15 + +AMF/@Model/saveTrajectory.m | 19 + +AMF/@Model/setFitParameters.m | 14 + +AMF/@Model/setPredictor.m | 4 + +AMF/@Model/setTimeStep.m | 3 + +AMF/@ModelComponent/ModelComponent.m | 45 + +AMF/@ModelComponent/filter.m | 4 + +AMF/@ModelComponent/getStruct.m | 15 + +AMF/@ModelComponent/isObservable.m | 3 + +AMF/@ModelComponent/plot.m | 3 + +AMF/@ModelConstant/ModelConstant.m | 11 + +AMF/@ModelInput/ModelInput.m | 24 + +AMF/@ModelParameter/ModelParameter.m | 27 + +AMF/@ModelParameter/isFitParameter.m | 3 + +AMF/@ModelPredictor/ModelPredictor.m | 11 + .../@ModelReaction/@ModelResult/ModelResult.m | 63 + +AMF/@ModelReaction/@ModelResult/plotStates.m | 16 + +AMF/@ModelReaction/@ModelResult/plot_hist.m | 18 + .../@ModelReaction/@ModelResult/plot_states.m | 13 + .../@ModelResult/plot_states_norm.m | 2 + +AMF/@ModelReaction/@ModelResult/plot_traj.m | 21 + +AMF/@ModelReaction/@ModelResult/test.m | 3 + +AMF/@ModelReaction/ModelReaction.m | 11 + +AMF/@ModelResult/ModelResult.m | 106 + +AMF/@ModelResult/getColorProfile.m | 0 +AMF/@ModelResult/getValue.m | 8 + +AMF/@ModelResult/plot.m | 53 + +AMF/@ModelResult/plotAll.m | 55 + +AMF/@ModelResult/plotHist.m | 14 + +AMF/@ModelResult/plotTraj.m | 22 + +AMF/@ModelState/ModelState.m | 19 + +AMF/createDataset.m | 54 + +AMF/fit.m | 69 + +AMF/fitTimeStep.m | 64 + +AMF/manipulate.m | 31 + +AMF/proflik.m | 56 + +AMF/regFun.m | 14 + +AMF/runADAPT.asv | 54 + +AMF/runADAPT.m | 63 + +AMF/simulate.m | 25 + README.MD | 22 + README.TXT | 22 + manual.docx | Bin 0 -> 101660 bytes manual.pdf | Bin 0 -> 686563 bytes models/bariatricData.m | 251 + models/bariatricData.mat | Bin 0 -> 9770 bytes models/bariatricData_basal.m | 251 + models/minCPepModel/minCPepData.m | 26 + models/minCPepModel/minCPepModel.m | 82 + models/minCPepModel/minCPepModel2.m | 69 + models/minCPepModel/minCPepReg.m | 10 + models/minCPepModel/runMinCPep.asv | 45 + models/minCPepModel/runMinCPep.m | 45 + models/minCPepModel/runMinCPep2.m | 38 + models/minGlucModel/minGlucData.m | 25 + models/minGlucModel/minGlucModel.m | 54 + models/minGlucModel/minGlucReg.m | 7 + models/minGlucModel/runMinGluc.m | 33 + models/minGlucModel2/minGlucData2.m | 25 + models/minGlucModel2/minGlucModel2.m | 44 + models/minGlucModel2/runMinGluc2.m | 37 + models/minModel/minData.m | 26 + models/minModel/minModel.m | 120 + models/minModel/minModel2.m | 96 + models/minModel/minReg.m | 14 + models/minModel/runMin.m | 46 + models/minModel/runMin2.m | 34 + models/tiemannModel/dat.m | 95 + models/tiemannModel/data_Oosterveer.mat | Bin 0 -> 18576 bytes models/tiemannModel/runTiemann.m | 38 + models/tiemannModel/tiemannData.m | 32 + models/tiemannModel/tiemannData.mat | Bin 0 -> 2352 bytes models/tiemannModel/tiemannModel.m | 144 + models/tiemannModel/tiemannReg.m | 5 + models/toyModel/runToy.m | 45 + models/toyModel/toyData.m | 16 + models/toyModel/toyData.mat | Bin 0 -> 595 bytes models/toyModel/toyModel.m | 37 + models/toyModel/toyReg.m | 14 + odemex/COPYING | 674 ++ odemex/Examples/SBMLexample.m | 61 + odemex/Examples/example.m | 58 + odemex/Examples/fitExample.m | 132 + odemex/Examples/goodwin.m | 64 + odemex/Examples/ifExample.m | 53 + odemex/Examples/interpolationExample.m | 88 + odemex/Examples/obsTest.m | 93 + odemex/Examples/sens1.m | 90 + odemex/Examples/sens2.m | 76 + odemex/Examples/sens3.m | 131 + odemex/Instructions.pdf | Bin 0 -> 339824 bytes odemex/MATLAB_models/addTwo.m | 30 + odemex/MATLAB_models/goodwin5.m | 26 + odemex/MATLAB_models/goodwinN.m | 15 + odemex/MATLAB_models/mymodel1.m | 33 + odemex/MATLAB_models/mymodel2.m | 44 + odemex/MATLAB_models/mymodel3.m | 37 + odemex/MATLAB_models/mymodel4.m | 43 + odemex/Parser/CVode/chooseCompiler.m | 164 + odemex/Parser/CVode/cv_src/include/cvodes.h | 1968 ++++ .../CVode/cv_src/include/cvodes/cvodes.h | 1968 ++++ .../CVode/cv_src/include/cvodes/cvodes_band.h | 72 + .../cv_src/include/cvodes/cvodes_bandpre.h | 179 + .../cv_src/include/cvodes/cvodes_bbdpre.h | 331 + .../cv_src/include/cvodes/cvodes_dense.h | 64 + .../CVode/cv_src/include/cvodes/cvodes_diag.h | 140 + .../cv_src/include/cvodes/cvodes_direct.h | 366 + .../cv_src/include/cvodes/cvodes_lapack.h | 103 + .../cv_src/include/cvodes/cvodes_spbcgs.h | 87 + .../cv_src/include/cvodes/cvodes_spgmr.h | 88 + .../cv_src/include/cvodes/cvodes_spils.h | 450 + .../cv_src/include/cvodes/cvodes_sptfqmr.h | 88 + .../Parser/CVode/cv_src/include/cvodes_band.h | 72 + .../CVode/cv_src/include/cvodes_bandpre.h | 179 + .../CVode/cv_src/include/cvodes_bbdpre.h | 331 + .../CVode/cv_src/include/cvodes_dense.h | 64 + .../Parser/CVode/cv_src/include/cvodes_diag.h | 140 + .../CVode/cv_src/include/cvodes_direct.h | 366 + .../CVode/cv_src/include/cvodes_lapack.h | 103 + .../CVode/cv_src/include/cvodes_spbcgs.h | 87 + .../CVode/cv_src/include/cvodes_spgmr.h | 88 + .../CVode/cv_src/include/cvodes_spils.h | 450 + .../CVode/cv_src/include/cvodes_sptfqmr.h | 88 + .../cv_src/include/nvector/nvector_parallel.h | 314 + .../cv_src/include/nvector/nvector_serial.h | 265 + .../CVode/cv_src/include/nvector_serial.h | 265 + .../cv_src/include/sundials/sundials_band.h | 153 + .../cv_src/include/sundials/sundials_config.h | 80 + .../include/sundials/sundials_config.in | 78 + .../cv_src/include/sundials/sundials_dense.h | 187 + .../cv_src/include/sundials/sundials_direct.h | 323 + .../include/sundials/sundials_fnvector.h | 41 + .../include/sundials/sundials_iterative.h | 242 + .../cv_src/include/sundials/sundials_lapack.h | 126 + .../cv_src/include/sundials/sundials_math.h | 139 + .../include/sundials/sundials_nvector.h | 373 + .../cv_src/include/sundials/sundials_spbcgs.h | 199 + .../cv_src/include/sundials/sundials_spgmr.h | 296 + .../include/sundials/sundials_sptfqmr.h | 254 + .../cv_src/include/sundials/sundials_types.h | 122 + .../CVode/cv_src/include/sundials/winDefine.h | 44 + .../CVode/cv_src/include/sundials_band.h | 153 + .../CVode/cv_src/include/sundials_config.in | 78 + .../CVode/cv_src/include/sundials_dense.h | 187 + .../CVode/cv_src/include/sundials_direct.h | 323 + .../CVode/cv_src/include/sundials_fnvector.h | 41 + .../CVode/cv_src/include/sundials_iterative.h | 242 + .../CVode/cv_src/include/sundials_lapack.h | 126 + .../CVode/cv_src/include/sundials_math.h | 139 + .../CVode/cv_src/include/sundials_nvector.h | 373 + .../CVode/cv_src/include/sundials_spbcgs.h | 199 + .../CVode/cv_src/include/sundials_spgmr.h | 296 + .../CVode/cv_src/include/sundials_sptfqmr.h | 254 + .../CVode/cv_src/include/sundials_types.h | 122 + .../CVode/cv_src/src/cvodes/CMakeLists.txt | 131 + odemex/Parser/CVode/cv_src/src/cvodes/LICENSE | 59 + .../CVode/cv_src/src/cvodes/Makefile.in | 180 + odemex/Parser/CVode/cv_src/src/cvodes/README | 431 + .../Parser/CVode/cv_src/src/cvodes/cvodea.c | 2967 ++++++ .../CVode/cv_src/src/cvodes/cvodea_io.c | 716 ++ .../Parser/CVode/cv_src/src/cvodes/cvodes.c | 9026 +++++++++++++++++ .../CVode/cv_src/src/cvodes/cvodes_band.c | 458 + .../CVode/cv_src/src/cvodes/cvodes_bandpre.c | 544 + .../cv_src/src/cvodes/cvodes_bandpre_impl.h | 77 + .../CVode/cv_src/src/cvodes/cvodes_bbdpre.c | 784 ++ .../cv_src/src/cvodes/cvodes_bbdpre_impl.h | 102 + .../CVode/cv_src/src/cvodes/cvodes_dense.c | 438 + .../CVode/cv_src/src/cvodes/cvodes_diag.c | 507 + .../cv_src/src/cvodes/cvodes_diag_impl.h | 68 + .../CVode/cv_src/src/cvodes/cvodes_direct.c | 711 ++ .../cv_src/src/cvodes/cvodes_direct_impl.h | 153 + .../CVode/cv_src/src/cvodes/cvodes_impl.h | 1089 ++ .../CVode/cv_src/src/cvodes/cvodes_io.c | 1877 ++++ .../CVode/cv_src/src/cvodes/cvodes_lapack.c | 808 ++ .../CVode/cv_src/src/cvodes/cvodes_spbcgs.c | 571 ++ .../CVode/cv_src/src/cvodes/cvodes_spgmr.c | 577 ++ .../CVode/cv_src/src/cvodes/cvodes_spils.c | 1182 +++ .../cv_src/src/cvodes/cvodes_spils_impl.h | 183 + .../CVode/cv_src/src/cvodes/cvodes_sptfqmr.c | 568 ++ .../CVode/cv_src/src/nvec_par/CMakeLists.txt | 89 + .../CVode/cv_src/src/nvec_par/Makefile.in | 128 + .../Parser/CVode/cv_src/src/nvec_par/README | 135 + .../cv_src/src/nvec_par/fnvector_parallel.c | 182 + .../cv_src/src/nvec_par/fnvector_parallel.h | 88 + .../cv_src/src/nvec_par/nvector_parallel.c | 1152 +++ .../CVode/cv_src/src/nvec_ser/CMakeLists.txt | 82 + .../CVode/cv_src/src/nvec_ser/Makefile.in | 125 + .../Parser/CVode/cv_src/src/nvec_ser/README | 131 + .../cv_src/src/nvec_ser/fnvector_serial.c | 147 + .../cv_src/src/nvec_ser/fnvector_serial.h | 84 + .../cv_src/src/nvec_ser/nvector_serial.c | 1034 ++ .../CVode/cv_src/src/sundials/CMakeLists.txt | 45 + .../CVode/cv_src/src/sundials/Makefile.in | 137 + .../Parser/CVode/cv_src/src/sundials/README | 201 + .../CVode/cv_src/src/sundials/sundials_band.c | 235 + .../cv_src/src/sundials/sundials_dense.c | 373 + .../cv_src/src/sundials/sundials_direct.c | 331 + .../cv_src/src/sundials/sundials_iterative.c | 288 + .../CVode/cv_src/src/sundials/sundials_math.c | 94 + .../cv_src/src/sundials/sundials_nvector.c | 233 + .../cv_src/src/sundials/sundials_spbcgs.c | 379 + .../cv_src/src/sundials/sundials_spgmr.c | 458 + .../cv_src/src/sundials/sundials_sptfqmr.c | 516 + odemex/Parser/CVode/ida_src/include/ida.h | 944 ++ odemex/Parser/CVode/ida_src/include/ida/ida.h | 944 ++ .../CVode/ida_src/include/ida/ida_band.h | 59 + .../CVode/ida_src/include/ida/ida_bbdpre.h | 275 + .../CVode/ida_src/include/ida/ida_dense.h | 58 + .../CVode/ida_src/include/ida/ida_direct.h | 300 + .../CVode/ida_src/include/ida/ida_lapack.h | 80 + .../CVode/ida_src/include/ida/ida_spbcgs.h | 59 + .../CVode/ida_src/include/ida/ida_spgmr.h | 60 + .../CVode/ida_src/include/ida/ida_spils.h | 321 + .../CVode/ida_src/include/ida/ida_sptfqmr.h | 59 + .../Parser/CVode/ida_src/include/ida_band.h | 59 + .../Parser/CVode/ida_src/include/ida_bbdpre.h | 275 + .../Parser/CVode/ida_src/include/ida_dense.h | 58 + .../Parser/CVode/ida_src/include/ida_direct.h | 300 + .../Parser/CVode/ida_src/include/ida_lapack.h | 80 + .../Parser/CVode/ida_src/include/ida_spbcgs.h | 59 + .../Parser/CVode/ida_src/include/ida_spgmr.h | 60 + .../Parser/CVode/ida_src/include/ida_spils.h | 321 + .../CVode/ida_src/include/ida_sptfqmr.h | 59 + .../include/nvector/nvector_parallel.h | 314 + .../ida_src/include/nvector/nvector_serial.h | 265 + .../ida_src/include/sundials/sundials_band.h | 153 + .../include/sundials/sundials_config.h | 80 + .../include/sundials/sundials_config.in | 78 + .../ida_src/include/sundials/sundials_dense.h | 187 + .../include/sundials/sundials_direct.h | 323 + .../include/sundials/sundials_fnvector.h | 41 + .../include/sundials/sundials_iterative.h | 242 + .../include/sundials/sundials_lapack.h | 126 + .../ida_src/include/sundials/sundials_math.h | 139 + .../include/sundials/sundials_nvector.h | 373 + .../include/sundials/sundials_spbcgs.h | 199 + .../ida_src/include/sundials/sundials_spgmr.h | 296 + .../include/sundials/sundials_sptfqmr.h | 254 + .../ida_src/include/sundials/sundials_types.h | 122 + .../ida_src/include/sundials/winDefine.h | 44 + .../CVode/ida_src/src/ida/CMakeLists.txt | 125 + odemex/Parser/CVode/ida_src/src/ida/LICENSE | 59 + .../Parser/CVode/ida_src/src/ida/Makefile.in | 169 + odemex/Parser/CVode/ida_src/src/ida/README | 364 + .../ida_src/src/ida/fcmix/CMakeLists.txt | 43 + .../CVode/ida_src/src/ida/fcmix/Makefile.in | 123 + .../Parser/CVode/ida_src/src/ida/fcmix/fida.c | 751 ++ .../Parser/CVode/ida_src/src/ida/fcmix/fida.h | 716 ++ .../CVode/ida_src/src/ida/fcmix/fidaband.c | 117 + .../CVode/ida_src/src/ida/fcmix/fidabbd.c | 150 + .../CVode/ida_src/src/ida/fcmix/fidabbd.h | 333 + .../CVode/ida_src/src/ida/fcmix/fidadense.c | 115 + .../CVode/ida_src/src/ida/fcmix/fidaewt.c | 87 + .../CVode/ida_src/src/ida/fcmix/fidajtimes.c | 116 + .../CVode/ida_src/src/ida/fcmix/fidalapack.c | 53 + .../CVode/ida_src/src/ida/fcmix/fidalapband.c | 112 + .../ida_src/src/ida/fcmix/fidalapdense.c | 111 + .../CVode/ida_src/src/ida/fcmix/fidapreco.c | 159 + .../CVode/ida_src/src/ida/fcmix/fidaroot.c | 88 + .../CVode/ida_src/src/ida/fcmix/fidaroot.h | 142 + odemex/Parser/CVode/ida_src/src/ida/ida.c | 3339 ++++++ .../Parser/CVode/ida_src/src/ida/ida_band.c | 320 + .../Parser/CVode/ida_src/src/ida/ida_bbdpre.c | 584 ++ .../CVode/ida_src/src/ida/ida_bbdpre_impl.h | 88 + .../Parser/CVode/ida_src/src/ida/ida_dense.c | 301 + .../Parser/CVode/ida_src/src/ida/ida_direct.c | 546 + .../CVode/ida_src/src/ida/ida_direct_impl.h | 100 + odemex/Parser/CVode/ida_src/src/ida/ida_ic.c | 728 ++ .../Parser/CVode/ida_src/src/ida/ida_impl.h | 483 + odemex/Parser/CVode/ida_src/src/ida/ida_io.c | 1152 +++ .../Parser/CVode/ida_src/src/ida/ida_lapack.c | 543 + .../Parser/CVode/ida_src/src/ida/ida_spbcgs.c | 476 + .../Parser/CVode/ida_src/src/ida/ida_spgmr.c | 475 + .../Parser/CVode/ida_src/src/ida/ida_spils.c | 637 ++ .../CVode/ida_src/src/ida/ida_spils_impl.h | 188 + .../CVode/ida_src/src/ida/ida_sptfqmr.c | 477 + .../CVode/ida_src/src/nvec_par/CMakeLists.txt | 89 + .../CVode/ida_src/src/nvec_par/Makefile.in | 128 + .../Parser/CVode/ida_src/src/nvec_par/README | 135 + .../ida_src/src/nvec_par/fnvector_parallel.c | 182 + .../ida_src/src/nvec_par/fnvector_parallel.h | 88 + .../ida_src/src/nvec_par/nvector_parallel.c | 1152 +++ .../CVode/ida_src/src/nvec_ser/CMakeLists.txt | 82 + .../CVode/ida_src/src/nvec_ser/Makefile.in | 125 + .../Parser/CVode/ida_src/src/nvec_ser/README | 131 + .../ida_src/src/nvec_ser/fnvector_serial.c | 147 + .../ida_src/src/nvec_ser/fnvector_serial.h | 84 + .../ida_src/src/nvec_ser/nvector_serial.c | 1034 ++ .../CVode/ida_src/src/sundials/CMakeLists.txt | 45 + .../CVode/ida_src/src/sundials/Makefile.in | 137 + .../Parser/CVode/ida_src/src/sundials/README | 201 + .../ida_src/src/sundials/sundials_band.c | 235 + .../ida_src/src/sundials/sundials_dense.c | 373 + .../ida_src/src/sundials/sundials_direct.c | 331 + .../ida_src/src/sundials/sundials_iterative.c | 288 + .../ida_src/src/sundials/sundials_math.c | 94 + .../ida_src/src/sundials/sundials_nvector.c | 233 + .../ida_src/src/sundials/sundials_spbcgs.c | 379 + .../ida_src/src/sundials/sundials_spgmr.c | 458 + .../ida_src/src/sundials/sundials_sptfqmr.c | 516 + odemex/Parser/CVode/lib/CVODE.lib | Bin 0 -> 738340 bytes odemex/Parser/CVode/setupCVode.m | 170 + odemex/Parser/CVode/setupIDA.m | 154 + odemex/Parser/cParserSet.m | 135 + odemex/Parser/compileC.m | 75 + odemex/Parser/convertToC.m | 535 + odemex/Parser/convertToC_IDA.m | 445 + odemex/Parser/outputC/dxdt.h | 40 + odemex/Parser/outputC/mexG.c | 473 + odemex/Parser/outputC/model/aJac.c | 50 + odemex/Parser/outputC/model/dxdt.c | 154 + odemex/Parser/outputC/model/dxdtDefs.h | 15 + odemex/Parser/outputC/ode.c | 225 + odemex/Parser/outputC/ode.h | 74 + odemex/Parser/outputC_IDA/dxdt.h | 39 + odemex/Parser/outputC_IDA/mexG.c | 340 + odemex/Parser/outputC_IDA/ode.c | 204 + odemex/Parser/outputC_IDA/ode.h | 73 + .../Parser/parserDependencies/Interpolate.m | 28 + .../analyseFunctionHeader.m | 59 + odemex/Parser/parserDependencies/dec1.m | 41 + .../parserDependencies/grabBetweenBrackets.m | 58 + .../parserDependencies/grabFieldNames.m | 31 + .../Parser/parserDependencies/grabIndices.m | 33 + odemex/Parser/parserDependencies/intPow.m | 30 + odemex/Parser/parserDependencies/jacGen1.m | 125 + odemex/Parser/parserDependencies/maximum.m | 29 + odemex/Parser/parserDependencies/minimum.m | 29 + odemex/Parser/parserDependencies/pow.m | 30 + odemex/Parser/parserDependencies/printList.m | 39 + .../parserDependencies/printUniqueList.m | 60 + .../parserDependencies/replaceStructNames.m | 35 + odemex/Parser/parserDependencies/sortList.m | 40 + odemex/Parser/parserDependencies/strtok2.m | 41 + odemex/SBML Tools/SBMLtoM.m | 260 + odemex/SBML Tools/avoidIntegerDivision.m | 24 + odemex/SBML Tools/strtok2.m | 13 + odemex/SBML_Files/HIF_4.xml | 226 + odemex/SBML_Files/model.xml | 806 ++ odemex/addPaths.m | 52 + odemex/observerFunctions/ccode/jac.c | 289 + odemex/observerFunctions/ccode/jac.h | 4 + odemex/observerFunctions/ccode/objfn.c | 72 + odemex/observerFunctions/ccode/objfn.h | 15 + odemex/observerFunctions/ccode/wrap.c | 74 + odemex/observerFunctions/compileObjective.m | 36 + odemex/observerFunctions/grabNextBracket.m | 59 + .../observerFunctions/grabNextDataBracket.m | 59 + odemex/observerFunctions/nJac.m | 40 + odemex/observerFunctions/observerFunctions.m | 344 + odemex/observerFunctions/printAsString.m | 37 + odemex/observerFunctions/replaceWithIndex.m | 45 + odemex/observerFunctions/strtok2.m | 41 + odemex/observerFunctions/structIndices.m | 34 + odemex/observerFunctions/useObserver.m | 9 + setup.m | 11 + temp/C_tiemannModel_ODE.m | 129 + temp/C_tiemannModel_ODEC.mexw64 | Bin 0 -> 103424 bytes temp/C_tiemannModel_ODEMEX.m | 129 + temp/C_tiemannModel_REACTIONS.m | 176 + 441 files changed, 87503 insertions(+) create mode 100644 +AMF/+utils/defineCustomColormap.m create mode 100644 +AMF/+utils/getHist.m create mode 100644 +AMF/+utils/mexify.m create mode 100644 +AMF/+utils/mexify2.m create mode 100644 +AMF/+utils/parfor_progress.m create mode 100644 +AMF/+utils/parfor_progress2.m create mode 100644 +AMF/+utils/writeFile.m create mode 100644 +AMF/+visualisation/define_custom_colormap.m create mode 100644 +AMF/+visualisation/define_figure_details.m create mode 100644 +AMF/+visualisation/errorbar_tick.m create mode 100644 +AMF/+visualisation/plot_results.m create mode 100644 +AMF/+visualisation/save_figure_to_file.m create mode 100644 +AMF/@DataComponent/DataComponent.m create mode 100644 +AMF/@DataComponent/filter.m create mode 100644 +AMF/@DataComponent/getStruct.m create mode 100644 +AMF/@DataComponent/isConstant.m create mode 100644 +AMF/@DataComponent/isObservable.m create mode 100644 +AMF/@DataComponent/plot.m create mode 100644 +AMF/@DataField/DataField.m create mode 100644 +AMF/@DataField/genSpline.m create mode 100644 +AMF/@DataField/interp.m create mode 100644 +AMF/@DataField/interpLinear.m create mode 100644 +AMF/@DataField/interpSpline.m create mode 100644 +AMF/@DataField/randomize.m create mode 100644 +AMF/@DataField/restore.m create mode 100644 +AMF/@DataFunction/DataFunction.m create mode 100644 +AMF/@DataSet/DataSet.m create mode 100644 +AMF/@DataSet/compileFunctions.m create mode 100644 +AMF/@DataSet/filter.m create mode 100644 +AMF/@DataSet/get.m create mode 100644 +AMF/@DataSet/getDataStruct.m create mode 100644 +AMF/@DataSet/getFitData.m create mode 100644 +AMF/@DataSet/getFitTime.m create mode 100644 +AMF/@DataSet/getInterpData.m create mode 100644 +AMF/@DataSet/interp.m create mode 100644 +AMF/@DataSet/loadGroup.m create mode 100644 +AMF/@DataSet/parseFields.m create mode 100644 +AMF/@DataSet/parseFunctions.m create mode 100644 +AMF/@DataSet/randomize.m create mode 100644 +AMF/@GridUI/GridUI.m create mode 100644 +AMF/@GridUI/draw.m create mode 100644 +AMF/@GridUI/render.m create mode 100644 +AMF/@GridUI/renderAxes.m create mode 100644 +AMF/@GridUI/renderControl.m create mode 100644 +AMF/@GridUI/renderEdit.m create mode 100644 +AMF/@GridUI/renderListBox.m create mode 100644 +AMF/@GridUI/size.m create mode 100644 +AMF/@Model/Model.m create mode 100644 +AMF/@Model/addComponents.m create mode 100644 +AMF/@Model/compile.m create mode 100644 +AMF/@Model/compileAll.m create mode 100644 +AMF/@Model/compileInputs.m create mode 100644 +AMF/@Model/compileMex.m create mode 100644 +AMF/@Model/compileODE.m create mode 100644 +AMF/@Model/compileODEMex.m create mode 100644 +AMF/@Model/compileReactions.m create mode 100644 +AMF/@Model/computeAll.m create mode 100644 +AMF/@Model/computeInputs.m create mode 100644 +AMF/@Model/computeReactions.m create mode 100644 +AMF/@Model/computeStates.m create mode 100644 +AMF/@Model/filter.m create mode 100644 +AMF/@Model/get.m create mode 100644 +AMF/@Model/getAll.m create mode 100644 +AMF/@Model/getInputStruct.m create mode 100644 +AMF/@Model/getInputStructMex.m create mode 100644 +AMF/@Model/getInputsMex.m create mode 100644 +AMF/@Model/getResiduals.m create mode 100644 +AMF/@Model/getResult.m create mode 100644 +AMF/@Model/getTime.m create mode 100644 +AMF/@Model/initializeObservables.m create mode 100644 +AMF/@Model/initiateExperiment.asv create mode 100644 +AMF/@Model/initiateExperiment.m create mode 100644 +AMF/@Model/parseAll.m create mode 100644 +AMF/@Model/parseConstants.m create mode 100644 +AMF/@Model/parseInputs.m create mode 100644 +AMF/@Model/parseParameters.m create mode 100644 +AMF/@Model/parseReactions.m create mode 100644 +AMF/@Model/parseStates.m create mode 100644 +AMF/@Model/plot.m create mode 100644 +AMF/@Model/plotAll.m create mode 100644 +AMF/@Model/randomizeData.m create mode 100644 +AMF/@Model/randomizeParameters.m create mode 100644 +AMF/@Model/saveTrajectory.m create mode 100644 +AMF/@Model/setFitParameters.m create mode 100644 +AMF/@Model/setPredictor.m create mode 100644 +AMF/@Model/setTimeStep.m create mode 100644 +AMF/@ModelComponent/ModelComponent.m create mode 100644 +AMF/@ModelComponent/filter.m create mode 100644 +AMF/@ModelComponent/getStruct.m create mode 100644 +AMF/@ModelComponent/isObservable.m create mode 100644 +AMF/@ModelComponent/plot.m create mode 100644 +AMF/@ModelConstant/ModelConstant.m create mode 100644 +AMF/@ModelInput/ModelInput.m create mode 100644 +AMF/@ModelParameter/ModelParameter.m create mode 100644 +AMF/@ModelParameter/isFitParameter.m create mode 100644 +AMF/@ModelPredictor/ModelPredictor.m create mode 100644 +AMF/@ModelReaction/@ModelResult/ModelResult.m create mode 100644 +AMF/@ModelReaction/@ModelResult/plotStates.m create mode 100644 +AMF/@ModelReaction/@ModelResult/plot_hist.m create mode 100644 +AMF/@ModelReaction/@ModelResult/plot_states.m create mode 100644 +AMF/@ModelReaction/@ModelResult/plot_states_norm.m create mode 100644 +AMF/@ModelReaction/@ModelResult/plot_traj.m create mode 100644 +AMF/@ModelReaction/@ModelResult/test.m create mode 100644 +AMF/@ModelReaction/ModelReaction.m create mode 100644 +AMF/@ModelResult/ModelResult.m create mode 100644 +AMF/@ModelResult/getColorProfile.m create mode 100644 +AMF/@ModelResult/getValue.m create mode 100644 +AMF/@ModelResult/plot.m create mode 100644 +AMF/@ModelResult/plotAll.m create mode 100644 +AMF/@ModelResult/plotHist.m create mode 100644 +AMF/@ModelResult/plotTraj.m create mode 100644 +AMF/@ModelState/ModelState.m create mode 100644 +AMF/createDataset.m create mode 100644 +AMF/fit.m create mode 100644 +AMF/fitTimeStep.m create mode 100644 +AMF/manipulate.m create mode 100644 +AMF/proflik.m create mode 100644 +AMF/regFun.m create mode 100644 +AMF/runADAPT.asv create mode 100644 +AMF/runADAPT.m create mode 100644 +AMF/simulate.m create mode 100644 README.MD create mode 100644 README.TXT create mode 100644 manual.docx create mode 100644 manual.pdf create mode 100644 models/bariatricData.m create mode 100644 models/bariatricData.mat create mode 100644 models/bariatricData_basal.m create mode 100644 models/minCPepModel/minCPepData.m create mode 100644 models/minCPepModel/minCPepModel.m create mode 100644 models/minCPepModel/minCPepModel2.m create mode 100644 models/minCPepModel/minCPepReg.m create mode 100644 models/minCPepModel/runMinCPep.asv create mode 100644 models/minCPepModel/runMinCPep.m create mode 100644 models/minCPepModel/runMinCPep2.m create mode 100644 models/minGlucModel/minGlucData.m create mode 100644 models/minGlucModel/minGlucModel.m create mode 100644 models/minGlucModel/minGlucReg.m create mode 100644 models/minGlucModel/runMinGluc.m create mode 100644 models/minGlucModel2/minGlucData2.m create mode 100644 models/minGlucModel2/minGlucModel2.m create mode 100644 models/minGlucModel2/runMinGluc2.m create mode 100644 models/minModel/minData.m create mode 100644 models/minModel/minModel.m create mode 100644 models/minModel/minModel2.m create mode 100644 models/minModel/minReg.m create mode 100644 models/minModel/runMin.m create mode 100644 models/minModel/runMin2.m create mode 100644 models/tiemannModel/dat.m create mode 100644 models/tiemannModel/data_Oosterveer.mat create mode 100644 models/tiemannModel/runTiemann.m create mode 100644 models/tiemannModel/tiemannData.m create mode 100644 models/tiemannModel/tiemannData.mat create mode 100644 models/tiemannModel/tiemannModel.m create mode 100644 models/tiemannModel/tiemannReg.m create mode 100644 models/toyModel/runToy.m create mode 100644 models/toyModel/toyData.m create mode 100644 models/toyModel/toyData.mat create mode 100644 models/toyModel/toyModel.m create mode 100644 models/toyModel/toyReg.m create mode 100644 odemex/COPYING create mode 100644 odemex/Examples/SBMLexample.m create mode 100644 odemex/Examples/example.m create mode 100644 odemex/Examples/fitExample.m create mode 100644 odemex/Examples/goodwin.m create mode 100644 odemex/Examples/ifExample.m create mode 100644 odemex/Examples/interpolationExample.m create mode 100644 odemex/Examples/obsTest.m create mode 100644 odemex/Examples/sens1.m create mode 100644 odemex/Examples/sens2.m create mode 100644 odemex/Examples/sens3.m create mode 100644 odemex/Instructions.pdf create mode 100644 odemex/MATLAB_models/addTwo.m create mode 100644 odemex/MATLAB_models/goodwin5.m create mode 100644 odemex/MATLAB_models/goodwinN.m create mode 100644 odemex/MATLAB_models/mymodel1.m create mode 100644 odemex/MATLAB_models/mymodel2.m create mode 100644 odemex/MATLAB_models/mymodel3.m create mode 100644 odemex/MATLAB_models/mymodel4.m create mode 100644 odemex/Parser/CVode/chooseCompiler.m create mode 100644 odemex/Parser/CVode/cv_src/include/cvodes.h create mode 100644 odemex/Parser/CVode/cv_src/include/cvodes/cvodes.h create mode 100644 odemex/Parser/CVode/cv_src/include/cvodes/cvodes_band.h create mode 100644 odemex/Parser/CVode/cv_src/include/cvodes/cvodes_bandpre.h create mode 100644 odemex/Parser/CVode/cv_src/include/cvodes/cvodes_bbdpre.h create mode 100644 odemex/Parser/CVode/cv_src/include/cvodes/cvodes_dense.h create mode 100644 odemex/Parser/CVode/cv_src/include/cvodes/cvodes_diag.h create mode 100644 odemex/Parser/CVode/cv_src/include/cvodes/cvodes_direct.h create mode 100644 odemex/Parser/CVode/cv_src/include/cvodes/cvodes_lapack.h create mode 100644 odemex/Parser/CVode/cv_src/include/cvodes/cvodes_spbcgs.h create mode 100644 odemex/Parser/CVode/cv_src/include/cvodes/cvodes_spgmr.h create mode 100644 odemex/Parser/CVode/cv_src/include/cvodes/cvodes_spils.h create mode 100644 odemex/Parser/CVode/cv_src/include/cvodes/cvodes_sptfqmr.h create mode 100644 odemex/Parser/CVode/cv_src/include/cvodes_band.h create mode 100644 odemex/Parser/CVode/cv_src/include/cvodes_bandpre.h create mode 100644 odemex/Parser/CVode/cv_src/include/cvodes_bbdpre.h create mode 100644 odemex/Parser/CVode/cv_src/include/cvodes_dense.h create mode 100644 odemex/Parser/CVode/cv_src/include/cvodes_diag.h create mode 100644 odemex/Parser/CVode/cv_src/include/cvodes_direct.h create mode 100644 odemex/Parser/CVode/cv_src/include/cvodes_lapack.h create mode 100644 odemex/Parser/CVode/cv_src/include/cvodes_spbcgs.h create mode 100644 odemex/Parser/CVode/cv_src/include/cvodes_spgmr.h create mode 100644 odemex/Parser/CVode/cv_src/include/cvodes_spils.h create mode 100644 odemex/Parser/CVode/cv_src/include/cvodes_sptfqmr.h create mode 100644 odemex/Parser/CVode/cv_src/include/nvector/nvector_parallel.h create mode 100644 odemex/Parser/CVode/cv_src/include/nvector/nvector_serial.h create mode 100644 odemex/Parser/CVode/cv_src/include/nvector_serial.h create mode 100644 odemex/Parser/CVode/cv_src/include/sundials/sundials_band.h create mode 100644 odemex/Parser/CVode/cv_src/include/sundials/sundials_config.h create mode 100644 odemex/Parser/CVode/cv_src/include/sundials/sundials_config.in create mode 100644 odemex/Parser/CVode/cv_src/include/sundials/sundials_dense.h create mode 100644 odemex/Parser/CVode/cv_src/include/sundials/sundials_direct.h create mode 100644 odemex/Parser/CVode/cv_src/include/sundials/sundials_fnvector.h create mode 100644 odemex/Parser/CVode/cv_src/include/sundials/sundials_iterative.h create mode 100644 odemex/Parser/CVode/cv_src/include/sundials/sundials_lapack.h create mode 100644 odemex/Parser/CVode/cv_src/include/sundials/sundials_math.h create mode 100644 odemex/Parser/CVode/cv_src/include/sundials/sundials_nvector.h create mode 100644 odemex/Parser/CVode/cv_src/include/sundials/sundials_spbcgs.h create mode 100644 odemex/Parser/CVode/cv_src/include/sundials/sundials_spgmr.h create mode 100644 odemex/Parser/CVode/cv_src/include/sundials/sundials_sptfqmr.h create mode 100644 odemex/Parser/CVode/cv_src/include/sundials/sundials_types.h create mode 100644 odemex/Parser/CVode/cv_src/include/sundials/winDefine.h create mode 100644 odemex/Parser/CVode/cv_src/include/sundials_band.h create mode 100644 odemex/Parser/CVode/cv_src/include/sundials_config.in create mode 100644 odemex/Parser/CVode/cv_src/include/sundials_dense.h create mode 100644 odemex/Parser/CVode/cv_src/include/sundials_direct.h create mode 100644 odemex/Parser/CVode/cv_src/include/sundials_fnvector.h create mode 100644 odemex/Parser/CVode/cv_src/include/sundials_iterative.h create mode 100644 odemex/Parser/CVode/cv_src/include/sundials_lapack.h create mode 100644 odemex/Parser/CVode/cv_src/include/sundials_math.h create mode 100644 odemex/Parser/CVode/cv_src/include/sundials_nvector.h create mode 100644 odemex/Parser/CVode/cv_src/include/sundials_spbcgs.h create mode 100644 odemex/Parser/CVode/cv_src/include/sundials_spgmr.h create mode 100644 odemex/Parser/CVode/cv_src/include/sundials_sptfqmr.h create mode 100644 odemex/Parser/CVode/cv_src/include/sundials_types.h create mode 100644 odemex/Parser/CVode/cv_src/src/cvodes/CMakeLists.txt create mode 100644 odemex/Parser/CVode/cv_src/src/cvodes/LICENSE create mode 100644 odemex/Parser/CVode/cv_src/src/cvodes/Makefile.in create mode 100644 odemex/Parser/CVode/cv_src/src/cvodes/README create mode 100644 odemex/Parser/CVode/cv_src/src/cvodes/cvodea.c create mode 100644 odemex/Parser/CVode/cv_src/src/cvodes/cvodea_io.c create mode 100644 odemex/Parser/CVode/cv_src/src/cvodes/cvodes.c create mode 100644 odemex/Parser/CVode/cv_src/src/cvodes/cvodes_band.c create mode 100644 odemex/Parser/CVode/cv_src/src/cvodes/cvodes_bandpre.c create mode 100644 odemex/Parser/CVode/cv_src/src/cvodes/cvodes_bandpre_impl.h create mode 100644 odemex/Parser/CVode/cv_src/src/cvodes/cvodes_bbdpre.c create mode 100644 odemex/Parser/CVode/cv_src/src/cvodes/cvodes_bbdpre_impl.h create mode 100644 odemex/Parser/CVode/cv_src/src/cvodes/cvodes_dense.c create mode 100644 odemex/Parser/CVode/cv_src/src/cvodes/cvodes_diag.c create mode 100644 odemex/Parser/CVode/cv_src/src/cvodes/cvodes_diag_impl.h create mode 100644 odemex/Parser/CVode/cv_src/src/cvodes/cvodes_direct.c create mode 100644 odemex/Parser/CVode/cv_src/src/cvodes/cvodes_direct_impl.h create mode 100644 odemex/Parser/CVode/cv_src/src/cvodes/cvodes_impl.h create mode 100644 odemex/Parser/CVode/cv_src/src/cvodes/cvodes_io.c create mode 100644 odemex/Parser/CVode/cv_src/src/cvodes/cvodes_lapack.c create mode 100644 odemex/Parser/CVode/cv_src/src/cvodes/cvodes_spbcgs.c create mode 100644 odemex/Parser/CVode/cv_src/src/cvodes/cvodes_spgmr.c create mode 100644 odemex/Parser/CVode/cv_src/src/cvodes/cvodes_spils.c create mode 100644 odemex/Parser/CVode/cv_src/src/cvodes/cvodes_spils_impl.h create mode 100644 odemex/Parser/CVode/cv_src/src/cvodes/cvodes_sptfqmr.c create mode 100644 odemex/Parser/CVode/cv_src/src/nvec_par/CMakeLists.txt create mode 100644 odemex/Parser/CVode/cv_src/src/nvec_par/Makefile.in create mode 100644 odemex/Parser/CVode/cv_src/src/nvec_par/README create mode 100644 odemex/Parser/CVode/cv_src/src/nvec_par/fnvector_parallel.c create mode 100644 odemex/Parser/CVode/cv_src/src/nvec_par/fnvector_parallel.h create mode 100644 odemex/Parser/CVode/cv_src/src/nvec_par/nvector_parallel.c create mode 100644 odemex/Parser/CVode/cv_src/src/nvec_ser/CMakeLists.txt create mode 100644 odemex/Parser/CVode/cv_src/src/nvec_ser/Makefile.in create mode 100644 odemex/Parser/CVode/cv_src/src/nvec_ser/README create mode 100644 odemex/Parser/CVode/cv_src/src/nvec_ser/fnvector_serial.c create mode 100644 odemex/Parser/CVode/cv_src/src/nvec_ser/fnvector_serial.h create mode 100644 odemex/Parser/CVode/cv_src/src/nvec_ser/nvector_serial.c create mode 100644 odemex/Parser/CVode/cv_src/src/sundials/CMakeLists.txt create mode 100644 odemex/Parser/CVode/cv_src/src/sundials/Makefile.in create mode 100644 odemex/Parser/CVode/cv_src/src/sundials/README create mode 100644 odemex/Parser/CVode/cv_src/src/sundials/sundials_band.c create mode 100644 odemex/Parser/CVode/cv_src/src/sundials/sundials_dense.c create mode 100644 odemex/Parser/CVode/cv_src/src/sundials/sundials_direct.c create mode 100644 odemex/Parser/CVode/cv_src/src/sundials/sundials_iterative.c create mode 100644 odemex/Parser/CVode/cv_src/src/sundials/sundials_math.c create mode 100644 odemex/Parser/CVode/cv_src/src/sundials/sundials_nvector.c create mode 100644 odemex/Parser/CVode/cv_src/src/sundials/sundials_spbcgs.c create mode 100644 odemex/Parser/CVode/cv_src/src/sundials/sundials_spgmr.c create mode 100644 odemex/Parser/CVode/cv_src/src/sundials/sundials_sptfqmr.c create mode 100644 odemex/Parser/CVode/ida_src/include/ida.h create mode 100644 odemex/Parser/CVode/ida_src/include/ida/ida.h create mode 100644 odemex/Parser/CVode/ida_src/include/ida/ida_band.h create mode 100644 odemex/Parser/CVode/ida_src/include/ida/ida_bbdpre.h create mode 100644 odemex/Parser/CVode/ida_src/include/ida/ida_dense.h create mode 100644 odemex/Parser/CVode/ida_src/include/ida/ida_direct.h create mode 100644 odemex/Parser/CVode/ida_src/include/ida/ida_lapack.h create mode 100644 odemex/Parser/CVode/ida_src/include/ida/ida_spbcgs.h create mode 100644 odemex/Parser/CVode/ida_src/include/ida/ida_spgmr.h create mode 100644 odemex/Parser/CVode/ida_src/include/ida/ida_spils.h create mode 100644 odemex/Parser/CVode/ida_src/include/ida/ida_sptfqmr.h create mode 100644 odemex/Parser/CVode/ida_src/include/ida_band.h create mode 100644 odemex/Parser/CVode/ida_src/include/ida_bbdpre.h create mode 100644 odemex/Parser/CVode/ida_src/include/ida_dense.h create mode 100644 odemex/Parser/CVode/ida_src/include/ida_direct.h create mode 100644 odemex/Parser/CVode/ida_src/include/ida_lapack.h create mode 100644 odemex/Parser/CVode/ida_src/include/ida_spbcgs.h create mode 100644 odemex/Parser/CVode/ida_src/include/ida_spgmr.h create mode 100644 odemex/Parser/CVode/ida_src/include/ida_spils.h create mode 100644 odemex/Parser/CVode/ida_src/include/ida_sptfqmr.h create mode 100644 odemex/Parser/CVode/ida_src/include/nvector/nvector_parallel.h create mode 100644 odemex/Parser/CVode/ida_src/include/nvector/nvector_serial.h create mode 100644 odemex/Parser/CVode/ida_src/include/sundials/sundials_band.h create mode 100644 odemex/Parser/CVode/ida_src/include/sundials/sundials_config.h create mode 100644 odemex/Parser/CVode/ida_src/include/sundials/sundials_config.in create mode 100644 odemex/Parser/CVode/ida_src/include/sundials/sundials_dense.h create mode 100644 odemex/Parser/CVode/ida_src/include/sundials/sundials_direct.h create mode 100644 odemex/Parser/CVode/ida_src/include/sundials/sundials_fnvector.h create mode 100644 odemex/Parser/CVode/ida_src/include/sundials/sundials_iterative.h create mode 100644 odemex/Parser/CVode/ida_src/include/sundials/sundials_lapack.h create mode 100644 odemex/Parser/CVode/ida_src/include/sundials/sundials_math.h create mode 100644 odemex/Parser/CVode/ida_src/include/sundials/sundials_nvector.h create mode 100644 odemex/Parser/CVode/ida_src/include/sundials/sundials_spbcgs.h create mode 100644 odemex/Parser/CVode/ida_src/include/sundials/sundials_spgmr.h create mode 100644 odemex/Parser/CVode/ida_src/include/sundials/sundials_sptfqmr.h create mode 100644 odemex/Parser/CVode/ida_src/include/sundials/sundials_types.h create mode 100644 odemex/Parser/CVode/ida_src/include/sundials/winDefine.h create mode 100644 odemex/Parser/CVode/ida_src/src/ida/CMakeLists.txt create mode 100644 odemex/Parser/CVode/ida_src/src/ida/LICENSE create mode 100644 odemex/Parser/CVode/ida_src/src/ida/Makefile.in create mode 100644 odemex/Parser/CVode/ida_src/src/ida/README create mode 100644 odemex/Parser/CVode/ida_src/src/ida/fcmix/CMakeLists.txt create mode 100644 odemex/Parser/CVode/ida_src/src/ida/fcmix/Makefile.in create mode 100644 odemex/Parser/CVode/ida_src/src/ida/fcmix/fida.c create mode 100644 odemex/Parser/CVode/ida_src/src/ida/fcmix/fida.h create mode 100644 odemex/Parser/CVode/ida_src/src/ida/fcmix/fidaband.c create mode 100644 odemex/Parser/CVode/ida_src/src/ida/fcmix/fidabbd.c create mode 100644 odemex/Parser/CVode/ida_src/src/ida/fcmix/fidabbd.h create mode 100644 odemex/Parser/CVode/ida_src/src/ida/fcmix/fidadense.c create mode 100644 odemex/Parser/CVode/ida_src/src/ida/fcmix/fidaewt.c create mode 100644 odemex/Parser/CVode/ida_src/src/ida/fcmix/fidajtimes.c create mode 100644 odemex/Parser/CVode/ida_src/src/ida/fcmix/fidalapack.c create mode 100644 odemex/Parser/CVode/ida_src/src/ida/fcmix/fidalapband.c create mode 100644 odemex/Parser/CVode/ida_src/src/ida/fcmix/fidalapdense.c create mode 100644 odemex/Parser/CVode/ida_src/src/ida/fcmix/fidapreco.c create mode 100644 odemex/Parser/CVode/ida_src/src/ida/fcmix/fidaroot.c create mode 100644 odemex/Parser/CVode/ida_src/src/ida/fcmix/fidaroot.h create mode 100644 odemex/Parser/CVode/ida_src/src/ida/ida.c create mode 100644 odemex/Parser/CVode/ida_src/src/ida/ida_band.c create mode 100644 odemex/Parser/CVode/ida_src/src/ida/ida_bbdpre.c create mode 100644 odemex/Parser/CVode/ida_src/src/ida/ida_bbdpre_impl.h create mode 100644 odemex/Parser/CVode/ida_src/src/ida/ida_dense.c create mode 100644 odemex/Parser/CVode/ida_src/src/ida/ida_direct.c create mode 100644 odemex/Parser/CVode/ida_src/src/ida/ida_direct_impl.h create mode 100644 odemex/Parser/CVode/ida_src/src/ida/ida_ic.c create mode 100644 odemex/Parser/CVode/ida_src/src/ida/ida_impl.h create mode 100644 odemex/Parser/CVode/ida_src/src/ida/ida_io.c create mode 100644 odemex/Parser/CVode/ida_src/src/ida/ida_lapack.c create mode 100644 odemex/Parser/CVode/ida_src/src/ida/ida_spbcgs.c create mode 100644 odemex/Parser/CVode/ida_src/src/ida/ida_spgmr.c create mode 100644 odemex/Parser/CVode/ida_src/src/ida/ida_spils.c create mode 100644 odemex/Parser/CVode/ida_src/src/ida/ida_spils_impl.h create mode 100644 odemex/Parser/CVode/ida_src/src/ida/ida_sptfqmr.c create mode 100644 odemex/Parser/CVode/ida_src/src/nvec_par/CMakeLists.txt create mode 100644 odemex/Parser/CVode/ida_src/src/nvec_par/Makefile.in create mode 100644 odemex/Parser/CVode/ida_src/src/nvec_par/README create mode 100644 odemex/Parser/CVode/ida_src/src/nvec_par/fnvector_parallel.c create mode 100644 odemex/Parser/CVode/ida_src/src/nvec_par/fnvector_parallel.h create mode 100644 odemex/Parser/CVode/ida_src/src/nvec_par/nvector_parallel.c create mode 100644 odemex/Parser/CVode/ida_src/src/nvec_ser/CMakeLists.txt create mode 100644 odemex/Parser/CVode/ida_src/src/nvec_ser/Makefile.in create mode 100644 odemex/Parser/CVode/ida_src/src/nvec_ser/README create mode 100644 odemex/Parser/CVode/ida_src/src/nvec_ser/fnvector_serial.c create mode 100644 odemex/Parser/CVode/ida_src/src/nvec_ser/fnvector_serial.h create mode 100644 odemex/Parser/CVode/ida_src/src/nvec_ser/nvector_serial.c create mode 100644 odemex/Parser/CVode/ida_src/src/sundials/CMakeLists.txt create mode 100644 odemex/Parser/CVode/ida_src/src/sundials/Makefile.in create mode 100644 odemex/Parser/CVode/ida_src/src/sundials/README create mode 100644 odemex/Parser/CVode/ida_src/src/sundials/sundials_band.c create mode 100644 odemex/Parser/CVode/ida_src/src/sundials/sundials_dense.c create mode 100644 odemex/Parser/CVode/ida_src/src/sundials/sundials_direct.c create mode 100644 odemex/Parser/CVode/ida_src/src/sundials/sundials_iterative.c create mode 100644 odemex/Parser/CVode/ida_src/src/sundials/sundials_math.c create mode 100644 odemex/Parser/CVode/ida_src/src/sundials/sundials_nvector.c create mode 100644 odemex/Parser/CVode/ida_src/src/sundials/sundials_spbcgs.c create mode 100644 odemex/Parser/CVode/ida_src/src/sundials/sundials_spgmr.c create mode 100644 odemex/Parser/CVode/ida_src/src/sundials/sundials_sptfqmr.c create mode 100644 odemex/Parser/CVode/lib/CVODE.lib create mode 100644 odemex/Parser/CVode/setupCVode.m create mode 100644 odemex/Parser/CVode/setupIDA.m create mode 100644 odemex/Parser/cParserSet.m create mode 100644 odemex/Parser/compileC.m create mode 100644 odemex/Parser/convertToC.m create mode 100644 odemex/Parser/convertToC_IDA.m create mode 100644 odemex/Parser/outputC/dxdt.h create mode 100644 odemex/Parser/outputC/mexG.c create mode 100644 odemex/Parser/outputC/model/aJac.c create mode 100644 odemex/Parser/outputC/model/dxdt.c create mode 100644 odemex/Parser/outputC/model/dxdtDefs.h create mode 100644 odemex/Parser/outputC/ode.c create mode 100644 odemex/Parser/outputC/ode.h create mode 100644 odemex/Parser/outputC_IDA/dxdt.h create mode 100644 odemex/Parser/outputC_IDA/mexG.c create mode 100644 odemex/Parser/outputC_IDA/ode.c create mode 100644 odemex/Parser/outputC_IDA/ode.h create mode 100644 odemex/Parser/parserDependencies/Interpolate.m create mode 100644 odemex/Parser/parserDependencies/analyseFunctionHeader.m create mode 100644 odemex/Parser/parserDependencies/dec1.m create mode 100644 odemex/Parser/parserDependencies/grabBetweenBrackets.m create mode 100644 odemex/Parser/parserDependencies/grabFieldNames.m create mode 100644 odemex/Parser/parserDependencies/grabIndices.m create mode 100644 odemex/Parser/parserDependencies/intPow.m create mode 100644 odemex/Parser/parserDependencies/jacGen1.m create mode 100644 odemex/Parser/parserDependencies/maximum.m create mode 100644 odemex/Parser/parserDependencies/minimum.m create mode 100644 odemex/Parser/parserDependencies/pow.m create mode 100644 odemex/Parser/parserDependencies/printList.m create mode 100644 odemex/Parser/parserDependencies/printUniqueList.m create mode 100644 odemex/Parser/parserDependencies/replaceStructNames.m create mode 100644 odemex/Parser/parserDependencies/sortList.m create mode 100644 odemex/Parser/parserDependencies/strtok2.m create mode 100644 odemex/SBML Tools/SBMLtoM.m create mode 100644 odemex/SBML Tools/avoidIntegerDivision.m create mode 100644 odemex/SBML Tools/strtok2.m create mode 100644 odemex/SBML_Files/HIF_4.xml create mode 100644 odemex/SBML_Files/model.xml create mode 100644 odemex/addPaths.m create mode 100644 odemex/observerFunctions/ccode/jac.c create mode 100644 odemex/observerFunctions/ccode/jac.h create mode 100644 odemex/observerFunctions/ccode/objfn.c create mode 100644 odemex/observerFunctions/ccode/objfn.h create mode 100644 odemex/observerFunctions/ccode/wrap.c create mode 100644 odemex/observerFunctions/compileObjective.m create mode 100644 odemex/observerFunctions/grabNextBracket.m create mode 100644 odemex/observerFunctions/grabNextDataBracket.m create mode 100644 odemex/observerFunctions/nJac.m create mode 100644 odemex/observerFunctions/observerFunctions.m create mode 100644 odemex/observerFunctions/printAsString.m create mode 100644 odemex/observerFunctions/replaceWithIndex.m create mode 100644 odemex/observerFunctions/strtok2.m create mode 100644 odemex/observerFunctions/structIndices.m create mode 100644 odemex/observerFunctions/useObserver.m create mode 100644 setup.m create mode 100644 temp/C_tiemannModel_ODE.m create mode 100644 temp/C_tiemannModel_ODEC.mexw64 create mode 100644 temp/C_tiemannModel_ODEMEX.m create mode 100644 temp/C_tiemannModel_REACTIONS.m diff --git a/+AMF/+utils/defineCustomColormap.m b/+AMF/+utils/defineCustomColormap.m new file mode 100644 index 0000000..a8beb26 --- /dev/null +++ b/+AMF/+utils/defineCustomColormap.m @@ -0,0 +1,28 @@ +function clist = define_custom_colormap(c_matrix,N) + +if length(c_matrix) == 3 + clist(1,:) = c_matrix{1}; %start color + clist(ceil(N/2),:) = c_matrix{2}; %middle color + clist(N,:) = c_matrix{3}; %end color + + dc1 = clist(ceil(N/2),:) - clist(1,:); + for i1 = 2:ceil(N/2)-1 + clist(i1,:) = clist(i1-1,:) + dc1/(N-1); + end + + dc2 = clist(N,:) - clist(ceil(N/2),:); + for i2 = ceil(N/2)+1:N-1 + clist(i2,:) = clist(i2-1,:) + dc2/(N-1); + end + + +elseif length(c_matrix) == 2 + clist(1,:) = c_matrix{1}; %start color + clist(N,:) = c_matrix{2}; %end color + + dc = clist(N,:)-clist(1,:); + + for i = 2:N-1 + clist(i,:) = clist(i-1,:) + dc/(N-1); + end +end \ No newline at end of file diff --git a/+AMF/+utils/getHist.m b/+AMF/+utils/getHist.m new file mode 100644 index 0000000..28a771e --- /dev/null +++ b/+AMF/+utils/getHist.m @@ -0,0 +1,14 @@ +function [N,C] = getHist(t,v,r,ny) + +a = repmat(t,size(v,1),1); +b = reshape(v.',numel(v),1); + +if numel(r) > 0 + [N, C] = hist3([a,b],{t,[r(1) : (r(2)-r(1))/(ny-1) : r(2)]}); +else + [N, C] = hist3([a,b],[numel(t) ny]); +end +N = log10(N); +N = N./max(max(N)); + +N(N==-inf) = 0; \ No newline at end of file diff --git a/+AMF/+utils/mexify.m b/+AMF/+utils/mexify.m new file mode 100644 index 0000000..facdf50 --- /dev/null +++ b/+AMF/+utils/mexify.m @@ -0,0 +1,6 @@ +function outputStr = mexify(inputStr) + +outputStr = inputStr; + +% parsers +outputStr = regexprep(outputStr, '([-+\w]+)\^([-+\w]+)', 'pow($1,$2)'); \ No newline at end of file diff --git a/+AMF/+utils/mexify2.m b/+AMF/+utils/mexify2.m new file mode 100644 index 0000000..c7988e6 --- /dev/null +++ b/+AMF/+utils/mexify2.m @@ -0,0 +1,8 @@ +function outputStr = mexify2(inputStr, compName) + +outputStr = inputStr; + +% parsers +outputStr = regexprep(outputStr, '([-+\w]+)\^([-+\w]+)', 'pow($1,$2)'); + +outputStr = regexprep(outputStr, 'if\((.*),(.*),(.*)\)', sprintf('0;\nif ($1)\n\t%s = $2;\nelse\n\t%s = $3;\nend', compName, compName)); \ No newline at end of file diff --git a/+AMF/+utils/parfor_progress.m b/+AMF/+utils/parfor_progress.m new file mode 100644 index 0000000..07ec991 --- /dev/null +++ b/+AMF/+utils/parfor_progress.m @@ -0,0 +1,82 @@ +function percent = parfor_progress(N) +%PARFOR_PROGRESS Progress monitor (progress bar) that works with parfor. +% PARFOR_PROGRESS works by creating a file called parfor_progress.txt in +% your working directory, and then keeping track of the parfor loop's +% progress within that file. This workaround is necessary because parfor +% workers cannot communicate with one another so there is no simple way +% to know which iterations have finished and which haven't. +% +% PARFOR_PROGRESS(N) initializes the progress monitor for a set of N +% upcoming calculations. +% +% PARFOR_PROGRESS updates the progress inside your parfor loop and +% displays an updated progress bar. +% +% PARFOR_PROGRESS(0) deletes parfor_progress.txt and finalizes progress +% bar. +% +% To suppress output from any of these functions, just ask for a return +% variable from the function calls, like PERCENT = PARFOR_PROGRESS which +% returns the percentage of completion. +% +% Example: +% +% N = 100; +% parfor_progress(N); +% parfor i=1:N +% pause(rand); % Replace with real code +% parfor_progress; +% end +% parfor_progress(0); +% +% See also PARFOR. + +% By Jeremy Scheff - jdscheff@gmail.com - http://www.jeremyscheff.com/ + +% error(nargchk(0, 1, nargin, 'struct')); + +if nargin < 1 + N = -1; +end + +percent = 0; +w = 50; % Width of progress bar + +if N > 0 + f = fopen('parfor_progress.txt', 'w'); + if f<0 + error('Do you have write permissions for %s?', pwd); + end + fprintf(f, '%d\n', N); % Save N at the top of progress.txt + fclose(f); + + if nargout == 0 + disp([' 0%[>', repmat(' ', 1, w), ']']); + end +elseif N == 0 + delete('parfor_progress.txt'); + percent = 100; + + if nargout == 0 + disp([repmat(char(8), 1, (w+9)), char(10), '100%[', repmat('=', 1, w+1), ']']); + end +else + + if ~exist('parfor_progress.txt', 'file') + error('parfor_progress.txt not found. Run PARFOR_PROGRESS(N) before PARFOR_PROGRESS to initialize parfor_progress.txt.'); + end + + f = fopen('parfor_progress.txt', 'a'); + fprintf(f, '1\n'); + fclose(f); + + f = fopen('parfor_progress.txt', 'r'); + progress = fscanf(f, '%d'); + fclose(f); + percent = (length(progress)-1)/progress(1)*100; + + if nargout == 0 + perc = sprintf('%3.0f%%', percent); % 4 characters wide, percentage + disp([repmat(char(8), 1, (w+9)), char(10), perc, '[', repmat('=', 1, round(percent*w/100)), '>', repmat(' ', 1, w - round(percent*w/100)), ']']); + end +end diff --git a/+AMF/+utils/parfor_progress2.m b/+AMF/+utils/parfor_progress2.m new file mode 100644 index 0000000..2335bb6 --- /dev/null +++ b/+AMF/+utils/parfor_progress2.m @@ -0,0 +1,82 @@ +function percent = parfor_progress2(N) +%PARFOR_PROGRESS Progress monitor (progress bar) that works with parfor. +% PARFOR_PROGRESS works by creating a file called parfor_progress.txt in +% your working directory, and then keeping track of the parfor loop's +% progress within that file. This workaround is necessary because parfor +% workers cannot communicate with one another so there is no simple way +% to know which iterations have finished and which haven't. +% +% PARFOR_PROGRESS(N) initializes the progress monitor for a set of N +% upcoming calculations. +% +% PARFOR_PROGRESS updates the progress inside your parfor loop and +% displays an updated progress bar. +% +% PARFOR_PROGRESS(0) deletes parfor_progress.txt and finalizes progress +% bar. +% +% To suppress output from any of these functions, just ask for a return +% variable from the function calls, like PERCENT = PARFOR_PROGRESS which +% returns the percentage of completion. +% +% Example: +% +% N = 100; +% parfor_progress(N); +% parfor i=1:N +% pause(rand); % Replace with real code +% parfor_progress; +% end +% parfor_progress(0); +% +% See also PARFOR. + +% By Jeremy Scheff - jdscheff@gmail.com - http://www.jeremyscheff.com/ + +% error(nargchk(0, 1, nargin, 'struct')); + +if nargin < 1 + N = -1; +end + +percent = 0; +w = 50; % Width of progress bar + +if N > 0 + f = fopen('parfor_progress.txt', 'w'); + if f<0 + error('Do you have write permissions for %s?', pwd); + end + fprintf(f, '%d\n', N); % Save N at the top of progress.txt + fclose(f); + + if nargout == 0 + disp([' 0%[>', repmat(' ', 1, w), ']']); + end +elseif N == 0 + delete('parfor_progress.txt'); + percent = 100; + + if nargout == 0 + disp([repmat(char(8), 1, (w+9)), char(10), '100%[', repmat('=', 1, w+1), ']']); + end +else + + if ~exist('parfor_progress.txt', 'file') + error('parfor_progress.txt not found. Run PARFOR_PROGRESS(N) before PARFOR_PROGRESS to initialize parfor_progress.txt.'); + end + +% f = fopen('parfor_progress.txt', 'a'); +% fprintf(f, '1\n'); +% fclose(f); + + f = fopen('parfor_progress.txt', 'r'); + progress = fscanf(f, '%d'); + fclose(f); + percent = (length(progress)-1)/progress(1)*100; + + if nargout == 0 + perc = sprintf('%3.0f%%', percent); % 4 characters wide, percentage + disp([perc, '[', repmat('=', 1, round(percent*w/100)), '>', repmat(' ', 1, w - round(percent*w/100)), ']']); + end +end diff --git a/+AMF/+utils/writeFile.m b/+AMF/+utils/writeFile.m new file mode 100644 index 0000000..90c1a3a --- /dev/null +++ b/+AMF/+utils/writeFile.m @@ -0,0 +1,5 @@ +function writeFile(fn, content) + +fid = fopen(fn, 'w'); +fprintf(fid, content); +fclose(fid); \ No newline at end of file diff --git a/+AMF/+visualisation/define_custom_colormap.m b/+AMF/+visualisation/define_custom_colormap.m new file mode 100644 index 0000000..a8beb26 --- /dev/null +++ b/+AMF/+visualisation/define_custom_colormap.m @@ -0,0 +1,28 @@ +function clist = define_custom_colormap(c_matrix,N) + +if length(c_matrix) == 3 + clist(1,:) = c_matrix{1}; %start color + clist(ceil(N/2),:) = c_matrix{2}; %middle color + clist(N,:) = c_matrix{3}; %end color + + dc1 = clist(ceil(N/2),:) - clist(1,:); + for i1 = 2:ceil(N/2)-1 + clist(i1,:) = clist(i1-1,:) + dc1/(N-1); + end + + dc2 = clist(N,:) - clist(ceil(N/2),:); + for i2 = ceil(N/2)+1:N-1 + clist(i2,:) = clist(i2-1,:) + dc2/(N-1); + end + + +elseif length(c_matrix) == 2 + clist(1,:) = c_matrix{1}; %start color + clist(N,:) = c_matrix{2}; %end color + + dc = clist(N,:)-clist(1,:); + + for i = 2:N-1 + clist(i,:) = clist(i-1,:) + dc/(N-1); + end +end \ No newline at end of file diff --git a/+AMF/+visualisation/define_figure_details.m b/+AMF/+visualisation/define_figure_details.m new file mode 100644 index 0000000..2e15ef5 --- /dev/null +++ b/+AMF/+visualisation/define_figure_details.m @@ -0,0 +1,59 @@ +function plotinfo = define_figure_details(varargin) + + if ~isempty(varargin) + plotinfo = varargin{1}; + else + plotinfo = struct(); + end + % figure size + dx = 10; + dy = 50; + ss = get(0,'ScreenSize'); + xmax = ss(3)-dx-10; + ymax = ss(4)-dy-80; + set(0,'DefaultFigurePosition',[dx dy xmax ymax]); + + + % font size + if ~isfield(plotinfo,'FS') + plotinfo.FS = 24; %40; + end + + % line width of axes + if ~isfield(plotinfo,'LW_axes') + plotinfo.LW_axes = 2; %3; + end + + % line width & marker size of (raw) data points + if ~isfield(plotinfo,'LW_data') + plotinfo.LW_data = 2; + end + if ~isfield(plotinfo,'MS_data') + plotinfo.MS_data = 14; + end + + % line width of spline data + if ~isfield(plotinfo,'LW_spline') + plotinfo.LW_spline = 3; + end + + % line width of model simulations / trajectories + if ~isfield(plotinfo,'LW_sim') + plotinfo.LW_sim = 4; + end + + + % text properties + set(0,'DefaultTextFontName','Myriad') + set(0,'DefaultTextFontSize',plotinfo.FS); + set(0,'DefaultTextInterpreter','tex'); + + % line and marker properties + set(0,'DefaultLineLineWidth',plotinfo.LW_data); + set(0,'DefaultLineMarkerSize',plotinfo.MS_data); + + % axes properties + set(0,'DefaultAxesFontName','Myriad') + set(0,'DefaultAxesFontSize',plotinfo.FS); + set(0,'DefaultAxesLineWidth',plotinfo.LW_axes); +end \ No newline at end of file diff --git a/+AMF/+visualisation/errorbar_tick.m b/+AMF/+visualisation/errorbar_tick.m new file mode 100644 index 0000000..9e40ebd --- /dev/null +++ b/+AMF/+visualisation/errorbar_tick.m @@ -0,0 +1,70 @@ +function errorbar_tick(h,w,xtype) +%ERRORBAR_TICK Adjust the width of errorbars +% ERRORBAR_TICK(H) adjust the width of error bars with handle H. +% Error bars width is given as a ratio of X axis length (1/80). +% ERRORBAR_TICK(H,W) adjust the width of error bars with handle H. +% The input W is given as a ratio of X axis length (1/W). The result +% is independent of the x-axis units. A ratio between 20 and 80 is usually fine. +% ERRORBAR_TICK(H,W,'UNITS') adjust the width of error bars with handle H. +% The input W is given in the units of the current x-axis. +% +% See also ERRORBAR +% + +% Author: Arnaud Laurent +% Creation : Jan 29th 2009 +% MATLAB version: R2007a +% +% Notes: This function was created from a post on the french forum : +% http://www.developpez.net/forums/f148/environnements-developpement/matlab/ +% Author : Jerome Briot (Dut) +% http://www.mathworks.com/matlabcentral/newsreader/author/94805 +% http://www.developpez.net/forums/u125006/dut/ +% It was further modified by Arnaud Laurent and Jerome Briot. + +% Check numbers of arguments +error(nargchk(1,3,nargin)) + +% Check for the use of V6 flag ( even if it is depreciated ;) ) +flagtype = get(h,'type'); + +% Check number of arguments and provide missing values +if nargin==1 + w = 80; +end + +if nargin<3 + xtype = 'ratio'; +end + +% Calculate width of error bars +if ~strcmpi(xtype,'units') + dx = diff(get(gca,'XLim')); % Retrieve x limits from current axis + w = dx/w; % Errorbar width +end + +% Plot error bars +if strcmpi(flagtype,'hggroup') % ERRORBAR(...) + + hh=get(h,'children'); % Retrieve info from errorbar plot + x = get(hh(2),'xdata'); % Get xdata from errorbar plot + + x(4:9:end) = x(1:9:end)-w/2; % Change xdata with respect to ratio + x(7:9:end) = x(1:9:end)-w/2; + x(5:9:end) = x(1:9:end)+w/2; + x(8:9:end) = x(1:9:end)+w/2; + + set(hh(2),'xdata',x(:)) % Change error bars on the figure + +else % ERRORBAR('V6',...) + + x = get(h(1),'xdata'); % Get xdata from errorbar plot + + x(4:9:end) = x(1:9:end)-w/2; % Change xdata with respect to the chosen ratio + x(7:9:end) = x(1:9:end)-w/2; + x(5:9:end) = x(1:9:end)+w/2; + x(8:9:end) = x(1:9:end)+w/2; + + set(h(1),'xdata',x(:)) % Change error bars on the figure + +end diff --git a/+AMF/+visualisation/plot_results.m b/+AMF/+visualisation/plot_results.m new file mode 100644 index 0000000..3f5f372 --- /dev/null +++ b/+AMF/+visualisation/plot_results.m @@ -0,0 +1,244 @@ +function plot_results(model,plotinfo) + addpath(genpath(fullfile(cd,'visualisation'))); + + load('r.mat') +% dir = [pwd '\' settings.folder_name '\' settings.phenotype '\']; +% load([dir sprintf('results_%s_Nit=%d_Nt=%d_seed=%d',settings.phenotype,model.options.numIter,model.options.numTimeSteps,settings.random_state)]); + + for it = 1:model.options.numIter + SSE(it,1) = sum(result.sse(:,it)); + end + [SSE_sorted,ind] = sort(SSE,'descend'); + clist = AMF.visualisation.define_custom_colormap(plotinfo.c_matrix,model.options.numIter); + + for i_mc = 1:numel(plotinfo.model_components) + x = plotinfo.model_components{i_mc}; + count = 0; + + + + + for i_x = 1:numel(result.(x)) + count = count + 1; + switch plotinfo.fig_style + case 'subplot' + % plotinfo.FS = 18; + % plotinfo.LW_axes = 2; + % plotinfo.LW_data = 3; + % plotinfo.MS_data = 16; + % plotinfo.LW_sim = 4; + + Nr = ceil(sqrt(numel(result.(x)))); + Nc = ceil(numel(result.(x))/Nr); + + if i_x == 1 + f{i_mc} = figure; %('name',[settings.phenotype ' - ' x]); + end + ax(i_x) = subplot(Nc,Nr,i_x);hold on + + case 'fig' + % plotinfo.FS = 40; + % plotinfo.LW_axes = 3; + % plotinfo.LW_data = 4; + % plotinfo.MS_data = 26; + % plotinfo.LW_sim = 6; + f{i_mc,i_x} = figure; %('name',[settings.phenotype ' - ' x]); + ax(i_x) = gca;hold on + + case 'splitfig' + if isfield(plotinfo,'Nr') + Nr = plotinfo.Nr; + else + Nr = 2; + end + if isfield(plotinfo,'Nc') + Nc = plotinfo.Nc; + else + Nc = 2; + end + i_fig = ceil( count / ( Nr * Nc )); + i_subpl = count - (i_fig-1) * ( Nr * Nc ); + + if i_subpl == 1 + f{i_fig} = figure; %('Name',[settings.phenotype ' - ' x ' [' num2str(i_fig) '/' num2str(ceil(numel(result.(x))/(Nr*Nc))) ']']); + end + ax(i_x) = subplot(Nr,Nc,i_subpl);hold on + end + AMF.visualisation.define_figure_details;%(plotinfo); + + T = result.(x)(i_x).time; + + switch plotinfo.plot_color + case 'normal' + for it = 1:model.options.numIter + X = result.(x)(i_x).val(:,it); + plot(T,X,'r-') + end + + case 'error' + for it = 1:model.options.numIter + X = result.(x)(i_x).val(:,it); + plot(T,X,'-','color',clist(it,:)); + end + + case 'density' + t_array = repmat(T,model.options.numIter,1); + + x_matrix = []; + for it = 1:model.options.numIter + x_matrix(it,:) = result.(x)(i_x).val(:,it); + end + x_array = x_matrix(:); + + [N,C] = hist3(ax(i_x),[t_array x_array],[model.options.numTimeSteps 100]); + N = N./max(max(N)); + N(isinf(N))=0; + + h=pcolor(C{1},C{2},N'); + shading(ax(i_x),'flat') + colormap(ax(i_x),clist); + + % annotate 67% confidence interval + if isfield(plotinfo,'ci') && plotinfo.ci + h_ci(1) = plot(T,mean(x_matrix)-std(x_matrix),'-.'); + h_ci(2) = plot(T,mean(x_matrix)+std(x_matrix),'-.'); + set(h_ci(:),'Color',clist(end,:)/2.5,'LineWidth',20) + end + case 'density2' + DT = 1; + NDX = 50; + Tspace = T(1):DT:T(end); + y_lim = get_ylim_without_outliers(result,model,x,i_x); + Xmin = y_lim(1); + Xmax = y_lim(2); + DX = ((ceil(Xmax)-floor(Xmin))/NDX); + Xspace = floor(Xmin) : DX : ceil(Xmax); + Z = zeros(length(Tspace),length(Xspace)-1); + + for it = 1:model.options.numIter + t_curr = T'; + x_curr = result.(x)(i_x).val(:,it); + + % -- interpolate data to discretized space + A{it}.t = interp1(t_curr,t_curr,Tspace); + A{it}.x = interp1(t_curr,x_curr,A{it}.t,'linear'); + A{it}.i = []; + + for t_i = 1:length(Tspace) + for x_i = 1:length(Xspace)-1 + dX = [Xspace(x_i) Xspace(x_i+1)]; + + left = find(A{it}.x(t_i)>=dX(1)); + right = find(A{it}.x(t_i) red + case 'black' + clist = define_custom_colormap({[0.9 0.9 0.9] [0 0 0]},max(Z(:))); %light grey -> black + case 'blue' + clist = define_custom_colormap({[0.8 0.8 1] [0 0 0.8]},max(Z(:))); %light blue -> dark blue + end + else + clist = define_custom_colormap(plotinfo.c_matrix,max(Z(:))); + end + + for it = 1:model.options.numIter + surf_x = repmat( A{it}.t( ~isnan(A{it}.t) ),2,1); + surf_y = repmat( A{it}.x( ~isnan(A{it}.t) ),2,1); + surf_z = zeros(size(surf_x)); + + surf_c = []; + for t_i = 1:length(surf_x) + if t_i <= length(A{it}.i) + surf_c(t_i) = Z(t_i,A{it}.i(t_i)); + else + surf_c(t_i) = 0; + end + end + + surface(surf_x,surf_y,surf_z,repmat(surf_c,2,1),... + 'FaceColor','none','EdgeColor','interp','LineWidth',1); + end + colormap(clist) + end + + + + if ~isempty(result.(x)(i_x).data) + plot(result.(x)(i_x).data.time,result.(x)(i_x).data.val,'kx',... + 'MarkerSize',20,'LineWidth',3); + he = errorbar(result.(x)(i_x).data.time,result.(x)(i_x).data.val,result.(x)(i_x).data.std,'k.',... + 'LineWidth',3); + AMF.visualisation.errorbar_tick(he,0.5,'units') + end + + xlabel(['time [' model.options.time_unit ']']) + + if ~isempty(result.(x)(i_x).unit) + ylabel([strrep(result.(x)(i_x).name,'_','-') ' [' result.(x)(i_x).unit ']']) + else + ylabel(strrep(result.(x)(i_x).name,'_','-')) + end + + set(ax(i_x),'xlim',[result.(x)(i_x).time(1)-0.25 result.(x)(i_x).time(end)+0.25]) + if isfield(plotinfo,'remove_outliers') && plotinfo.remove_outliers + set(ax(i_x),'ylim',get_ylim_without_outliers(result,model,x,i_x)) + end + end + + if plotinfo.save + save_dir = [pwd '\results\' plotinfo.plot_color '\']; + if ~exist(save_dir,'dir') + mkdir(save_dir) + end + for i_f = 1:length(f) + s.fig_handle = f{i_f}; + if length(f) == 1 + s.filename = [save_dir 'Nit=' num2str(model.options.numIter) '_Nt=' num2str(model.options.numTimeSteps) '_' x]; + else + s.filename = [save_dir 'Nit=' num2str(model.options.numIter) '_Nt=' num2str(model.options.numTimeSteps) '_' x num2str(i_f)]; + end + s.eps = 0; + s.png = 1; + save_figure_to_file(s) + close(i_f); + end + end + end +end + +function y_lim = get_ylim_without_outliers(result,model,x,i_x) + minlist = []; + maxlist = []; + for it = 1:model.options.numIter + minlist(end+1,1) = min(result.(x)(i_x).val(:,it)); + maxlist(end+1,1) = max(result.(x)(i_x).val(:,it)); + end + minlist_sorted = sort(minlist,'ascend'); + minQ1 = minlist_sorted(ceil(0.25*length(minlist))); + minQ3 = minlist_sorted(ceil(0.75*length(minlist))); + + maxlist_sorted = sort(maxlist,'ascend'); + maxQ1 = maxlist_sorted(ceil(0.25*length(maxlist))); + maxQ3 = maxlist_sorted(ceil(0.75*length(maxlist))); + + w=2; + i_min_outliers = (minlist > minQ3 + w*(minQ3 - minQ1) | minlist < minQ1 - w*(minQ3 - minQ1)); + i_max_outliers = (maxlist > maxQ3 + w*(maxQ3 - maxQ1) | maxlist < maxQ1 - w*(maxQ3 - maxQ1)); + + + y_lim(1) = min(minlist(~i_min_outliers)); + y_lim(2) = max(maxlist(~i_max_outliers)); +end \ No newline at end of file diff --git a/+AMF/+visualisation/save_figure_to_file.m b/+AMF/+visualisation/save_figure_to_file.m new file mode 100644 index 0000000..1d91c6d --- /dev/null +++ b/+AMF/+visualisation/save_figure_to_file.m @@ -0,0 +1,185 @@ +function save_figure_to_file(save_options) + + +%% Construct the filename +if numel(save_options.filename) < 5 || ~strcmpi(save_options.filename(end-3:end), '.eps') + save_options.filename = [save_options.filename '.eps']; % Add the missing extension +end + + +%% Find all the used fonts in the figure +font_handles = findall(save_options.fig_handle, '-property', 'FontName'); +fonts = get(font_handles, 'FontName'); +if ~iscell(fonts) + fonts = {fonts}; +end + + +%% Map supported font aliases onto the correct name +fontsl = lower(fonts); +for a = 1:numel(fonts) + f1 = fontsl{a}; + f1(f1==' ') = []; + switch f1 + case {'times', 'timesnewroman', 'times-roman'} + fontsl{a} = 'times-roman'; + case {'arial', 'helvetica'} + fontsl{a} = 'helvetica'; + case {'newcenturyschoolbook', 'newcenturyschlbk'} + fontsl{a} = 'newcenturyschlbk'; + otherwise + end +end +fontslu = unique(fontsl); +% Determine the font swap table +matlab_fonts = {'Helvetica', 'Times-Roman', 'Palatino', 'Bookman', 'Helvetica-Narrow', 'Symbol', ... + 'AvantGarde', 'NewCenturySchlbk', 'Courier', 'ZapfChancery', 'ZapfDingbats'}; +matlab_fontsl = lower(matlab_fonts); +require_swap = find(~ismember(fontslu, matlab_fontsl)); +unused_fonts = find(~ismember(matlab_fontsl, fontslu)); +font_swap = cell(3, min(numel(require_swap), numel(unused_fonts))); +fonts_new = fonts; +for a = 1:size(font_swap, 2) + font_swap{1,a} = find(strcmp(fontslu{require_swap(a)}, fontsl)); + font_swap{2,a} = matlab_fonts{unused_fonts(a)}; + font_swap{3,a} = fonts{font_swap{1,a}(1)}; + fonts_new(font_swap{1,a}) = {font_swap{2,a}}; +end + + +%% Swap the fonts +if ~isempty(font_swap) + fonts_size = get(font_handles, 'FontSize'); + if iscell(fonts_size) + fonts_size = cell2mat(fonts_size); + end + M = false(size(font_handles)); + % Loop because some changes may not stick first time, due to listeners + c = 0; + update = zeros(1000, 1); + for b = 1:10 % Limit number of loops to avoid infinite loop case + for a = 1:numel(M) + M(a) = ~isequal(get(font_handles(a), 'FontName'), fonts_new{a}) || ~isequal(get(font_handles(a), 'FontSize'), fonts_size(a)); + if M(a) + set(font_handles(a), 'FontName', fonts_new{a}, 'FontSize', fonts_size(a)); + c = c + 1; + update(c) = a; + end + end + if ~any(M) + break; + end + end + % Compute the order to revert fonts later, without the need of a loop + [update, M] = unique(update(1:c)); + [M, M] = sort(M); + update = reshape(update(M), 1, []); +end + + +%% Set paper size +old_pos_mode = get(save_options.fig_handle, 'PaperPositionMode'); +old_orientation = get(save_options.fig_handle, 'PaperOrientation'); +set(save_options.fig_handle, 'PaperPositionMode', 'auto', 'PaperOrientation', 'portrait'); + + +%% MATLAB bug fix - black and white text can come out inverted sometimes +% Find the white and black text +white_text_handles = findobj(save_options.fig_handle, 'Type', 'text'); +M = get(white_text_handles, 'Color'); +if iscell(M) + M = cell2mat(M); +end +M = sum(M, 2); +black_text_handles = white_text_handles(M == 0); +white_text_handles = white_text_handles(M == 3); + + +%% Set the font colors slightly off their correct values +set(black_text_handles, 'Color', [0 0 0] + eps); +set(white_text_handles, 'Color', [1 1 1] - eps); + + +%% MATLAB bug fix - white lines can come out funny sometimes +% Find the white lines +white_line_handles = findobj(save_options.fig_handle, 'Type', 'line'); +M = get(white_line_handles, 'Color'); +if iscell(M) + M = cell2mat(M); +end +white_line_handles = white_line_handles(sum(M, 2) == 3); + + +%% Set the line color slightly off white +set(white_line_handles, 'Color', [1 1 1] - 0.00001); + + +%% Print to eps and png files +if save_options.eps + print(save_options.fig_handle,'-depsc2',save_options.filename); +end +if save_options.png + print(save_options.fig_handle,'-dpng',[save_options.filename(1:end-4) '.png']); +end + + +%% Reset the font and line colors +set(black_text_handles, 'Color', [0 0 0]); +set(white_text_handles, 'Color', [1 1 1]); +set(white_line_handles, 'Color', [1 1 1]); + + +%% Reset paper size +set(save_options.fig_handle, 'PaperPositionMode', old_pos_mode, 'PaperOrientation', old_orientation); + + +%% Correct the fonts +if ~isempty(font_swap) + % Reset the font names in the figure + for a = update + set(font_handles(a), 'FontName', fonts{a}, 'FontSize', fonts_size(a)); + end + % Replace the font names in the eps file + font_swap = font_swap(2:3,:); + try + swap_fonts(save_options.filename, font_swap{:}); + catch + warning('swap_fonts() failed. This is usually because the figure contains a large number of patch objects. Consider exporting to a bitmap format in this case.'); + return + end +end + + +%% Fix the line styles +try + fix_lines(save_options.filename); +catch +% warning('fix_lines() failed. This is usually because the figure contains a large number of patch objects. Consider exporting to a bitmap format in this case.'); +end +return + + + +% ========================================================================================================================= +function swap_fonts(fname, varargin) +% Read in the file +fh = fopen(fname, 'r'); +if fh == -1 + error('File %s not found.', fname); +end +fstrm = fread(fh, '*char')'; +fclose(fh); + +% Replace the font names +for a = 1:2:numel(varargin) + fstrm = regexprep(fstrm, [varargin{a} '-?[a-zA-Z]*\>'], varargin{a+1}(~isspace(varargin{a+1}))); +end + +% Write out the updated file +fh = fopen(fname, 'w'); +if fh == -1 + error('Unable to open %s for writing.', fname2); +end +fwrite(fh, fstrm, 'char*1'); +fclose(fh); +return \ No newline at end of file diff --git a/+AMF/@DataComponent/DataComponent.m b/+AMF/@DataComponent/DataComponent.m new file mode 100644 index 0000000..55bc1af --- /dev/null +++ b/+AMF/@DataComponent/DataComponent.m @@ -0,0 +1,30 @@ +classdef DataComponent < handle + properties + name + obs + index + + timeField + valField + stdField + + unitConv + smooth + + src + curr + + time + val + std + + ppform + options + + fitIdx + end + methods + function this = DataComponent(varargin) + end + end +end \ No newline at end of file diff --git a/+AMF/@DataComponent/filter.m b/+AMF/@DataComponent/filter.m new file mode 100644 index 0000000..f6a29f4 --- /dev/null +++ b/+AMF/@DataComponent/filter.m @@ -0,0 +1,3 @@ +function fieldArr = filter(fieldArr, func) + +fieldArr = fieldArr(func(fieldArr)); \ No newline at end of file diff --git a/+AMF/@DataComponent/getStruct.m b/+AMF/@DataComponent/getStruct.m new file mode 100644 index 0000000..e454111 --- /dev/null +++ b/+AMF/@DataComponent/getStruct.m @@ -0,0 +1,11 @@ +function s = getStruct(compArr) + +for i = 1:length(compArr) + comp = compArr(i); + + props = properties(comp); + for j = 1:length(props) + propName = props{j}; + s(i).(propName) = comp.(propName); + end +end \ No newline at end of file diff --git a/+AMF/@DataComponent/isConstant.m b/+AMF/@DataComponent/isConstant.m new file mode 100644 index 0000000..dbd5c93 --- /dev/null +++ b/+AMF/@DataComponent/isConstant.m @@ -0,0 +1,8 @@ +function filter = isConstant(fieldArr) + +filter = zeros(1, length(fieldArr)); +for i = 1:length(fieldArr) + field = fieldArr(i); + filter(i) = length(field.src.time); +end +filter = filter < 2; \ No newline at end of file diff --git a/+AMF/@DataComponent/isObservable.m b/+AMF/@DataComponent/isObservable.m new file mode 100644 index 0000000..b393de5 --- /dev/null +++ b/+AMF/@DataComponent/isObservable.m @@ -0,0 +1,3 @@ +function filter = isObservable(fieldArr) + +filter = logical([fieldArr.obs]); \ No newline at end of file diff --git a/+AMF/@DataComponent/plot.m b/+AMF/@DataComponent/plot.m new file mode 100644 index 0000000..181e85b --- /dev/null +++ b/+AMF/@DataComponent/plot.m @@ -0,0 +1,7 @@ +function this = plot(this) + +if any(this.src.std) + errorbar(this.src.time, this.src.val, this.src.std, 'xr'); +else + plot(this.src.time, this.src.val, 'xr'); +end \ No newline at end of file diff --git a/+AMF/@DataField/DataField.m b/+AMF/@DataField/DataField.m new file mode 100644 index 0000000..533654e --- /dev/null +++ b/+AMF/@DataField/DataField.m @@ -0,0 +1,24 @@ +classdef DataField < AMF.DataComponent + properties + end + methods + function this = DataField(index, name, obs, timeField, valField, stdField, unitConv, smooth) + this.index = index; + this.name = name; + this.obs = obs; + this.timeField = timeField; + this.valField = valField; + this.stdField = stdField; + this.unitConv = unitConv; + this.smooth = smooth; + + this.src.val = []; + this.src.std = []; + this.src.time = []; + this.ppform = struct(); + + this.curr.val = []; + this.curr.std = []; + end + end +end \ No newline at end of file diff --git a/+AMF/@DataField/genSpline.m b/+AMF/@DataField/genSpline.m new file mode 100644 index 0000000..3f1e2f9 --- /dev/null +++ b/+AMF/@DataField/genSpline.m @@ -0,0 +1,22 @@ +function fieldArr = genSpline(fieldArr) + +for i = 1:length(fieldArr) + field = fieldArr(i); + + if isConstant(field) + continue + end + + t = field.src.time; + dd = field.curr.val; + ds = field.curr.std; + smooth = field.smooth; + + w = (1 ./ ds ).^2; + + if (sum(isinf(w))==0) + field.ppform = csaps(t,dd,smooth,[],w); + else + field.ppform = csaps(t,dd,smooth,[]); + end +end \ No newline at end of file diff --git a/+AMF/@DataField/interp.m b/+AMF/@DataField/interp.m new file mode 100644 index 0000000..ef4eecf --- /dev/null +++ b/+AMF/@DataField/interp.m @@ -0,0 +1,72 @@ +function [val, std] = interp(fieldArr, t, method) + +if nargin < 3, method = 'LINEAR'; end + +switch upper(method) + + case 'LINEAR' + interpFunc = @interpLinear; + + case 'SPLINE' + interpFunc = @interpSpline; + + otherwise + error('Unknown interpolation method.'); +end + +for field = fieldArr + field.time = t(:); + + if isConstant(field) + if isempty(field.src.time) + % static (no time point) + val = ones(size(field.time)) * field.curr.val; + + if any(field.curr.std) + std = ones(size(field.time)) * field.curr.std; + else + std = []; + end + else + % constant (vector of NaNs with one value at the measured time + % point) + timeIdx = find(t == field.src.time); + val = nan(size(field.time)); val(timeIdx) = field.curr.val; + + if any(field.curr.std) + std = nan(size(field.time)); std(timeIdx) = field.curr.std; + else + std = []; + end + end + + field.val = val; + field.std = std; + else + % dynamic + [val, std] = interpFunc(field, t); + field.val = val(:); + field.std = std(:); + end +end + +val = [fieldArr.val]; +std = [fieldArr.std]; + +% val = zeros(length(t), length(fieldArr)); +% std = zeros(length(t), length(fieldArr)); +% +% for i = 1:length(fieldArr) +% field = fieldArr(i); +% +% switch upper(field.type) +% case 'CONSTANT' +% val(:,i) = field.val * ones(length(t), 1); +% std(:,i) = field.std * ones(length(t), 1); +% otherwise +% [fieldVal, fieldStd] = interpFunc(field, t); +% +% val(:,i) = fieldVal; +% std(:,i) = fieldStd; +% end +% end \ No newline at end of file diff --git a/+AMF/@DataField/interpLinear.m b/+AMF/@DataField/interpLinear.m new file mode 100644 index 0000000..9eb280b --- /dev/null +++ b/+AMF/@DataField/interpLinear.m @@ -0,0 +1,9 @@ +function [val, std] = interpLinear(field, t) + +val = interp1(field.src.time, field.curr.val, t, 'linaer', 'extrap'); + +if any(field.curr.std) + std = sqrt(interp1(field.src.time, field.curr.std .^ 2, t, 'linear', 'extrap'))'; +else + std = []; +end \ No newline at end of file diff --git a/+AMF/@DataField/interpSpline.m b/+AMF/@DataField/interpSpline.m new file mode 100644 index 0000000..38df743 --- /dev/null +++ b/+AMF/@DataField/interpSpline.m @@ -0,0 +1,13 @@ +function [val, std] = interpSpline(field, t) + +if isempty(field.ppform) + genSpline(field); +end + +val = ppval(field.ppform, t)'; + +if any(field.curr.std) + std = sqrt(interp1(field.src.time, field.curr.std .^ 2, t, 'linear','extrap'))'; +else + std = []; +end \ No newline at end of file diff --git a/+AMF/@DataField/randomize.m b/+AMF/@DataField/randomize.m new file mode 100644 index 0000000..49e30ad --- /dev/null +++ b/+AMF/@DataField/randomize.m @@ -0,0 +1,9 @@ +function fieldArr = randomize(fieldArr) + +for field = fieldArr + if ~isempty(field.src.std) + field.curr.val = field.src.val + randn(size(field.src.val)) .* field.src.std; + + genSpline(field); + end +end \ No newline at end of file diff --git a/+AMF/@DataField/restore.m b/+AMF/@DataField/restore.m new file mode 100644 index 0000000..1cd6963 --- /dev/null +++ b/+AMF/@DataField/restore.m @@ -0,0 +1,8 @@ +function fieldArr = restore(fieldArr) + +for field = fieldArr + field.curr.val = field.src.val; + field.curr.std = field.src.std; + + genSpline(field); +end \ No newline at end of file diff --git a/+AMF/@DataFunction/DataFunction.m b/+AMF/@DataFunction/DataFunction.m new file mode 100644 index 0000000..efe4bbd --- /dev/null +++ b/+AMF/@DataFunction/DataFunction.m @@ -0,0 +1,16 @@ +classdef DataFunction < AMF.DataComponent + properties + valExpr + stdExpr + end + methods + function this = DataFunction(index, name, obs, timeField, valExpr, stdExpr) + this.index = index; + this.name = name; + this.obs = obs; + this.timeField = timeField; + this.valExpr = valExpr; + this.stdExpr = stdExpr; + end + end +end \ No newline at end of file diff --git a/+AMF/@DataSet/DataSet.m b/+AMF/@DataSet/DataSet.m new file mode 100644 index 0000000..bf82034 --- /dev/null +++ b/+AMF/@DataSet/DataSet.m @@ -0,0 +1,68 @@ +classdef DataSet < handle + properties + name + description + specification + + data + + groups + activeGroup + + fields + functions + ref + list + + funcs + compileDir + end + methods + function this = DataSet(dataFile) + this.name = dataFile; + this.specification = feval(dataFile); + this.description = this.specification.DESCRIPTION; + this.groups = this.specification.GROUPS; + + this.compileDir = 'temp/'; + this.funcs.func = str2func(['C_', this.name, '_FUNCTIONS']); + + % fields + this.fields = AMF.DataField.empty; + n = size(this.specification.FIELDS, 1); + for i = 1:n + fieldSpec = this.specification.FIELDS(i,:); + fieldName = fieldSpec{1}; + newField = AMF.DataField(i, fieldSpec{:}); + this.ref.(fieldName) = newField; + + this.fields(i) = newField; + end + + % functions + if isfield(this.specification, 'FUNCTIONS') + this.functions = AMF.DataFunction.empty; + m = size(this.specification.FUNCTIONS, 1); + for i = 1:m + fieldSpec = this.specification.FUNCTIONS(i,:); + fieldName = fieldSpec{1}; + newFunc = AMF.DataFunction(i + n, fieldSpec{:}); + this.ref.(fieldName) = newFunc; + + this.functions(i) = newFunc; + end + end + +% this.fields = struct2array(this.ref); + this.list = struct2cell(this.ref); + + this.data = load([this.specification.FILE, '.mat']); + + this.loadGroup(this.groups{1}); + + if ~isempty(this.functions) + compileFunctions(this); + end + end + end +end \ No newline at end of file diff --git a/+AMF/@DataSet/compileFunctions.m b/+AMF/@DataSet/compileFunctions.m new file mode 100644 index 0000000..710d26d --- /dev/null +++ b/+AMF/@DataSet/compileFunctions.m @@ -0,0 +1,38 @@ +function this = compileFunctions(this) + +if isempty(this.functions) + return +end + +import AMF.utils.writeFile + +% +% Data functions +% + +fn = char(this.funcs.func); + +header = ['function [dd, ds] = ', fn, '(dd,ds,d)\n\n']; + +DD = {}; +DS = {}; +n = length(this.fields); +for i = 1:length(this.fields) + comp = this.fields(i); + DD{i} = [comp.name, ' = dd(:, d.d.', comp.name, ');\n']; + DS{i} = [comp.name, ' = ds(:, d.d.', comp.name, ');\n']; +end + +DFD = {}; EDFD = {}; +DFS = {}; EDFS = {}; +for i = 1:length(this.functions) + comp = this.functions(i); + DFD{i} = [comp.name, ' = ', comp.valExpr, ';\n']; + DFS{i} = [comp.name, ' = ', comp.stdExpr, ';\n']; + EDFD{i} = ['dd(:, ', num2str(comp.index), ') = ', comp.name, ';\n']; + EDFS{i} = ['ds(:, ', num2str(comp.index), ') = ', comp.name, ';\n']; +end + +content = [DD{:}, '\n', DFD{:}, '\n', EDFD{:}, '\n', DS{:}, '\n', DFS{:}, '\n', EDFS{:}]; + +writeFile([this.compileDir, fn, '.m'], [header, content]); \ No newline at end of file diff --git a/+AMF/@DataSet/filter.m b/+AMF/@DataSet/filter.m new file mode 100644 index 0000000..7c5de22 --- /dev/null +++ b/+AMF/@DataSet/filter.m @@ -0,0 +1,4 @@ +function compList = filter(this, func) + +idx = cellfun(func, this.list); +compList = this.list(idx); \ No newline at end of file diff --git a/+AMF/@DataSet/get.m b/+AMF/@DataSet/get.m new file mode 100644 index 0000000..aeb9291 --- /dev/null +++ b/+AMF/@DataSet/get.m @@ -0,0 +1,7 @@ +function fields = get(this, varargin) + +for i = 1:length(varargin) + fieldName = varargin{i}; + + fields(i) = this.ref.(fieldName); +end \ No newline at end of file diff --git a/+AMF/@DataSet/getDataStruct.m b/+AMF/@DataSet/getDataStruct.m new file mode 100644 index 0000000..ded16f8 --- /dev/null +++ b/+AMF/@DataSet/getDataStruct.m @@ -0,0 +1,9 @@ +function d = getDataStruct(this) + +nf = length(this.fields); +for i = 1:nf + d.d.(this.fields(i).name) = this.fields(i).index; +end +for i = 1:length(this.functions) + d.d.(this.functions(i).name) = this.functions(i).index; +end \ No newline at end of file diff --git a/+AMF/@DataSet/getFitData.m b/+AMF/@DataSet/getFitData.m new file mode 100644 index 0000000..f6e9383 --- /dev/null +++ b/+AMF/@DataSet/getFitData.m @@ -0,0 +1,25 @@ +function [dd, ds] = getFitData(this) + +ft = getFitTime(this); +tt = nan(size(ft)); + +for i = 1:length(this.fields) + df = this.fields(i); + t = df.src.time; + idx = ismember(ft, t); + + if isempty(t) + d = ones(size(ft)) * df.curr.val(1); + s = ones(size(ft)) * df.curr.std(1); + else + d = tt; d(idx) = df.curr.val; + s = tt; s(idx) = df.curr.std; + end + + dd(:,i) = d; + ds(:,i) = s; +end + +if ~isempty(this.functions) + [dd, ds] = this.funcs.func(dd, ds, getDataStruct(this)); +end \ No newline at end of file diff --git a/+AMF/@DataSet/getFitTime.m b/+AMF/@DataSet/getFitTime.m new file mode 100644 index 0000000..3535610 --- /dev/null +++ b/+AMF/@DataSet/getFitTime.m @@ -0,0 +1,12 @@ +function t = getFitTime(this) + +t = []; + +for i = 1:length(this.fields) + df = this.fields(i); + if df.obs + t = [t df.src.time(:)']; + end +end + +t = sort(unique(t)); \ No newline at end of file diff --git a/+AMF/@DataSet/getInterpData.m b/+AMF/@DataSet/getInterpData.m new file mode 100644 index 0000000..b29cd62 --- /dev/null +++ b/+AMF/@DataSet/getInterpData.m @@ -0,0 +1,11 @@ +function [dd, ds] = getInterpData(this, t, method) + +if nargin < 3 + method = 'spline'; +end + +[dd, ds] = interp(this.fields, t, method); + +if ~isempty(this.functions) + [dd, ds] = this.funcs.func(dd, ds, getDataStruct(this)); +end \ No newline at end of file diff --git a/+AMF/@DataSet/interp.m b/+AMF/@DataSet/interp.m new file mode 100644 index 0000000..ad71638 --- /dev/null +++ b/+AMF/@DataSet/interp.m @@ -0,0 +1,7 @@ +function this = interp(this, t, method) + +if nargin < 3, method = 'LINEAR'; end + +interp(this.fields, t, method); + +parseFunctions(this); \ No newline at end of file diff --git a/+AMF/@DataSet/loadGroup.m b/+AMF/@DataSet/loadGroup.m new file mode 100644 index 0000000..0c9d70d --- /dev/null +++ b/+AMF/@DataSet/loadGroup.m @@ -0,0 +1,6 @@ +function this = loadGroup(this, groupName) + +this.activeGroup = groupName; + +parseFields(this); +parseFunctions(this); \ No newline at end of file diff --git a/+AMF/@DataSet/parseFields.m b/+AMF/@DataSet/parseFields.m new file mode 100644 index 0000000..47dba83 --- /dev/null +++ b/+AMF/@DataSet/parseFields.m @@ -0,0 +1,17 @@ +function this = parseFields(this) + +dataStruct = this.data.(this.activeGroup); + +for field = this.fields + if ~isempty(field.timeField) + field.src.time = dataStruct.(field.timeField); + end + + field.src.val = dataStruct.(field.valField) * field.unitConv; + + if ~isempty(field.stdField) + field.src.std = dataStruct.(field.stdField) * field.unitConv; + end + + restore(field); +end \ No newline at end of file diff --git a/+AMF/@DataSet/parseFunctions.m b/+AMF/@DataSet/parseFunctions.m new file mode 100644 index 0000000..0c7c19a --- /dev/null +++ b/+AMF/@DataSet/parseFunctions.m @@ -0,0 +1,10 @@ +function this = parseFunctions(this) + +dataStruct = this.data.(this.activeGroup); + +for field = this.functions + if ~isempty(field.timeField) + field.src.time = dataStruct.(field.timeField); + end + +end \ No newline at end of file diff --git a/+AMF/@DataSet/randomize.m b/+AMF/@DataSet/randomize.m new file mode 100644 index 0000000..f64a6fa --- /dev/null +++ b/+AMF/@DataSet/randomize.m @@ -0,0 +1,5 @@ +function this = randomize(this) + +randomize(this.fields); + +parseFunctions(this); \ No newline at end of file diff --git a/+AMF/@GridUI/GridUI.m b/+AMF/@GridUI/GridUI.m new file mode 100644 index 0000000..57c2ea7 --- /dev/null +++ b/+AMF/@GridUI/GridUI.m @@ -0,0 +1,15 @@ +classdef GridUI < handle + properties + id + color + + controls + handles + dim = [0 0] + scale = 25 + end + methods + function this = GridUI(varargin) + end + end +end \ No newline at end of file diff --git a/+AMF/@GridUI/draw.m b/+AMF/@GridUI/draw.m new file mode 100644 index 0000000..2f999b9 --- /dev/null +++ b/+AMF/@GridUI/draw.m @@ -0,0 +1,16 @@ +function this = draw(this, name, type, pos, size, value, cb) + +import AMF.* + +control.name = name; +control.type = type; +control.pos = pos; +control.size = size; +control.callback = cb; +control.value = value; +control.selected = ''; + +this.controls.(name) = control; + +this.dim(1) = max([control.pos(1) + control.size(1) + 2, this.dim(1)]); +this.dim(2) = max([control.pos(2) + control.size(2) + 2, this.dim(2)]); \ No newline at end of file diff --git a/+AMF/@GridUI/render.m b/+AMF/@GridUI/render.m new file mode 100644 index 0000000..375b080 --- /dev/null +++ b/+AMF/@GridUI/render.m @@ -0,0 +1,8 @@ +function this = render(this) + +this.id = figure; +this.color = get(this.id, 'color'); + +set(this.id, 'Position', [0, 0, fliplr(size(this))]); + +structfun(@this.renderControl, this.controls); \ No newline at end of file diff --git a/+AMF/@GridUI/renderAxes.m b/+AMF/@GridUI/renderAxes.m new file mode 100644 index 0000000..ccee716 --- /dev/null +++ b/+AMF/@GridUI/renderAxes.m @@ -0,0 +1,9 @@ +function handle = renderAxes(this, control) + +UISize = size(this); +pos(1) = (control.pos(2) + 2) / UISize(2) * this.scale; +pos(2) = (control.pos(1) + 2) / UISize(1) * this.scale; +dim(1) = (control.size(2) - 2) / UISize(2) * this.scale; +dim(2) = (control.size(1) - 2) / UISize(1) * this.scale; + +handle = axes('Parent', this.id, 'Position', [pos(1), pos(2), dim(1), dim(2)]); \ No newline at end of file diff --git a/+AMF/@GridUI/renderControl.m b/+AMF/@GridUI/renderControl.m new file mode 100644 index 0000000..d7e61d1 --- /dev/null +++ b/+AMF/@GridUI/renderControl.m @@ -0,0 +1,15 @@ +function handle = renderControl(this, control) + +switch control.type + case 'EDIT' + handle = renderEdit(this, control); + case 'AXES' + handle = renderAxes(this, control); + case 'LISTBOX' + handle = renderListBox(this, control); + + otherwise + handle = 0; +end + +this.handles.(control.name) = handle; \ No newline at end of file diff --git a/+AMF/@GridUI/renderEdit.m b/+AMF/@GridUI/renderEdit.m new file mode 100644 index 0000000..0f5a603 --- /dev/null +++ b/+AMF/@GridUI/renderEdit.m @@ -0,0 +1,35 @@ +function handle = renderEdit(this, control) + +UISize = size(this); + +xpos = control.pos(2) * this.scale; +ypos = UISize(1) - control.pos(1) * this.scale - this.scale * 2; +xsize = control.size(2) * this.scale; +ysize = control.size(1) * this.scale; + +pos = [xpos, ypos]; +dim = [xsize, ysize]; + +label = uicontrol('Parent', this.id, 'Style', 'text', 'Position', [pos(1), pos(2), .5 * dim(1), dim(2)], 'String', control.name, 'BackgroundColor', this.color); + +handle = uicontrol('Parent', this.id, 'Style', 'edit', 'Position', [pos(1) + .5 * dim(1), pos(2),.5 *dim(1),dim(2)],'String',control.value, 'BackgroundColor', [1,1,1]); +set(handle, 'Callback', {@callback, this, control.name}); + +function callback(handle, ~, this, name) + +string = get(handle, 'String'); +value = str2double(string); + +this.controls.(name).value = value; +callback = this.controls.(name).callback; + +if ~isempty(callback) + if isa(callback, 'cell') + cb = callback{1}; + args = callback(2:end); + else + cb = callback; + args = {}; + end + cb(this, args{:}); +end \ No newline at end of file diff --git a/+AMF/@GridUI/renderListBox.m b/+AMF/@GridUI/renderListBox.m new file mode 100644 index 0000000..9a68390 --- /dev/null +++ b/+AMF/@GridUI/renderListBox.m @@ -0,0 +1,35 @@ +function handle = renderEdit(this, control) + +UISize = size(this); + +xpos = control.pos(2) * this.scale; +ypos = UISize(1) - control.pos(1) * this.scale - this.scale * 2; +xsize = control.size(2) * this.scale; +ysize = control.size(1) * this.scale; + +pos = [xpos, ypos]; +dim = [xsize, ysize]; + +label = uicontrol('Parent', this.id, 'Style', 'text', 'Position', [pos(1), pos(2), dim(1), this.scale], 'String', control.name, 'BackgroundColor', this.color); + +handle = uicontrol('Parent', this.id, 'Style', 'listbox', 'Position', [pos(1), pos(2)-dim(2), dim(1), dim(2)],'String',control.value, 'Value', 1, 'BackgroundColor', [1,1,1]); +set(handle, 'Callback', {@callback, this, control.name}); + +function callback(handle, ~, this, name) + +string = get(handle, 'String'); +value = get(handle, 'Value'); + +this.controls.(name).value = string{value}; +callback = this.controls.(name).callback; + +if ~isempty(callback) + if isa(callback, 'cell') + cb = callback{1}; + args = callback(2:end); + else + cb = callback; + args = {}; + end + cb(this, args{:}); +end \ No newline at end of file diff --git a/+AMF/@GridUI/size.m b/+AMF/@GridUI/size.m new file mode 100644 index 0000000..7bf0a64 --- /dev/null +++ b/+AMF/@GridUI/size.m @@ -0,0 +1,3 @@ +function dim = size(this) + +dim = this.dim * this.scale; \ No newline at end of file diff --git a/+AMF/@Model/Model.m b/+AMF/@Model/Model.m new file mode 100644 index 0000000..1988a35 --- /dev/null +++ b/+AMF/@Model/Model.m @@ -0,0 +1,146 @@ +classdef Model < handle + properties + name + specification + dataset + + compilePrefix + compileDir + resultsDir + + functions + + template + list + ref + + predictors + constants + inputs + parameters + states + reactions + + fitParameters + observableStates + observableReactions + observableStatesData + observableReactionsData + observables + mStruct + iStruct + dStruct + + predictor + + time + fitTime + + options + result + + currTimeStep + end + methods + function this = Model(modelFile) + this.name = modelFile; + this.specification = feval(modelFile); + + this.compileDir = 'temp/'; + this.compilePrefix = ['C_', this.name]; + + if ~exist(this.compileDir, 'dir') + mkdir(this.compileDir); + end + addpath(this.compileDir); + + this.resultsDir = 'results/'; + + if ~exist(this.resultsDir, 'dir') + mkdir(this.resultsDir); + end + addpath(this.resultsDir); + + this.functions.ODE = str2func([this.compilePrefix, '_ODE']); + this.functions.ODEMex = str2func([this.compilePrefix, '_ODEMEX']); + this.functions.ODEC = str2func([this.compilePrefix, '_ODEC']); + this.functions.reactions = str2func([this.compilePrefix, '_REACTIONS']); + this.functions.inputs = str2func([this.compilePrefix, '_INPUTS']); + this.functions.reg = []; + this.functions.err = @AMF.errFun; + this.functions.errStep = @AMF.errFunStep; + + addComponents(this, 'PREDICTOR', this.specification, @AMF.ModelPredictor); + addComponents(this, 'CONSTANTS', this.specification, @AMF.ModelConstant); + addComponents(this, 'INPUTS', this.specification, @AMF.ModelInput); + addComponents(this, 'PARAMETERS', this.specification, @AMF.ModelParameter); + addComponents(this, 'STATES', this.specification, @AMF.ModelState); + addComponents(this, 'REACTIONS', this.specification, @AMF.ModelReaction); + + % component list + this.list = struct2cell(this.ref); + + % component groups + this.predictor = getAll(this, 'predictor'); + this.constants = getAll(this, 'constants'); + this.inputs = getAll(this, 'inputs'); + this.parameters = getAll(this, 'parameters'); + this.states = getAll(this, 'states'); + this.reactions = getAll(this, 'reactions'); + + % derived component groups + this.fitParameters = this.parameters(logical([this.parameters.fit])); + + % --- + + % default options + this.options.optimset = optimset('MaxIter',1e3,'Display','off','MaxFunEvals',1e5,'TolX',1e-8,'TolFun',1e-8); + this.options.odeTol = [1e-12 1e-12 100]; + this.options.useMex = 0; + % TODO: odeset + this.options.parScale = [2 -2]; + this.options.numIter = 1; + this.options.lab1 = .1; + this.options.seed = 1; + this.options.numTimeSteps = this.predictor.val(end) - this.predictor.val(1); + this.options.SSTime = 1000; + this.options.savePrefix = ''; + this.options.randPars = 1; + this.options.randData = 1; + + this.options.interpMethod = 'linear'; + + this.currTimeStep = 0; + + this.time = getTime(this); + + this.result.oxi = []; + this.result.ofi = []; + this.result.oxdi = []; + this.result.ofdi = []; + this.result.pidx = []; + this.result.lb = []; + this.result.p = []; + this.result.x = []; + this.result.u = []; + this.result.v = []; + this.result.sse = []; + this.result.dt = []; + this.result.dd = []; + this.result.ds = []; + this.result.idd = []; + this.result.ids = []; + this.result.xinit = []; + this.result.xcurr = []; + this.result.pcurr = [this.parameters.init]; + this.result.pinit = []; + this.result.pprev = []; + this.result.vcurr = []; + this.result.nfp = length(this.fitParameters); + this.result.time = []; + this.result.uidx = []; + this.result.upidx = []; + this.result.uvec = []; + end + end +end \ No newline at end of file diff --git a/+AMF/@Model/addComponents.m b/+AMF/@Model/addComponents.m new file mode 100644 index 0000000..de84cef --- /dev/null +++ b/+AMF/@Model/addComponents.m @@ -0,0 +1,13 @@ +function this = addComponents(this, groupName, spec, compType) + +this.template.(groupName) = func2str(compType); + +if ~isfield(spec, groupName) + return +end + +compSpec = spec.(groupName); +for i = 1:size(compSpec, 1) + name = compSpec{i, 1}; + this.ref.(name) = compType(i, compSpec{i, :}); +end \ No newline at end of file diff --git a/+AMF/@Model/compile.m b/+AMF/@Model/compile.m new file mode 100644 index 0000000..1274c81 --- /dev/null +++ b/+AMF/@Model/compile.m @@ -0,0 +1,83 @@ +function this = compile(this) + +prefix = 'C'; + +% +% ODE +% + +fn = [prefix, '_', this.name, '_ODE']; +fid = fopen([fn, '.m'], 'w'); + +fprintf(fid, ['function dxdt = ', fn, '(t,x,p,m)\n']); + +[states, n] = filterByType(this, 'State'); +for i = 1:n + comp = states(i); + fprintf(fid, ['dxdt(', num2str(states(i).index) ,')', ' = ' ,comp.compiledExpr, ';\n']); +end + +fprintf(fid, '\ndxdt = dxdt(:);'); +fclose(fid); + +% % +% % Inputs +% % +% +% fn = [prefix, '_', this.name, '_Inputs']; +% fid = fopen([fn, '.m'], 'w'); +% +% fprintf(fid, ['function u = ', fn, '(t,m)\n']); +% +% [inputs, n] = filterByType(this, 'Input'); +% for i = 1:n +% comp = inputs(i); +% fprintf(fid, [comp.compiledVar, ' = ' ,comp.compiledExpr, ';\n']); +% end +% +% fclose(fid); +% +% % +% % Reactions +% % +% +% fn = [prefix, '_', this.name, '_Reactions']; +% fid = fopen([fn, '.m'], 'w'); +% +% fprintf(fid, ['function v = ', fn, '(t,x,p,m)\n']); +% +% [reactions, n] = filterByType(this, 'Reaction'); +% for i = 1:n +% comp = reactions(i); +% fprintf(fid, [comp.compiledVar, ' = ' ,comp.compiledExpr, ';\n']); +% end +% +% fclose(fid); +% +% % EXPERIMENTAL +% +% % +% % Constraints +% % +% +% fn = [prefix, '_', this.name, '_Constraints']; +% fid = fopen([fn, '.m'], 'w'); +% +% fprintf(fid, ['function E = ', fn, '(model)\n']); +% +% n = size(this.spec.CONSTRAINTS, 1); +% for i = 1:n +% expr = this.spec.CONSTRAINTS{i,1}; +% weight = this.spec.CONSTRAINTS{i,2}; +% +% vars = symvar(expr); +% for j = 1:length(vars) +% var = char(vars(j)); +% expr = regexprep(expr, var, ['model.comps.', var]); +% end +% +% fprintf(fid, ['E(', num2str(i) ,') = ' ,expr, '* ', num2str(weight),';\n']); +% end +% +% fprintf(fid, 'E = E(:);\n'); +% fclose(fid); \ No newline at end of file diff --git a/+AMF/@Model/compileAll.m b/+AMF/@Model/compileAll.m new file mode 100644 index 0000000..de0e299 --- /dev/null +++ b/+AMF/@Model/compileAll.m @@ -0,0 +1,14 @@ +function compileAll(this) + +clear mex + +compileODE(this); +compileODEMex(this); +compileInputs(this); +compileReactions(this); + +if this.options.useMex + compileMex(this); +end + +addpath(this.compileDir); \ No newline at end of file diff --git a/+AMF/@Model/compileInputs.m b/+AMF/@Model/compileInputs.m new file mode 100644 index 0000000..db2f40f --- /dev/null +++ b/+AMF/@Model/compileInputs.m @@ -0,0 +1,24 @@ +function this = compileInputs(this) + +if isempty(this.inputs) + return +end + +import AMF.utils.writeFile + +% +% ODE +% + +fn = char(this.functions.inputs); + +header = ['function u = ', fn, '(t,uv,m)\n\n']; + +for i = 1:length(this.inputs) + comp = this.inputs(i); + IC{i} = ['u(', num2str(comp.index), ') = interp1(uv(m.u.', comp.name, '_t), ', 'uv(m.u.', comp.name, '), t, ''', comp.method, ''', ''extrap'');\n']; +end + +content = [IC{:}]; + +writeFile([this.compileDir, fn, '.m'], [header, content]); \ No newline at end of file diff --git a/+AMF/@Model/compileMex.m b/+AMF/@Model/compileMex.m new file mode 100644 index 0000000..12ba350 --- /dev/null +++ b/+AMF/@Model/compileMex.m @@ -0,0 +1,17 @@ +function compileMex(this) + +% ----------------------------------------------------- +% MEX +% + +if exist('convertToC') && exist('compileC') + clear mex + + inputFn = func2str(this.functions.ODEMex); + outputFn = func2str(this.functions.ODEC); + + convertToC(getInputStructMex(this), [inputFn, '.m']); + compileC([pwd, '\', this.compileDir , outputFn]); +else + fprintf('Add paths of odemex toolbox before compiling the model!\n'); +end \ No newline at end of file diff --git a/+AMF/@Model/compileODE.m b/+AMF/@Model/compileODE.m new file mode 100644 index 0000000..0d70dad --- /dev/null +++ b/+AMF/@Model/compileODE.m @@ -0,0 +1,53 @@ +function this = compileODE(this) + +import AMF.utils.writeFile + +% +% ODE +% + +fn = char(this.functions.ODE); + +header = ['function dxdt = ', fn, '(t,x,p,u,m)\n\n']; + +CC = {}; +for i = 1:length(this.constants) + comp = this.constants(i); + CC{i} = [comp.name, ' = m.c.', comp.name, ';\n']; +end + +IC = {}; +for i = 1:length(this.inputs) + comp = this.inputs(i); + IC{i} = [comp.name, ' = interp1(u(m.u.', comp.name, '_t), ', 'u(m.u.', comp.name, '), t, ''', comp.method, ''', ''extrap'');\n']; +end + +SC = {}; +for i = 1:length(this.states) + comp = this.states(i); + SC{i} = [comp.name, ' = x(m.s.', comp.name, ');\n']; +end + +PC = {}; +for i = 1:length(this.parameters) + comp = this.parameters(i); + PC{i} = [comp.name, ' = p(m.p.', comp.name, ');\n']; +end + +RC = {}; +for i = 1:length(this.reactions) + comp = this.reactions(i); + RC{i} = [comp.name, ' = ', comp.expr, ';\n']; +end + +OC = {}; +for i = 1:length(this.states) + comp = this.states(i); + OC{i} = ['dxdt(', num2str(comp.index), ') = ', comp.expr, ';\n']; +end + +footer = '\ndxdt = dxdt(:);'; + +content = [IC{:}, '\n', CC{:}, '\n', SC{:}, '\n', PC{:}, '\n', RC{:}, '\n', OC{:}]; + +writeFile([this.compileDir, fn, '.m'], [header, content, footer]); \ No newline at end of file diff --git a/+AMF/@Model/compileODEMex.m b/+AMF/@Model/compileODEMex.m new file mode 100644 index 0000000..33a7f30 --- /dev/null +++ b/+AMF/@Model/compileODEMex.m @@ -0,0 +1,56 @@ +function this = compileODE(this) + +import AMF.utils.writeFile +import AMF.utils.mexify2 + +% +% ODE +% + +fn = char(this.functions.ODEMex); + +header = ['function dxdt = ', fn, '(t,x,p,u,m)\n\n']; + +CC = {}; +for i = 1:length(this.constants) + comp = this.constants(i); + CC{i} = [comp.name, ' = m.c.', comp.name, ';\n']; +end + +IC = {}; +for i = 1:length(this.inputs) + comp = this.inputs(i); + IC{i} = [comp.name, ' = interpolate( &u(m.u.', comp.name, '_t), ', '&u(m.u.', comp.name, '), ', num2str(length(comp.initVal)),', t, 1);\n']; +end + +% interpolate( &u(myStruct.u.time1), &u(myStruct.u.linear1), 6, t, 1 ); + +SC = {}; +for i = 1:length(this.states) + comp = this.states(i); + SC{i} = [comp.name, ' = x(m.s.', comp.name, ');\n']; +end + +PC = {}; +for i = 1:length(this.parameters) + comp = this.parameters(i); + PC{i} = [comp.name, ' = p(m.p.', comp.name, ');\n']; +end + +RC = {}; +for i = 1:length(this.reactions) + comp = this.reactions(i); + RC{i} = [comp.name, ' = ', mexify2(comp.expr, comp.name), ';\n']; +end + +OC = {}; +for i = 1:length(this.states) + comp = this.states(i); + OC{i} = ['dxdt(', num2str(comp.index), ') = ', mexify2(comp.expr, comp.name), ';\n']; +end + +footer = '\ndxdt = dxdt(:);'; + +content = [IC{:}, '\n', CC{:}, '\n', SC{:}, '\n', PC{:}, '\n', RC{:}, '\n', OC{:}]; + +writeFile([this.compileDir, fn, '.m'], [header, content, footer]); \ No newline at end of file diff --git a/+AMF/@Model/compileReactions.m b/+AMF/@Model/compileReactions.m new file mode 100644 index 0000000..840f5a1 --- /dev/null +++ b/+AMF/@Model/compileReactions.m @@ -0,0 +1,51 @@ +function this = compileReactions(this) + +import AMF.utils.writeFile + +% +% ODE +% + +fn = char(this.functions.reactions); + +header = ['function v = ', fn, '(t,x,p,u,m)\n\n']; + +CC = {}; +for i = 1:length(this.constants) + comp = this.constants(i); + CC{i} = [comp.name, ' = m.c.', comp.name, ';\n']; +end + +IC = {}; +for i = 1:length(this.inputs) + comp = this.inputs(i); + IC{i} = [comp.name, ' = interp1(u(m.u.', comp.name, '_t), ', 'u(m.u.', comp.name, '), t, ''', comp.method, ''', ''extrap'');\n']; +end + +SC = {}; +for i = 1:length(this.states) + comp = this.states(i); + SC{i} = [comp.name, ' = x(m.s.', comp.name, ');\n']; +end + +PC = {}; +for i = 1:length(this.parameters) + comp = this.parameters(i); + PC{i} = [comp.name, ' = p(m.p.', comp.name, ');\n']; +end + +RC = {}; +for i = 1:length(this.reactions) + comp = this.reactions(i); + RC{i} = [comp.name, ' = ', AMF.utils.mexify2(comp.expr, comp.name), ';\n']; +end + +RRC = {}; +for i = 1:length(this.reactions); + comp = this.reactions(i); + RRC{i} = ['v(', num2str(comp.index), ') = ', comp.name, ';\n']; +end + +content = [IC{:}, '\n', CC{:}, '\n', SC{:}, '\n', PC{:}, '\n', RC{:}, '\n', RRC{:}]; + +writeFile([this.compileDir, fn, '.m'], [header, content]); \ No newline at end of file diff --git a/+AMF/@Model/computeAll.m b/+AMF/@Model/computeAll.m new file mode 100644 index 0000000..45ac316 --- /dev/null +++ b/+AMF/@Model/computeAll.m @@ -0,0 +1,38 @@ +function this = computeAll(this, t, x0, p, ts) + +if nargin < 5, ts = 0; end + +% compute +x = computeStates(this, t, x0, p); + +if ts > 0 + t = t(end); + x = x(end,:); +end + +u = this.computeInputs(t); +v = this.computeReactions(t, x, p); + +% update the component current values +for i = 1:length(this.states) + this.states(i).curr = x(:,i); +end +for i = 1:length(this.reactions) + this.reactions(i).curr = v(:,i); +end +for i = 1:length(this.inputs) + this.inputs(i).curr = u(:,i); +end + +% store the values in the trajectories +if ts > 0 + this.result.x(ts,:) = x; + this.result.v(ts,:) = v; + if ~isempty(this.inputs) + this.result.u(ts,:) = u; + end +else + this.result.x = x; + this.result.v = v; + this.result.u = u; +end \ No newline at end of file diff --git a/+AMF/@Model/computeInputs.m b/+AMF/@Model/computeInputs.m new file mode 100644 index 0000000..85396a8 --- /dev/null +++ b/+AMF/@Model/computeInputs.m @@ -0,0 +1,12 @@ +function u = computeInputs(this, time, uvec) + +if isempty(this.inputs) + u = []; + return +end + +m = this.mStruct; +for i = 1:length(time) + t = time(i); + u(i,:) = this.functions.inputs(t, uvec, m); +end \ No newline at end of file diff --git a/+AMF/@Model/computeReactions.m b/+AMF/@Model/computeReactions.m new file mode 100644 index 0000000..f02f6b5 --- /dev/null +++ b/+AMF/@Model/computeReactions.m @@ -0,0 +1,9 @@ +function v = computeReactions(this, t, x, p, uvec) + +n = length(t); +v = zeros(n, length(this.reactions)); + +m = this.mStruct; +for i = 1:n + v(i,:) = this.functions.reactions(t(i), x(i,:), p, uvec, m); +end \ No newline at end of file diff --git a/+AMF/@Model/computeStates.m b/+AMF/@Model/computeStates.m new file mode 100644 index 0000000..497eed9 --- /dev/null +++ b/+AMF/@Model/computeStates.m @@ -0,0 +1,9 @@ +function x = computeStates(this, t, x0, p, uvec) + +if ~this.options.useMex + mStruct = this.mStruct; + [~, x] = ode15s(this.functions.ODE, t, x0, this.options.odeTol, p, uvec, mStruct); +else + [~,x] = this.functions.ODEC(t, x0, p, uvec, this.options.odeTol); + x = x'; +end \ No newline at end of file diff --git a/+AMF/@Model/filter.m b/+AMF/@Model/filter.m new file mode 100644 index 0000000..7c5de22 --- /dev/null +++ b/+AMF/@Model/filter.m @@ -0,0 +1,4 @@ +function compList = filter(this, func) + +idx = cellfun(func, this.list); +compList = this.list(idx); \ No newline at end of file diff --git a/+AMF/@Model/get.m b/+AMF/@Model/get.m new file mode 100644 index 0000000..ab75e4c --- /dev/null +++ b/+AMF/@Model/get.m @@ -0,0 +1,7 @@ +function comps = get(this, varargin) + +for i = 1:length(varargin) + compName = varargin{i}; + + comps(i) = this.ref.(compName); +end \ No newline at end of file diff --git a/+AMF/@Model/getAll.m b/+AMF/@Model/getAll.m new file mode 100644 index 0000000..09f0073 --- /dev/null +++ b/+AMF/@Model/getAll.m @@ -0,0 +1,10 @@ +function [comps, n] = getAll(this, type) + +compClass = this.template.(upper(type)); + +idx = cellfun(@(comp) isa(comp, compClass), this.list); + +comps = this.list(idx); +comps = [comps{:}]; + +n = length(comps); \ No newline at end of file diff --git a/+AMF/@Model/getInputStruct.m b/+AMF/@Model/getInputStruct.m new file mode 100644 index 0000000..d3c135d --- /dev/null +++ b/+AMF/@Model/getInputStruct.m @@ -0,0 +1,7 @@ +function mStruct = getInputStruct(this) + +for state = this.states, mStruct.s.(state.name) = state.index; end +for param = this.parameters, mStruct.p.(param.name) = param.index; end +for constant = this.constants, mStruct.c.(constant.name) = constant.val; end +for reaction = this.reactions, mStruct.v.(reaction.name) = reaction.index; end +for input = this.inputs, mStruct.u.(input.name) = input.index; end diff --git a/+AMF/@Model/getInputStructMex.m b/+AMF/@Model/getInputStructMex.m new file mode 100644 index 0000000..30ef54f --- /dev/null +++ b/+AMF/@Model/getInputStructMex.m @@ -0,0 +1,14 @@ +function mStruct = getInputStructMex(this) + +for state = this.states, mStruct.s.(state.name) = state.index; end +for param = this.parameters, mStruct.p.(param.name) = param.index; end +for constant = this.constants, mStruct.c.(constant.name) = constant.val; end + +% TODO: fix allocation +n = 1; +for input = this.inputs + mStruct.u.(input.name) = n:n+length(input.initVal)-1; + n = n+length(input.initVal); + mStruct.u.([input.name, '_t']) = n:n+length(input.initTime)-1; + n = n+length(input.initTime); +end diff --git a/+AMF/@Model/getInputsMex.m b/+AMF/@Model/getInputsMex.m new file mode 100644 index 0000000..b1ca5ef --- /dev/null +++ b/+AMF/@Model/getInputsMex.m @@ -0,0 +1,6 @@ +function u = getInputsMex(this) + +u = []; +for input = this.inputs + u = [u, input.initVal(:)', input.initTime(:)']; +end \ No newline at end of file diff --git a/+AMF/@Model/getResiduals.m b/+AMF/@Model/getResiduals.m new file mode 100644 index 0000000..938dbb1 --- /dev/null +++ b/+AMF/@Model/getResiduals.m @@ -0,0 +1,52 @@ +function resid = getResiduals(this, ts) + +import AMF.regFun + +if nargin < 2, ts = 0; end + +% observables = filter(this, @isObservable); +observables = this.observables; + +% compute error from observables +resid = 0; +for i = 1:length(observables) + comp = observables{i}; + + if ts > 0 + err = comp.data.val(ts)-comp.curr(:); + + if any(comp.data.std) + err = err ./ comp.data.std(ts); + else + err = err ./ comp.data.val(ts); + end + else + idx = comp.data.fitIdx; + err = comp.data.src.val(:)-comp.curr(idx); + + if any(comp.data.std) + err = err ./ comp.data.src.std(:); + else + err = err ./ comp.data.src.val(:); + end + end + + resid = [resid; err]; +end + +% pad error to prevent lsqnonlin warnings +resid = [resid; zeros(length(this.fitParameters), 1)]; + +% standard ADAPT regularization +regADAPT = regFun(this); +resid = [resid; regADAPT(:)]; + +% additional regularization +if ~isempty(this.functions.reg) + reg = this.functions.reg(this); + resid = [resid; reg(:)]; +end + +% remove NaNs (caused by single time point data or zero divisions in model reactions or state derivatives) +resid(isnan(resid)) = 0; +resid(isinf(resid)) = 0; \ No newline at end of file diff --git a/+AMF/@Model/getResult.m b/+AMF/@Model/getResult.m new file mode 100644 index 0000000..3691623 --- /dev/null +++ b/+AMF/@Model/getResult.m @@ -0,0 +1,22 @@ +function result = getResult(this) + +result.predictor = getStruct(this.predictor); +result.parameters = getStruct(this.parameters); +result.states = getStruct(this.states); +result.reactions = getStruct(this.reactions); + +result.options = this.options; + +if ~isempty(this.constants) + result.constants = getStruct(this.constants); +else + result.constants = []; +end + +if ~isempty(this.inputs) + result.inputs = getStruct(this.inputs); +else + result.inputs = []; +end + +result.time = getTime(this); \ No newline at end of file diff --git a/+AMF/@Model/getTime.m b/+AMF/@Model/getTime.m new file mode 100644 index 0000000..d2df7d9 --- /dev/null +++ b/+AMF/@Model/getTime.m @@ -0,0 +1,18 @@ +function t = getTime(this, ts) + +if nargin < 2, ts = 0; end + +t = this.predictor.val(1):this.predictor.val(end)/this.options.numTimeSteps:this.predictor.val(end); + +if ts > 0 + SSTime = this.options.SSTime; + + if ts > 1 + t = [t(ts-1); (t(ts-1)+t(ts))/2; t(ts)]; + else + t0 = t(ts)-SSTime; + t = [t0; (t0+t(ts))/2; t(ts)]; + end +end + +t = t(:); \ No newline at end of file diff --git a/+AMF/@Model/initializeObservables.m b/+AMF/@Model/initializeObservables.m new file mode 100644 index 0000000..69c840a --- /dev/null +++ b/+AMF/@Model/initializeObservables.m @@ -0,0 +1,8 @@ +function this = initializeObservables(this) + +observables = filter(this, @isObservable); + +for i = 1:length(observables) + comp = observables{i}; + comp.init = comp.data.val(1); +end \ No newline at end of file diff --git a/+AMF/@Model/initiateExperiment.asv b/+AMF/@Model/initiateExperiment.asv new file mode 100644 index 0000000..e410d71 --- /dev/null +++ b/+AMF/@Model/initiateExperiment.asv @@ -0,0 +1,25 @@ +randfunction this = initiateExperiment(this, dataset) + +this.dataset = dataset; +interp(this.dataset, 0, 'spline'); + +observables = filter(this.dataset, @isObservable); + +this.fitTime = []; + +for i = 1:length(observables) + dataField = observables{i}; + this.fitTime = [this.fitTime, dataField.src.time]; +end + +this.fitTime = sort(unique(this.fitTime)); + +for i = 1:length(observables) + dataField = observables{i}; + fieldName = dataField.name; + + comp = this.ref.(fieldName); + comp.data = dataField; + + dataField.fitIdx = arrayfun(@(t) find(this.fitTime == t), dataField.src.time); +end \ No newline at end of file diff --git a/+AMF/@Model/initiateExperiment.m b/+AMF/@Model/initiateExperiment.m new file mode 100644 index 0000000..934ab02 --- /dev/null +++ b/+AMF/@Model/initiateExperiment.m @@ -0,0 +1,29 @@ +function this = initiateExperiment(this, dataset) + +this.dataset = dataset; + +observables = filter(this.dataset, @isObservable); + +for i = 1:length(observables) + df = observables{i}; + name = df.name; + + this.ref.(name).obs = 1; + this.ref.(name).dataIdx = df.index; +end + +% save observable indices (states, reactions corresponding data) +this.result.oxi = logical([this.states.obs]); +this.result.ofi = logical([this.reactions.obs]); +this.result.oxdi = [this.states.dataIdx]; +this.result.ofdi = [this.reactions.dataIdx]; + +% +dt = getFitTime(this.dataset); +[dd, ds] = getFitData(this.dataset); + +this.result.dt = dt(:); +this.result.dd = dd; +this.result.ds = ds; + +this.dStruct = getDataStruct(this.dataset); \ No newline at end of file diff --git a/+AMF/@Model/parseAll.m b/+AMF/@Model/parseAll.m new file mode 100644 index 0000000..44f31b2 --- /dev/null +++ b/+AMF/@Model/parseAll.m @@ -0,0 +1,10 @@ +function this = parseAll(this) + +parseConstants(this); +parseStates(this); +parseReactions(this); +parseParameters(this); +parseInputs(this); + +this.iStruct = getInputStruct(this); +this.mStruct = getInputStructMex(this); \ No newline at end of file diff --git a/+AMF/@Model/parseConstants.m b/+AMF/@Model/parseConstants.m new file mode 100644 index 0000000..d177b45 --- /dev/null +++ b/+AMF/@Model/parseConstants.m @@ -0,0 +1,23 @@ +function this = parseConstants(this) + +if isempty(this.constants) + return +end + +for comp = this.constants + + switch class(comp.expr) + + case 'char' + if isempty(this.dataset) + error('Can not obtain constant value from dataset.'); + end + + comp.val = this.dataset.ref.(comp.expr).src.val(1); + + case 'double' + comp.val = comp.expr; + + end + +end \ No newline at end of file diff --git a/+AMF/@Model/parseInputs.m b/+AMF/@Model/parseInputs.m new file mode 100644 index 0000000..36f7555 --- /dev/null +++ b/+AMF/@Model/parseInputs.m @@ -0,0 +1,46 @@ +function this = parseInputs(this) + +if isempty(this.inputs) + return +end + +uidx = []; +upidx = []; +uvec = []; + +for comp = this.inputs + + switch upper(comp.type) + case 'DATA' + if isempty(this.dataset) + error('Can not obtain input value from dataset.'); + end + + dataField = this.dataset.ref.(comp.args{1}); + comp.initVal = dataField.curr.val; + comp.initTime = dataField.src.time; + + uidx = [uidx zeros(1,length(comp.initVal)) zeros(1,length(comp.initTime))]; + uvec = [uvec comp.initVal(:)' comp.initTime(:)']; + + case 'FUNCTION' + t = comp.args{1}; +% params = get(this, comp.args{2:end}); + pnames = comp.args(2:end); + + pidx = cellfun(@(p) this.ref.(p).index, pnames); + upidx = [upidx pidx]; + + comp.initTime = t; +% comp.initVal = [params.curr]; + comp.initVal = this.result.pcurr(pidx); + + uidx = [uidx ones(1, length(pnames)) zeros(1,length(comp.initTime))]; + uvec = [uvec comp.initVal(:)' comp.initTime(:)']; + end + +end + +this.result.uidx = logical(uidx); +this.result.upidx = upidx; +this.result.uvec = uvec; \ No newline at end of file diff --git a/+AMF/@Model/parseParameters.m b/+AMF/@Model/parseParameters.m new file mode 100644 index 0000000..2ab51a5 --- /dev/null +++ b/+AMF/@Model/parseParameters.m @@ -0,0 +1,15 @@ +function this = parseParameters(this) + +for comp = this.parameters + + if isa(comp.expr, 'char') + sourcePar = this.ref.(comp.expr); + comp.init = sourcePar.init; + end +end + +this.result.pcurr = [this.parameters.init]; +this.result.pinit = [this.parameters.init]; +this.result.pidx = logical([this.parameters.fit]); +this.result.lb = [this.parameters.lb]; +this.result.ub = [this.parameters.ub]; \ No newline at end of file diff --git a/+AMF/@Model/parseReactions.m b/+AMF/@Model/parseReactions.m new file mode 100644 index 0000000..20c0606 --- /dev/null +++ b/+AMF/@Model/parseReactions.m @@ -0,0 +1,3 @@ +function this = parseReactions(this) + +% \ No newline at end of file diff --git a/+AMF/@Model/parseStates.m b/+AMF/@Model/parseStates.m new file mode 100644 index 0000000..dd46e13 --- /dev/null +++ b/+AMF/@Model/parseStates.m @@ -0,0 +1,15 @@ +function this = parseStates(this) + +[dd, ~] = getInterpData(this.dataset, 0, 'spline'); +d = getDataStruct(this.dataset); + +for comp = this.states + + if isa(comp.initExpr, 'char') + dataCompName = comp.initExpr; + comp.init = dd(d.d.(dataCompName)); + end +end + +this.result.xinit = [this.states.init]; +this.result.xcurr = [this.states.init]; \ No newline at end of file diff --git a/+AMF/@Model/plot.m b/+AMF/@Model/plot.m new file mode 100644 index 0000000..0e6f332 --- /dev/null +++ b/+AMF/@Model/plot.m @@ -0,0 +1,52 @@ +function this = plot(this, name) + +comp = this.ref.(name); + +plot(this.time, comp.val, 'r'); + +if ~isempty(comp.data) + data.time = comp.data.src.time; + data.val = comp.data.src.val; + data.std = comp.data.src.std; + + hold on + if any(data.std) + errorbar(data.time, data.val, data.std, 'kx', 'LineWidth', 2); + else + plot(data.time, data.val, 'kx', 'LineWidth', 2); + end + hold off +end + +xlabel([this.predictor.unitType, ' [', this.predictor.unit, ']']); +xlim([comp.time(1) comp.time(end)]); + +if comp.label + title(comp.label); +else + title(comp.name); +end + +if comp.unit + ylabel(sprintf('%s [%s]', comp.unitType, comp.unit)); +else + ylabel(comp.unitType); +end + +% function this = plot(this, compName) +% +% comp = this.ref.(compName); +% +% plot(this.getTime(), comp.val); +% +% title(comp.label); +% xlabel([this.predictor.unitType, '[', this.predictor.unit, ']']); +% ylabel([comp.unitType, '[', comp.unit, ']']); +% +% if isObservable(comp); +% hold on; +% plot(comp.data); +% hold off; +% end +% +% xlim([this.predictor.val(1) this.predictor.val(end)]); \ No newline at end of file diff --git a/+AMF/@Model/plotAll.m b/+AMF/@Model/plotAll.m new file mode 100644 index 0000000..e7af686 --- /dev/null +++ b/+AMF/@Model/plotAll.m @@ -0,0 +1,10 @@ +function this = plotAll(this, type) + +comps = this.(type); +n = length(comps); +ns = sqrt(n); + +for i = 1:n + subplot(ceil(ns),ceil(ns),i); hold on; + plot(this, comps(i).name); +end \ No newline at end of file diff --git a/+AMF/@Model/randomizeData.m b/+AMF/@Model/randomizeData.m new file mode 100644 index 0000000..60ffa1a --- /dev/null +++ b/+AMF/@Model/randomizeData.m @@ -0,0 +1,10 @@ +function this = randomizeData(this) + +randomize(this.dataset); + +t = getTime(this); + +[idd, ids] = getInterpData(this.dataset, t, 'spline'); + +this.result.idd = idd; +this.result.ids = ids; \ No newline at end of file diff --git a/+AMF/@Model/randomizeParameters.m b/+AMF/@Model/randomizeParameters.m new file mode 100644 index 0000000..c0c4011 --- /dev/null +++ b/+AMF/@Model/randomizeParameters.m @@ -0,0 +1,15 @@ +function pcurr = randomizeParameters(this) + +np = length(this.fitParameters); + +smax = this.options.parScale(1); +smin = this.options.parScale(2); +pcurr = 10.^((smax-smin)*rand(np,1)+smin); + +for i = 1:np + this.fitParameters(i).init = pcurr(i); + this.fitParameters(i).curr = pcurr(i); +end + +this.result.pcurr = [this.parameters.init]; +this.result.pinit = [this.parameters.init]; \ No newline at end of file diff --git a/+AMF/@Model/saveTrajectory.m b/+AMF/@Model/saveTrajectory.m new file mode 100644 index 0000000..281d32b --- /dev/null +++ b/+AMF/@Model/saveTrajectory.m @@ -0,0 +1,19 @@ +function this = saveTrajectory(this) + +x = this.result.x; +v = this.result.v; +u = this.result.u; +p = this.result.p; + +for i = 1:length(this.states) + this.states(i).val = x(:,i); +end +for i = 1:length(this.reactions) + this.reactions(i).val = v(:,i); +end +for i = 1:length(this.inputs) + this.inputs(i).val = u(:,i); +end +for i = 1:length(this.fitParameters) + this.fitParameters(i).val = p(:,i); +end \ No newline at end of file diff --git a/+AMF/@Model/setFitParameters.m b/+AMF/@Model/setFitParameters.m new file mode 100644 index 0000000..98d7be6 --- /dev/null +++ b/+AMF/@Model/setFitParameters.m @@ -0,0 +1,14 @@ +function this = setFitParameters(this, t, p, ts) + +if nargin < 4, ts = 0; end + +for i = 1:length(this.fitParameters) + this.fitParameters(i).curr = p(:,i); +end +parseInputs(this); + +if ts > 0 + this.result.p(ts,:) = p; +else + this.result.p = p; +end \ No newline at end of file diff --git a/+AMF/@Model/setPredictor.m b/+AMF/@Model/setPredictor.m new file mode 100644 index 0000000..cac7a99 --- /dev/null +++ b/+AMF/@Model/setPredictor.m @@ -0,0 +1,4 @@ +function this = setPredictor(this, name) + +this.predictor = this.ref.(name); +% parseAll(this); \ No newline at end of file diff --git a/+AMF/@Model/setTimeStep.m b/+AMF/@Model/setTimeStep.m new file mode 100644 index 0000000..7803457 --- /dev/null +++ b/+AMF/@Model/setTimeStep.m @@ -0,0 +1,3 @@ +function this = setTimeStep(this, ts) + +this.currTimeStep = ts; \ No newline at end of file diff --git a/+AMF/@ModelComponent/ModelComponent.m b/+AMF/@ModelComponent/ModelComponent.m new file mode 100644 index 0000000..1dda02d --- /dev/null +++ b/+AMF/@ModelComponent/ModelComponent.m @@ -0,0 +1,45 @@ +classdef ModelComponent < handle + properties + index + name + expr + + % data + data + dataIdx + obs = 0 + dt + dd + ds + idd + ids + + % computed + time + init + prev + curr + val + + % meta + unitType + unit + label + end + methods + function this = ModelComponent(index, name, metaData) + this.index = index; + this.name = name; + +% this.data.field = []; +% this.data.val = []; +% this.data.std = []; + + if ~isempty(metaData) + this.unitType = metaData{1}; + this.unit = metaData{2}; + this.label = metaData{3}; + end + end + end +end \ No newline at end of file diff --git a/+AMF/@ModelComponent/filter.m b/+AMF/@ModelComponent/filter.m new file mode 100644 index 0000000..ddf172e --- /dev/null +++ b/+AMF/@ModelComponent/filter.m @@ -0,0 +1,4 @@ +function comps = filter(compArray, func) + +idx = logical(func(compArray)); +comps = compArray(idx); \ No newline at end of file diff --git a/+AMF/@ModelComponent/getStruct.m b/+AMF/@ModelComponent/getStruct.m new file mode 100644 index 0000000..9c3bd9e --- /dev/null +++ b/+AMF/@ModelComponent/getStruct.m @@ -0,0 +1,15 @@ +function s = getStruct(compArr) + +for i = 1:length(compArr) + comp = compArr(i); + + props = properties(comp); + for j = 1:length(props) + propName = props{j}; + s(i).(propName) = comp.(propName); + end + + if isa(s(i).data, 'AMF.DataField') + s(i).data = getStruct(s(i).data); + end +end \ No newline at end of file diff --git a/+AMF/@ModelComponent/isObservable.m b/+AMF/@ModelComponent/isObservable.m new file mode 100644 index 0000000..ca0d5d7 --- /dev/null +++ b/+AMF/@ModelComponent/isObservable.m @@ -0,0 +1,3 @@ +function filter = isObservable(compArray) + +filter = logical([compArray.obs]); \ No newline at end of file diff --git a/+AMF/@ModelComponent/plot.m b/+AMF/@ModelComponent/plot.m new file mode 100644 index 0000000..67ac027 --- /dev/null +++ b/+AMF/@ModelComponent/plot.m @@ -0,0 +1,3 @@ +function this = plot(this) + +plot(this.time, this.curr, 'b'); \ No newline at end of file diff --git a/+AMF/@ModelConstant/ModelConstant.m b/+AMF/@ModelConstant/ModelConstant.m new file mode 100644 index 0000000..cf7bc6f --- /dev/null +++ b/+AMF/@ModelConstant/ModelConstant.m @@ -0,0 +1,11 @@ +classdef ModelConstant < AMF.ModelComponent + properties + end + methods + function this = ModelConstant(index, name, expr, meta) + this = this@AMF.ModelComponent(index, name, meta); + + this.expr = expr; + end + end +end \ No newline at end of file diff --git a/+AMF/@ModelInput/ModelInput.m b/+AMF/@ModelInput/ModelInput.m new file mode 100644 index 0000000..a2bb691 --- /dev/null +++ b/+AMF/@ModelInput/ModelInput.m @@ -0,0 +1,24 @@ +classdef ModelInput < AMF.ModelComponent + properties + type + func + predictor + parameters + method + + initVal + initTime + + args + pidx + end + methods + function this = ModelInput(index, name, type, args, method, meta) + this = this@AMF.ModelComponent(index, name, meta); + + this.type = type; + this.args = args; + this.method = method; + end + end +end \ No newline at end of file diff --git a/+AMF/@ModelParameter/ModelParameter.m b/+AMF/@ModelParameter/ModelParameter.m new file mode 100644 index 0000000..0a0d5eb --- /dev/null +++ b/+AMF/@ModelParameter/ModelParameter.m @@ -0,0 +1,27 @@ +classdef ModelParameter < AMF.ModelComponent + properties + fit + lb + ub + end + methods + function this = ModelParameter(index, name, fit, expr, bnd, meta) + this = this@AMF.ModelComponent(index, name, meta); + + this.expr = expr; + if isa(expr, 'double') + this.init = expr; + end + + this.fit = fit; + + if isempty(bnd) + this.lb = 0; + this.ub = inf; + else + this.lb = bnd(1); + this.ub = bnd(2); + end + end + end +end \ No newline at end of file diff --git a/+AMF/@ModelParameter/isFitParameter.m b/+AMF/@ModelParameter/isFitParameter.m new file mode 100644 index 0000000..4e4c4a2 --- /dev/null +++ b/+AMF/@ModelParameter/isFitParameter.m @@ -0,0 +1,3 @@ +function filter = isFitParameter(compArray) + +filter = logical([compArray.fit]); \ No newline at end of file diff --git a/+AMF/@ModelPredictor/ModelPredictor.m b/+AMF/@ModelPredictor/ModelPredictor.m new file mode 100644 index 0000000..d762c12 --- /dev/null +++ b/+AMF/@ModelPredictor/ModelPredictor.m @@ -0,0 +1,11 @@ +classdef ModelPredictor < AMF.ModelComponent + properties + end + methods + function this = ModelPredictor(index, name, val, meta) + this = this@AMF.ModelComponent(index, name, meta); + + this.val = val(:); + end + end +end \ No newline at end of file diff --git a/+AMF/@ModelReaction/@ModelResult/ModelResult.m b/+AMF/@ModelReaction/@ModelResult/ModelResult.m new file mode 100644 index 0000000..8072d33 --- /dev/null +++ b/+AMF/@ModelReaction/@ModelResult/ModelResult.m @@ -0,0 +1,63 @@ +classdef ModelResult < handle + properties + predictor + constants + inputs + parameters + states + reactions + + time + sse + + options + end + methods + function this = ModelResult(result) + if isfield(result, 'error'); + this.sse = [result.error]; + end + + this.time = result(1).time(:); + this.options = result(1).options; + + this.predictor = result(1).predictor; + this.constants = result(1).constants; + this.inputs = result(1).inputs; + this.parameters = result(1).parameters; + this.states = result(1).states; + this.reactions = result(1).reactions; + + for i = 1:length(result) + for j = 1:length(this.parameters) + this.parameters(j).val(:,i) = result(i).parameters(j).val; + if ~isempty(this.parameters(j).data) + this.parameters(j).data.val(:,i) = result(i).parameters(j).data.val; + this.parameters(j).data.std(:,i) = result(i).parameters(j).data.std; + end + end + for j = 1:length(this.states) + this.states(j).val(:,i) = result(i).states(j).val; + if ~isempty(this.states(j).data) + this.states(j).data.val(:,i) = result(i).states(j).data.val; + this.states(j).data.std(:,i) = result(i).states(j).data.std; + end + end + for j = 1:length(this.reactions) + this.reactions(j).val(:,i) = result(i).reactions(j).val; + if ~isempty(this.reactions(j).data) + this.reactions(j).data.val(:,i) = result(i).reactions(j).data.val; + this.reactions(j).data.std(:,i) = result(i).reactions(j).data.std; + end + end + for j = 1:length(this.inputs) + this.inputs(j).val(:,i) = result(i).inputs(j).val; + if ~isempty(this.inputs(j).data) + this.inputs(j).data.val(:,i) = result(i).inputs(j).data.val; + this.inputs(j).data.std(:,i) = result(i).inputs(j).data.std; + end + end + end + end + end +end \ No newline at end of file diff --git a/+AMF/@ModelReaction/@ModelResult/plotStates.m b/+AMF/@ModelReaction/@ModelResult/plotStates.m new file mode 100644 index 0000000..675e909 --- /dev/null +++ b/+AMF/@ModelReaction/@ModelResult/plotStates.m @@ -0,0 +1,16 @@ +function this = plotStates(this) + +n = length(this.states); +r = sqrt(n); + +figure; + +for i = 1:n + subplot(floor(r), ceil(r), i); + state = this.states(i); + + t = this.time; + x = state.val; + + plot(t, x, 'r'); +end \ No newline at end of file diff --git a/+AMF/@ModelReaction/@ModelResult/plot_hist.m b/+AMF/@ModelReaction/@ModelResult/plot_hist.m new file mode 100644 index 0000000..40f96f6 --- /dev/null +++ b/+AMF/@ModelReaction/@ModelResult/plot_hist.m @@ -0,0 +1,18 @@ +function this = plot_hist(this, t, r, xlab, ylab, colors) +if strcmp(colors, 'blue') + cs = {[1 1 1] [0 0 0.8] [0 0 0.2]}; +elseif strcmp(colors, 'red') + cs = {[1 1 1] [0.8 0 0] [0.2 0 0]}; +end +cm = AMF.utils.define_custom_colormap(cs, 100); + +ny = 100; +[N,C] = AMF.utils.getHist(t,r',[],ny); +pcolor(C{1},C{2},N'); +shading flat; + +xlabel(xlab) +ylabel(ylab) +colormap(cm) +axis([min(C{1})-1 max(C{1})+1 min(C{2}) max(C{2})]) +end diff --git a/+AMF/@ModelReaction/@ModelResult/plot_states.m b/+AMF/@ModelReaction/@ModelResult/plot_states.m new file mode 100644 index 0000000..6cee0e7 --- /dev/null +++ b/+AMF/@ModelReaction/@ModelResult/plot_states.m @@ -0,0 +1,13 @@ +function plot_states(this) + +h3 = figure('Name','States'); + +numstates = size(this.states,2); +numsupls = ceil(sqrt(numstates)); + +for it = 1:numstates + subplot(numsupls,numsupls,it) + + val = this.states(it).val; + plot_hist(this,this.time, val, 'xlab', 'ylab', 'red'); +end \ No newline at end of file diff --git a/+AMF/@ModelReaction/@ModelResult/plot_states_norm.m b/+AMF/@ModelReaction/@ModelResult/plot_states_norm.m new file mode 100644 index 0000000..8b786ad --- /dev/null +++ b/+AMF/@ModelReaction/@ModelResult/plot_states_norm.m @@ -0,0 +1,2 @@ +function this = plot_states_norm(this) + diff --git a/+AMF/@ModelReaction/@ModelResult/plot_traj.m b/+AMF/@ModelReaction/@ModelResult/plot_traj.m new file mode 100644 index 0000000..f0aee1f --- /dev/null +++ b/+AMF/@ModelReaction/@ModelResult/plot_traj.m @@ -0,0 +1,21 @@ +function this = plot_traj(this, t, r, vals, xlab, ylab, colors) + +t = this.time; +r = + +if strcmp(colors, 'blue') + cs = {[0.6 0.6 0.8] [0 0 0.8] [0 0 0.2]}; +elseif strcmp(colors, 'red') + cs = {[0.8 0.6 0.6] [0.8 0 0] [0.2 0 0]}; +end +length_colormap = 101; +cm = AMF.utils.define_custom_colormap(cs, length_colormap); + + +for it=1:size(r,2) + plot(t, r(:,it), 'Color', cm(1+100-(round(vals(it)*100)),:)); + hold on +end +xlabel(xlab) +ylabel(ylab) +end \ No newline at end of file diff --git a/+AMF/@ModelReaction/@ModelResult/test.m b/+AMF/@ModelReaction/@ModelResult/test.m new file mode 100644 index 0000000..ebe4b4b --- /dev/null +++ b/+AMF/@ModelReaction/@ModelResult/test.m @@ -0,0 +1,3 @@ +function this = test(this) + +disp('KAAAAAA'); \ No newline at end of file diff --git a/+AMF/@ModelReaction/ModelReaction.m b/+AMF/@ModelReaction/ModelReaction.m new file mode 100644 index 0000000..c4516e1 --- /dev/null +++ b/+AMF/@ModelReaction/ModelReaction.m @@ -0,0 +1,11 @@ +classdef ModelReaction < AMF.ModelComponent + properties + end + methods + function this = ModelReaction(index, name, expr, meta) + this = this@AMF.ModelComponent(index, name, meta); + + this.expr = expr; + end + end +end \ No newline at end of file diff --git a/+AMF/@ModelResult/ModelResult.m b/+AMF/@ModelResult/ModelResult.m new file mode 100644 index 0000000..126e64b --- /dev/null +++ b/+AMF/@ModelResult/ModelResult.m @@ -0,0 +1,106 @@ +classdef ModelResult < handle + properties + predictor + states + constants + reactions + inputs + parameters + + sse + result + time + mStruct + options + + ref = struct() + end + methods + function this = ModelResult(model, result) + this.result = result; + this.time = result(1).time; + this.sse = [result.sse]; + this.mStruct = getInputStructMex(model); + this.options = model.options; + + this.predictor = getStruct(model.predictor); + if ~isempty(model.states), this.states = getStruct(model.states); end + if ~isempty(model.constants), this.constants = getStruct(model.constants); end + if ~isempty(model.reactions), this.reactions = getStruct(model.reactions); end + if ~isempty(model.inputs), this.inputs = getStruct(model.inputs); end + if ~isempty(model.parameters), this.parameters = getStruct(model.parameters); end + + for i = 1:length(this.result) + for j = 1:length(this.states) + this.states(j).val(:,i) = this.result(i).x(:,j); + + if this.states(j).obs + oxi = double(this.result(1).oxi); + oxi(logical(oxi)) = this.result(1).oxdi; + oxdi = oxi(j); + if i == 1 + dt = this.result(i).dt; % fit time + dd = this.result(i).dd(:,oxdi); % data val + ds = this.result(i).ds(:,oxdi); % data std + + this.states(j).dt = dt(~isnan(dd)); + this.states(j).dd = dd(~isnan(dd)); + this.states(j).ds = ds(~isnan(dd)); + end + + if ~isempty(this.result(i).idd) + idd = this.result(i).idd(:,oxdi); + ids = this.result(i).ids(:,oxdi); + + this.states(j).idd(:,i) = idd; + this.states(j).ids(:,i) = ids; + end + end + + this.ref.(this.states(j).name) = this.states(j); + end + for j = 1:length(this.reactions) + this.reactions(j).val(:,i) = this.result(i).v(:,j); + + if this.reactions(j).obs + ofi = double(this.result(1).ofi); + ofi(logical(ofi)) = this.result(1).ofdi; + ofdi = ofi(j); + if i == 1 + dt = this.result(i).dt; % fit time + dd = this.result(i).dd(:,ofdi); % data val + ds = this.result(i).ds(:,ofdi); % data std + + this.reactions(j).dt = dt(~isnan(dd)); + this.reactions(j).dd = dd(~isnan(dd)); + this.reactions(j).ds = ds(~isnan(dd)); + end + + if ~isempty(this.result(i).idd) + idd = this.result(i).idd(:,ofdi); + ids = this.result(i).ids(:,ofdi); + + this.reactions(j).idd(:,i) = idd; + this.reactions(j).ids(:,i) = ids; + end + end + + this.ref.(this.reactions(j).name) = this.reactions(j); + end + for j = 1:length(this.inputs) + this.inputs(j).val(:,i) = this.result(i).u(:,j); + + this.ref.(this.inputs(j).name) = this.inputs(j); + end + for j = 1:length(this.parameters) + this.parameters(j).val(:,i) = this.result(i).p(:,j); + + this.ref.(this.parameters(j).name) = this.parameters(j); + end + for j = 1:length(this.constants) + this.ref.(this.constants(j).name) = this.constants(j); + end + end + end + end +end \ No newline at end of file diff --git a/+AMF/@ModelResult/getColorProfile.m b/+AMF/@ModelResult/getColorProfile.m new file mode 100644 index 0000000..e69de29 diff --git a/+AMF/@ModelResult/getValue.m b/+AMF/@ModelResult/getValue.m new file mode 100644 index 0000000..b08a99b --- /dev/null +++ b/+AMF/@ModelResult/getValue.m @@ -0,0 +1,8 @@ +function val = getValue(this, name, i) + +if nargin < 3, i = 0; end + +val = this.ref.(name).val; +if i > 0 + val = val(i,:); +end \ No newline at end of file diff --git a/+AMF/@ModelResult/plot.m b/+AMF/@ModelResult/plot.m new file mode 100644 index 0000000..49d5db2 --- /dev/null +++ b/+AMF/@ModelResult/plot.m @@ -0,0 +1,53 @@ +function this = plot(this, names, mode) + +if nargin < 3, mode = 'TRAJ'; end + +import AMF.utils.defineCustomColormap + +if isa(names, 'char') + names = {names}; +end + +n = length(names); +ns = sqrt(n); + +numIter = this.options.numIter; + +for i = 1:length(names) + subplot(ceil(ns),ceil(ns),i); hold on; + name = names{i}; + + comp = this.ref.(name); + + switch upper(mode) + case 'TRAJ' + colorMap = defineCustomColormap({[0.8 0.6 0.6] [0.8 0 0] [0.2 0 0]}, numIter); + plotTraj(this, comp, colorMap); + + case 'HIST' + colorMap = defineCustomColormap({[1 1 1] [0.8 0 0] [0.2 0 0]}, numIter); + plotHist(this, comp, colorMap); + + case 'HIST_LOG' + + % TODO: plot logarithmic histograms + + otherwise + error('Unknown plot mode %s', mode); + end + + xlabel([this.predictor.unitType, ' [', this.predictor.unit, ']']); + xlim([this.time(1) this.time(end)]); + + if comp.label + title(comp.label); + else + title(comp.name); + end + + if comp.unit + ylabel(sprintf('%s [%s]', comp.unitType, comp.unit)); + else + ylabel(comp.unitType); + end +end \ No newline at end of file diff --git a/+AMF/@ModelResult/plotAll.m b/+AMF/@ModelResult/plotAll.m new file mode 100644 index 0000000..c2792a1 --- /dev/null +++ b/+AMF/@ModelResult/plotAll.m @@ -0,0 +1,55 @@ +function this = plotAll(this, type, mode) + +if nargin < 3, mode = 'TRAJ'; end + +import AMF.utils.defineCustomColormap + +comps = this.(type); +if strcmpi(type, 'PARAMETERS') + comps = comps(logical([this.parameters.fit])); +end + +n = length(comps); +ns = sqrt(n); + +numIter = this.options.numIter; + +figure('Name', upper(type)); + +for i = 1:n + subplot(ceil(ns),ceil(ns),i); hold on; + + comp = comps(i); + + switch upper(mode) + case 'TRAJ' + colorMap = defineCustomColormap({[0.8 0.6 0.6] [0.8 0 0] [0.2 0 0]}, numIter); + plotTraj(this, comp, colorMap); + + case 'HIST' + colorMap = defineCustomColormap({[1 1 1] [0.8 0 0] [0.2 0 0]}, numIter); + plotHist(this, comp, colorMap); + + case 'HIST_LOG' + + % TODO: plot logarithmic histograms + + otherwise + error('Unknown plot mode %s', mode); + end + + xlabel([this.predictor.unitType, ' [', this.predictor.unit, ']']); + xlim([this.time(1) this.time(end)]); + + if comp.label + title(comp.label); + else + title(comp.name); + end + + if comp.unit + ylabel(sprintf('%s [%s]', comp.unitType, comp.unit)); + else + ylabel(comp.unitType); + end +end \ No newline at end of file diff --git a/+AMF/@ModelResult/plotHist.m b/+AMF/@ModelResult/plotHist.m new file mode 100644 index 0000000..259f60e --- /dev/null +++ b/+AMF/@ModelResult/plotHist.m @@ -0,0 +1,14 @@ +function this = plotHist(this, comp, colorMap) + +ny = round(length(this.time) / 2); % proper bin count ?? + +[N,C] = AMF.utils.getHist(this.time,comp.val',[],ny); +pcolor(C{1},C{2},N'); +shading flat; + +colormap(colorMap); +axis([min(C{1})-1 max(C{1})+1 min(C{2}) max(C{2})]) + +if comp.obs + errorbar(comp.dt, comp.dd, comp.ds, 'k--', 'LineWidth', 2); +end \ No newline at end of file diff --git a/+AMF/@ModelResult/plotTraj.m b/+AMF/@ModelResult/plotTraj.m new file mode 100644 index 0000000..0900140 --- /dev/null +++ b/+AMF/@ModelResult/plotTraj.m @@ -0,0 +1,22 @@ +function plotTraj(this, comp, colorMap) + +import AMF.utils.defineCustomColormap + +[~, sseIdx] = sort(sum(this.sse), 'descend'); + +numIter = length(this.result); + +for it = 1:numIter + itIdx = sseIdx(it); + if numIter == 1 + plotColor = [1 0 0]; + else + plotColor = colorMap(it,:); + end + + plot(this.time, comp.val(:,itIdx), 'Color', plotColor); +end + +if comp.obs + errorbar(comp.dt, comp.dd, comp.ds, 'k--', 'LineWidth', 2); +end \ No newline at end of file diff --git a/+AMF/@ModelState/ModelState.m b/+AMF/@ModelState/ModelState.m new file mode 100644 index 0000000..6f2a049 --- /dev/null +++ b/+AMF/@ModelState/ModelState.m @@ -0,0 +1,19 @@ +classdef ModelState < AMF.ModelComponent + properties + derivedODE + compiledODE + initExpr + end + methods + function this = ModelState(index, name, init, expr, meta) + this = this@AMF.ModelComponent(index, name, meta); + + this.expr = expr; + this.initExpr = init; + + if isa(this.initExpr, 'double') + this.init = init; + end + end + end +end \ No newline at end of file diff --git a/+AMF/createDataset.m b/+AMF/createDataset.m new file mode 100644 index 0000000..8f8b73c --- /dev/null +++ b/+AMF/createDataset.m @@ -0,0 +1,54 @@ +function dataset = createDataset(dataFile) + +import AMF.* + +specification = feval(dataFile); + +if isfield(specification, 'DESCRIPTION') + description = specification.DESCRIPTION; +else + description = []; +end + +if isfield(specification, 'TYPE') + type = specification.TYPE; +else + type = []; +end + +if ~isfield(specification, 'GROUPS') + error('A dataset requires at least one group.'); +end + +groups = specification.GROUPS; + +if ~isfield(specification, 'FILE') + error('A dataset requires a MAT file containing the experimental data values.'); +end + +data = load([specification.FILE, '.mat']); + +if isfield(specification, 'FIELDS') + spec = specification.FIELDS; + + fields = AMF.DataField.empty; + for i = 1:size(spec, 1) + args = spec(i, :); + fields(i) = AMF.DataField(i, args{:}); + end +else + error('A dataset requires at least one defined data field.'); +end + +if isfield(specification, 'FUNCTIONS') + spec = specification.FUNCTIONS; + + functions = AMF.DataFunction.empty; + for i = 1:size(spec, 1) + args = spec(i,:); + functions(i) = AMF.DataFunction(i, args{:}); + end +end + +dataset.a = fields; +dataset.f = functions; \ No newline at end of file diff --git a/+AMF/fit.m b/+AMF/fit.m new file mode 100644 index 0000000..e14f1e9 --- /dev/null +++ b/+AMF/fit.m @@ -0,0 +1,69 @@ +function result = fit(model) + +import AMF.* + +model.time = getFitTime(model.dataset); +t = model.time; +model.result.time = t; + +model.result.pidx = logical([model.parameters.fit]); +model.result.pcurr = [model.parameters.init]; + +lb = [model.fitParameters.lb]; +ub = [model.fitParameters.ub]; + +p0 = [model.fitParameters.init]; +x0 = [model.states.init]; + +tic +[~, sse, ~] = lsqnonlin(@objectiveFunction,(p0),lb,ub,model.options.optimset, model,t,x0); +toc + +model.result.p = model.result.pcurr; +model.result.x = model.result.xcurr; +model.result.v = model.result.vcurr; +model.result.sse = sse; + +if ~isempty(model.inputs) + uvec = model.result.uvec; + uvec(model.result.uidx) = model.result.pcurr(model.result.upidx); + + model.result.u = computeInputs(model, t, uvec); +end + +result = ModelResult(model, model.result); + +function error = objectiveFunction(pest, model, t, x0) + +model.result.pcurr(model.result.pidx) = pest; +p = model.result.pcurr; + +uvec = model.result.uvec; +uvec(model.result.uidx) = model.result.pcurr(model.result.upidx); + +x = computeStates(model, t, x0, p, uvec); +v = computeReactions(model, t, x, p, uvec); + +model.result.xcurr = x; +model.result.vcurr = v; + +ox = x(:,model.result.oxi); +of = v(:,model.result.ofi); + +sim = [ox of]; + +odi = [model.result.oxdi model.result.ofdi]; + +dat = model.result.dd(:,odi); +sd = model.result.ds(:,odi); + +error = (sim(:) - dat(:)) ./ sd(:); + +error = [error;zeros(length(p), 1)]; + +if ~isempty(model.functions.reg) + error = [error; model.functions.reg(model, model.iStruct, model.dStruct)]; +end + +error = error(~isnan(error)); +error = error(~isinf(error)); \ No newline at end of file diff --git a/+AMF/fitTimeStep.m b/+AMF/fitTimeStep.m new file mode 100644 index 0000000..01d54e7 --- /dev/null +++ b/+AMF/fitTimeStep.m @@ -0,0 +1,64 @@ +function [pest, sse, resid] = fitTimeStep(model, ts) + +setTimeStep(model, ts); + +model.result.pprev = model.result.pcurr; + +x0 = model.result.xcurr; +p0 = model.result.pcurr(model.result.pidx); +lb = model.result.lb(model.result.pidx); +ub = model.result.ub(model.result.pidx); + +t = getTime(model, ts); + +[pest, sse, resid] = lsqnonlin(@objectiveFunction,(p0),lb,ub,model.options.optimset, model,x0,t,ts); + +model.result.p(ts,:) = model.result.pcurr; +model.result.x(ts,:) = model.result.xcurr; +model.result.v(ts,:) = model.result.vcurr; +model.result.sse(ts) = sse; + +if ~isempty(model.inputs) + uvec = model.result.uvec; + uvec(model.result.uidx) = model.result.pcurr(model.result.upidx); + + model.result.u(ts,:) = computeInputs(model, t(end), uvec); +end + +function error = objectiveFunction(pest, model, x0, t, ts) + +model.result.pcurr(model.result.pidx) = pest; +p = model.result.pcurr; + +uvec = model.result.uvec; +uvec(model.result.uidx) = model.result.pcurr(model.result.upidx); + +x = computeStates(model, t, x0, p, uvec); +v = computeReactions(model, t(end), x(end,:), p, uvec); + +model.result.xcurr = x(end,:); +model.result.vcurr = v; + +ox = model.result.xcurr(model.result.oxi); +of = model.result.vcurr(model.result.ofi); + +sim = [ox of]; + +odi = [model.result.oxdi model.result.ofdi]; + +dat = model.result.idd(ts,odi); +sd = model.result.ids(ts,odi); + +error = (sim(:) - dat(:)) ./ sd(:); + +error = [error;zeros(length(p), 1)]; + +reg = AMF.regFun(model, t); +error = [error;reg(:)]; + +if ~isempty(model.functions.reg) + error = [error; model.functions.reg(model, model.iStruct, model.dStruct)]; +end + +error(isnan(error)) = 0; +error(isinf(error)) = 0; \ No newline at end of file diff --git a/+AMF/manipulate.m b/+AMF/manipulate.m new file mode 100644 index 0000000..024df47 --- /dev/null +++ b/+AMF/manipulate.m @@ -0,0 +1,31 @@ +function ui = manipulate(model, compName) + + +import AMF.* + +ui = GridUI; + +params = getAll(model, 'parameters'); +for i = 1:length(params) + p = params(i); + ui.draw(p.name, 'EDIT', [i, 1], [1, 6], model.result.pcurr(p.index), {@update, model, compName}); +end + +ui.draw('ax1', 'AXES', [1, 8], [20, 25], 0, []); + +render(ui); +update(ui, model, compName); + +function update(ui, model, compName) + +import AMF.* + +params = getAll(model, 'parameters'); +for i = 1:length(params) + p = params(i); + model.result.pcurr(p.index) = ui.controls.(p.name).value; +end + +result = simulate(model); +cla; +plot(result, compName); \ No newline at end of file diff --git a/+AMF/proflik.m b/+AMF/proflik.m new file mode 100644 index 0000000..1943134 --- /dev/null +++ b/+AMF/proflik.m @@ -0,0 +1,56 @@ +function [val, chi2] = proflik(model, pName, frac, alpha) + +import AMF.* + +[~, sse] = fit(model); + +p = model.ref.(pName); +p.fit = 0; +parseParameters(model); + +popt = p.curr; + +val(1) = popt; +chi2(1) = sse; + +ref = chi2pdf(1-alpha, 1); + +rat = -inf; +ctr = 2; +while rat <= ref + p.curr = popt * (1+frac*(ctr-1)); disp(p.curr); + [~, sse] = fit(model); + val = [val p.curr]; + chi2 = [chi2 sse]; + + rat = 2 * log10(sse / chi2(1)); % ??? + ctr = ctr + 1; +end + +rat = -inf; +ctr = 2; +while rat <= ref + p.curr = popt * (1-frac*(ctr-1)); disp(p.curr); + [~, sse] = fit(model); + val = [val p.curr]; + chi2 = [chi2 sse]; + + rat = 2 * log(sse / chi2(1)); % ??? + ctr = ctr + 1; +end + +p.fit = 1; +parseParameters(model); + +[val, idx] = sort(val); +chi2 = chi2(idx); + +% display +figure; +plot(val, chi2, 'r'); +hold on; +[~, idx] = min(chi2); +plot(val(idx), chi2(idx), 'kx', 'MarkerSize', 10, 'LineWidth', 2); + +xlabel(p.name); +ylabel('chi2'); \ No newline at end of file diff --git a/+AMF/regFun.m b/+AMF/regFun.m new file mode 100644 index 0000000..e1d25f9 --- /dev/null +++ b/+AMF/regFun.m @@ -0,0 +1,14 @@ +function reg = regFun(model, t) + +lab1 = model.options.lab1; +pcurr = model.result.pcurr; +pprev = model.result.pprev; +pinit = model.result.pinit; + +dt = t(end) - t(1); + +if t(end) == 0 + reg = zeros(1, length(pcurr)); +else + reg = (pcurr - pprev) ./ pinit ./ dt * lab1; +end \ No newline at end of file diff --git a/+AMF/runADAPT.asv b/+AMF/runADAPT.asv new file mode 100644 index 0000000..9afbd23 --- /dev/null +++ b/+AMF/runADAPT.asv @@ -0,0 +1,54 @@ +function modelResult = runADAPT(model) + +import AMF.* + +model.time = getTime(model); + +seed = model.options.seed; +numIter = model.options.numIter; + +% if isempty(model.functions.reg) +% model.functions.reg = @regFun; +% end + +rng('default'); rng(seed); + +t = getTime(model); + +tic + +result = getResult(model); +result.error = 0; + +parfor it = 1:numIter + randomizeParameters(model); + randomizeData(model); + initializeObservables(model); + + parseAll(model); + + error = zeros(size(t)); + for ts = 1:length(t) + setTimeStep(model, ts); + [~, sse, ~] = fitTimeStep(model, ts); + + error(ts) = sse; + end + + saveTrajectory(model); + + itResult = getResult(model); + itResult.error = error(:); + + result(it) = itResult; + + fprintf('Computed trajectory %d [%d]\n', it, max(error)); +end + +resultStr = sprintf('%s_%s_%d_%d', model.options.savePrefix, model.name, model.options.numIter, model.options.numTimeSteps); +save([model.resultsDir, resultStr], 'result'); + +% modelResult = ModelResult(result); + + +toc \ No newline at end of file diff --git a/+AMF/runADAPT.m b/+AMF/runADAPT.m new file mode 100644 index 0000000..42224c8 --- /dev/null +++ b/+AMF/runADAPT.m @@ -0,0 +1,63 @@ +function result = runADAPT(model) + +import AMF.* + +model.time = getTime(model); +t = model.time; + +seed = model.options.seed; +numIter = model.options.numIter; + +rng('default'); rng(seed); + +% interpolate data (not randomized) + +[idd, ids] = getInterpData(model.dataset, t); +model.result.idd = idd; +model.result.ids = ids; + +% pre-allocate +model.result.p = zeros(length(t), length(model.parameters)); +model.result.x = zeros(length(t), length(model.states)); +model.result.u = zeros(length(t), length(model.inputs)); +model.result.v = zeros(length(t), length(model.reactions)); +model.result.sse = zeros(length(t), 1); +model.result.time = t; + +result = model.result; + +tic +parfor it = 1:numIter + model2 = model; % parfor fix + elt = 0; + + success = 0; + while ~success + try + if model.options.randPars, randomizeParameters(model2); end + if model.options.randData, randomizeData(model2); end + + parseAll(model2); + + tic + for ts = 1:length(t) + fitTimeStep(model2, ts); + end + elt = toc; + + success = 1; + catch err + % + end + end + + fprintf('Computed trajectory %d [%d] - %.2fs\n', it, max(model2.result.sse), elt); + + result(it) = model2.result; +end +toc + +result = AMF.ModelResult(model, result); + +resultStr = sprintf('%s_%s_%s__%d_%d', model.options.savePrefix, model.name, model.dataset.activeGroup, model.options.numIter, model.options.numTimeSteps); +save([model.resultsDir, resultStr], 'result'); \ No newline at end of file diff --git a/+AMF/simulate.m b/+AMF/simulate.m new file mode 100644 index 0000000..34d51a0 --- /dev/null +++ b/+AMF/simulate.m @@ -0,0 +1,25 @@ +function result = simulate(model) + +model.time = getTime(model); +t = model.time; + +x0 = model.result.xinit; +p = model.result.pcurr; + +if ~isempty(model.inputs) + uvec = model.result.uvec; + uvec(model.result.uidx) = model.result.pcurr(model.result.upidx); + + model.result.u = computeInputs(model, t, uvec); +else + uvec = []; +end + +model.result.p = p; +model.result.x = computeStates(model, t, x0, p, uvec); +model.result.xcurr = model.result.x; +model.result.v = computeReactions(model, t, model.result.x, p, uvec); +model.result.vcurr = model.result.v; +model.result.time = t; + +result = AMF.ModelResult(model, model.result); \ No newline at end of file diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..1ed55a8 --- /dev/null +++ b/README.MD @@ -0,0 +1,22 @@ +** Read the manual (manual.pdf) for a complete overview of how to install and use the AMF package. + +Install the ADAPT Modeling Framework (AMF) by running + +setup + +in the AMF root directory. This will add all subdirectories to the MATLAB path and will attempt to start a parralel pool. +To run the examples, please make sure the ODEMEX toolbox is configured properly (Instructions.pdf located in the odemex folder). + +The following example run files are included: + +runToy + +-> runs ADAPT on the toy model (Natal van Riel et al) to compute parameter trajectories + +runMinGluc + +-> fits the minimal glucose model (Dalla man et al) to post-bariatric surgery insulin data + +runMinCPep + +-> fits the minimal c-peptide model (Dalla man et al) to post-bariatric surgery glucose data \ No newline at end of file diff --git a/README.TXT b/README.TXT new file mode 100644 index 0000000..1ed55a8 --- /dev/null +++ b/README.TXT @@ -0,0 +1,22 @@ +** Read the manual (manual.pdf) for a complete overview of how to install and use the AMF package. + +Install the ADAPT Modeling Framework (AMF) by running + +setup + +in the AMF root directory. This will add all subdirectories to the MATLAB path and will attempt to start a parralel pool. +To run the examples, please make sure the ODEMEX toolbox is configured properly (Instructions.pdf located in the odemex folder). + +The following example run files are included: + +runToy + +-> runs ADAPT on the toy model (Natal van Riel et al) to compute parameter trajectories + +runMinGluc + +-> fits the minimal glucose model (Dalla man et al) to post-bariatric surgery insulin data + +runMinCPep + +-> fits the minimal c-peptide model (Dalla man et al) to post-bariatric surgery glucose data \ No newline at end of file diff --git a/manual.docx b/manual.docx new file mode 100644 index 0000000000000000000000000000000000000000..ff32786df15966bb9a4b25b187570e2d872439c1 GIT binary patch literal 101660 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 literal 0 HcmV?d00001 diff --git a/manual.pdf b/manual.pdf new file mode 100644 index 0000000000000000000000000000000000000000..212a0ab7333fee30a6dcfa875d104190809b3570 GIT binary patch literal 686563 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þSh7@!StrN0e*>tODWltO|O z((SL~kmr0YKo1wp6;5+jh8j`Pg&}e2TXHWIe#vip6XnO@a_N>?mY|k6rmNp( z(*!nBG@eE&g3L;7)lgzH3%%wH`rys`#O?&HGq_7VMI?4PavTJF)UvS&4VD&9`x_)GCo%=`?y$*z3Q#uQ)Qw*h}eh3K|v!mim$y3}j}f5#c< zz1UK1g0~9V>;-EAy>6Z~O#Z5*hmC5p$<+-x+x!971Z&*0E)VsFbT|U!GeBfzw|drvD+_k$!dp>4q#Z*1XI)6X zAUzwFy`!M%yI#u4V@RcjF8eC9j3CR)uWe9tM+60JaFty|?Y#T+?gfj511CXBw7TFp zOGF^ZM9@>YbA}$8=5*roIEv}6mdDa>!pAhppktQD9=M~rNOx%R#RSsjGknt8!_6vt zYP~{L5DPuMfXy#B+X~Le4c)MpjCYk?Cwm`I*8EV8)0=6y4^tnja~C9=UCoFb@9^&+ zc$c()d@C~lKuvXh5vAADwABrCt~!LoQ?2sBLnc(P{_`CqV=M-)_&F%D^ww1jWGsM< z5UlmKH*&oy=(QF1!It~W;2ozJ^}hA3#vtF8=5_irS)n@LsbNL>SbbcxBje(PR2Cmx zwr8@=Nn7A9cjV2s4n@FA5uG2nca+T!f4laHW+*`p zb;E~ebO91xl6^HOiEpq{(?qoI@dy_!%V4*Pc)AF00a z`G4v{3kGzH5mOws4Hw}^=M2gn0q?T>Ji^sC-uqp7c4N6^CzOiB|Uek)0PV7B^91?0z#W4q)t9)<&2NoQCI2j?tg*=hp*TZZtxA| z;1>HUUWYebHd==->m&ALTqy7`x3Qpw5Wb)nu1S;qk_x_l3sbi#@d|Retcw_!EIT3j+U(p^QiLF4am!V300+S%AY_c@Sqi`yJ8>H-cOjnKMj= z&-ff4tmY6Oq~^AZGm?&P(h(5t5%dY~n;}i*v?uwKcDN z&wP9*``OrXJi|~r_k`5|81m<^YF{#zIdJW=Vq2(+VqT>01N)EHOE(ZT z2Df)e7~(t>OJCQS&ZMfBvqDk^y6M3xkkcYQ+tPWUiwyyAR2PKCms}5pTV#C}H`Ay6 z61@%n!scBLcQe4_(!|vJp-*}cZAUdoEnFYbagISQp8Xs}2q4!xda8cXN3qzO(^oGb z?Z_kYWEKtl<&)*SdYAh1Y=ttg>3G|6F;RZ{no;Oj+BAK~-9}ilOsZBZRUtcy5jXG2myr_tGK9D{0YJ|+We7#j zRkp!Eo5R+oaK1! z3E#dretsRcR=_7yb*V!2}ZO&Z)*NzY+*B;ey>O=YS)0n|PBWIU`RGEOi7rvV)Lsqq>8B zcq2Tbb7H+XUCKRT{2}Unu)+RwKlQUYFu_7JgJk!%a`}d}3TUZ2x!RS{=;L7pI$iE_ zxX{JhNCaLkp?69d&J)1%3uafw%wO)-fHJe^S2lF&HsLEg!jZ$N{mBw=A)oWom``Ar z@wO5VLx8U-`I?me%a2~rE8N|!r~dAnuw9e6T1^4J6Wmi}T&syUj7zOu%xnVtf9+jY zWS=dM16x;w4T_F6+#q*T#Pg~T5C?LS4Z)E((mfLV)`MIuBO6bcZxAlh3FO5>jA)-Y zvew6gRaF^y$y5*^kAMacn#4U!0p+m=`?7AAB^Rl|pNV@IXMk1~81yB~q0H}29`dvo z?=wVwakGVVvmG?JWakDs9mPxAQXddR{gdT{a68ehvtFIf7&9rbXWs@Ru;&Kv*mH6z z=IqB1q?^77GkwL{Cgde7%H6|yKka}(oa4vhST%r9hDfIX zd=%!})~fV6GaQp0IQ<(P8u7|2>+4O4y&#;w9_NhT!n?fy4$0pbqIh>w|`4%fpA6)UaKIRzyrO-uT%+ITsa{2 zEzm9{kQ$xtlzl&x{p#PD9&2x-gb=tUICyb7IAnEDSh}S&@@z+6bl1qOtF5A=t2`*bt?j`15TO3yv z@?5xO<{aqBHoI6`74Z7+JOkk7vm1u{%QtBoZ3)3^>lMK{!3|=YWuP8qLswO3s48sN z${FQY5Ak&WRdembGV(&+GwJo^62u+K%Lnw5;f>Yq^*`fm|NhwoHMYJ15oQ-naQCh6 zJ!Q2xUf;yQBKh5-*+UH(O%ka1Vv(t!&-qzW1yq$htJ)MN7CLTPmWl2!=(7#Ul z7oUR-dC!nM(i)KP0|vKjoxf)I%Uq&z!%ub@JEQN-4(e5i1fCa0=epY6N(i6qLGN?5 zOP}mKw(A(vALhc7(VyfhHJmI{dQEvya&4(V^;lG)=mhcg;C%DduF`ZWY%9hnoa_Dc z31i*8dWrBVk%t27+xOLJB-3p3%SE@RZo1-6a((|a%x&4HU~Y?qYX)Y;cmET<{|2E) zoGMwK9TD0q;^fpwxt5^wQ+Ws=8E9g z-^oI0&Bt;5!=D|sKDdLLJ&J&EqbY>VYA0gVmJgWJrC1bb1kjvtpPyPZ=Mf*f;#i>P zJxyEMA!&FFrsdTSi~1*tE7v`H3HKY~H0`I7blDY>g?l8h*%N0F19La*G8W(Fb6y&~ z8HwxVjdw`})_l&g1YOxn0Mbqj@f0k;s~;VOxkvI}G6{2!6v8EhufC5UGnCIu^Z;Vd z8F7RB1H^$_;#-h=9}xk=kPMt1ir-q_r>D1nlkR;4Y*&LaueK;&YyTxF$=*>>ygqLb z{O^rS{YCp{LjCA}a%c__u+ooC!`vf-_$Mh(%TSbvsVoIo;?OQPX14Rn&_(xecD6%O zxKy7~v!W-Tdt~bSvNiOhxz1D_s~c?rSueqSygPCXSA$}&S4e-evtD85`5)Hvx)kDc z_U~T3W)T}@ybRif_wVDt$GJMJi`no8vw;_81BLOQ%1r3<;rYzDKI5jUOroOI(gsPQMK< zmVD&Q`^Z^lEO6QzY>jYQUvF-$>!!D6Em-)8SE;;&bI3;;X@jt@ce+g8Nu!J~B`5H~ zQeF1Ft~Y?@SE=m4n%D7Hr)aXG{*yr#>ZLA(kZ7>KGj~EXz!c;R=GD_P<=I!&DmoYL zs>BJD?ttT)8p2v+Lsj1~$!K+GMrr|L(xEc2l!Sl4k>mtMONux6pi;f>TCo3&Tj4&x zgz&@tHoIu)p~?KTl8)$wJZiio)8OrOf9xYCLw?T02h?C51h8my%S^wNPM0Li%7Nnw z8boygr$9E3@5&^jRiJCA1XM|fO2E_;2uqO-Reb*sOrEJAkb9El%fPP8l&trKkKN*K zCt|^JEtUf!7G}t$!Ddx@u1$jtR{PU&G#nS=Zt7}&cv}xU9mALXDcyBD{`1zP1e%Ng zC-qKA_I$hU%Y&^Q0W(oB8Q8QxW1*j8Swh@P7MegE@u4)i7xdY4uhAaeqULmL)=lAF z(B+;d+LIo)9wKnamA!IX3*qTk3<3CJ_g&XByE*~TR5t=p7GY0Q#X7P1^<)WS2?u5ypTbwY%av1I4%jXa^FSnpMe~J^=5ygS z{kiZe`URITBo7X+(=Jk*Xq@+hH5cu?c2F;r+^YQuG;=8!dnF!7U6!}NNHGZIXaWXHL zb>Ng<=v6!X{O!@F?{!MPCP2el)B&A=z_j(7x^!^lxVpx*tgNFj0qasK5O$lmeZo76 z8E(eQyh-ubZ%j$g@TS0&wgLK-SLUX;dnS$vAD241{U%=*uXu}$DK$);oL9~#(a7{? z{9JhC5aio5w!V%BBWLjUS-HVUKf}X(UP=Ogqs79B zdA9r?#J@mPTpg)2l1ADU7rR}H3_4pGpwF$6eohiOX6|Lg0uC}_0Edp-KYqF) zHNQUy|B}7k7v6mKLi4cT-o$e`87=HiFjbP6>!6Bi4_wq%DxT}WYFs=I#aI})s*(PN zXi~ECE=}c0L-JsB-`!Cm6XM47(%(Gxe)T*Cl0kskXo3)mVQk)ZfH%-KTkjXa0k%M8 zp9~DbiDNBTNS1CRLpd((ZQVH^n{!q;2zC}Y7;@G=Sif>e$-R}EeZZd^#7lX=wy$Ft z#I*m-&0-I*yklGg?H|>Wr|2cV>6Zw1{%sTTQ$6MZ0s72&3lEuE45E@U)+Ga z5zO)Z+BB(OJ*o3pH~V4xmU+qBc&t`wI7f|jCn?$g|fqb zL#5Mu;tXo7kFoPuP0x>3=3#m!WI=Ead-t=6;C>Kf3w+yd4IMG4aj<fYa^6@rTr#*Zv*OPRjNdPozzP^FCpBFYRxWWutvj^W%eNO<$#UwALlp z{N}F=jt}otAcw_WmW$Y);G>b2i-cG;XmQ|&MO~ID=y3Lpa@&5#Cq-P>DCn?`jQ$Ij zCqyi$cA)4Sw_6EATHSay`n`LFuY7Cwzc?Hi9lnQzY(|<>)3c; zvpV13`wsTC`)g$ZY5UFUK4}R}>Xf#%V$I7MRtw|f8coY&R;oM3q*e`q|ML6}PNM}H zr~Sj;q)x!5**m^qS8HX(>X!y@`^od0hYjbzxOc5AD6M?^GvD7FY-!!&thTktY}B^3 zy#L1o!M55rF1c3LH~!qTjBVAB__rKbYya{K{lz8MPWAr7^{f^?^RfBN=dYZ}k8S@X zR~aVqww}qRnUjhhWWL<~$I^(_fhJYiKjpTIE^l||`y?Ba_z7uuHlNl0tVtrdRl}!3 z{+9dhuO|M@4;+_tQUM0nC^;9-KHf9(nnLX8fMS$G5>{;3KK`p1rER?84n>q*d_8V{ zT5g?9{M~<|_>nb%xqs~A_i>FN#FqOMByscm6rR~fup?^{|KeDl5GGblnD-_<)m7*}2Fe^VDg=E;gMKpb$DXXL6p=BfbJh3HJkJ7DBUkOpT&=JVy zn^JFW?qp_Q@eNGOq{P?B=pH_DL>gLl{4@yEHzftM9@5Mr+@-L?kB1K|sM)cJwH!?; zC44a`V{u!%LS`O6n+N&gzC-LN^I*m8QfD!80Y8^#!6It5V=@_Q0QbTb)VPIJ%FXv) z*ueNCZTD%Iy}w?m{-%y#>OsKchKCQnu+=f}UiwV^8N1%Z?ZQ4>{m>O}f@$ ziT@*DCCsM!B&+(&MUWx_5qNkvn1vlyjIxgA(|vohcmi*FSIeZcVdT+iZf-_q#kU=4+;`ESFN17b*j?Bs^`tzs^vIT)khLk z)g>vtT5`%Ve!bZb0+_US$bZqSsv|FcJ@9{l_fS1@mPr9M0ibzCsA1m{SrHTAPw5t*GO`XFL5Z4?}kbY}9 zeGR-ngIgyOLR7iOQ8Em8tLg+=o9v!TlJP3v^GLrqLYznYzz*~3+Z|XYxxg}7@h-=GC(^PERyka7?Ku%snugJD0$6(1=w?8ZN>yoQn*Gq%0SQ#XOUw4F;%=jtuUN$Ga7xVvo;w+z_RxXSC3_oVl=J{Z+2H4;1(XB z8H#_(yWfbTEF6xLPCCd-MQXSf8R6HDWhJ`IUDMb9Dc!~|NZv=C6=2|C(L$Ub z%T2{nW{NU@p0i#*ZbUd9R**xyqshy_nq!J`)tIvmo3{=tE@EJESezI`VxPHl!m*Ec zOzn8c;>{3|iAc%4Bk(hDLMtu~NHvz9B{tU(mw_!dLuX+zHpa5=sW4$A$7Wk?`oH1- zZn78h)=U1w-J?*?=Y94rGy6gskl(5BvFtg)VVm@9S^aFukWeqb96$EtIY7KfcbN)n z8w12Js9w~rIe}GPNH)8FgsERnIM}AD)D%>qjdx-vDa7EgrS%ydYVoWlsOk z*l&wgFO%KC@>#JvP1t$b+!n`@G*O2j`E}I#)!z6Wp+Oppu#pWm6mt_Y_SbG8f#$YW<8Tu?MccdY-_0UQjV2onU$t= zL~T(u!)wkvonHDoUFmLz{+QYw@RX+0IO)lO>Qz)rBtogkHln3mXnjF2VYH|wovKh_ zpGW{!r9&_VbnYiF3FQSD%p9AbOK<$5hzse+sM_n1cc@r|yk@rD`_;tAk8FM;5>!@c zJ#A%{v82FaN;v^=80-U)-nODJyX!edVOsDFrXDw#HWRD>R0_jnAlwb$M<|7SAAKd( z0gHBgbmMdHYra-Ju>6_c8tZ_%*F8V1aIf5^8wOExU9WW2$mmAZe#jiX>>zla=I6MP zYLzZ{Q29pH{7H$kh+03LXxY!~8n0gp#Z|DX=6zJ~n)yGdnGB6!UiJL>P#=34OBJfH zd)@Vt>Heg=5!L>pe<3mM)V)tix$?y#U|sF)W*c{W`eWA>Udg;0m2wr-?~&Pbk%sz! zXWU5|@*+0wsfPUEvD0CqxYqbHL_}hZkLLWP&to&M>7t5?R$?tlF8jI9BNNR$i3eRX ze_#*QT)_@zp8Wi!Y=yCO;YS!vgI$EGm82a^Jq1U=G13E%>NO|zvK1)?S)sgAtWpuL z?WT!JlKQ;kvSD?CWnInxUP^yf49z!D+s!1y zBu5z2cx`kgf!rp#&=;0?dZB+rY&XTw)|ID8&owCw6k?5@i*mKs9)e%+Z8wD|*W+hI zD8nf8V-yjP{?_Z0R6&Mq{!hpY`iQ#nFl+1XUr0Li1)WMGzVEH~9|@Vz7lcrAiJcDj zuX7~lZbc`Y$L56<0mIN!@q1uJe<@ZNB`uNy(3Lbv>SaDFxzi!G_8_mrw(p>@p+91g z*CzC-qoxa#2M^^XnE>sbjsRo~@Xhk$V77$GNlH6=JDrY~->;6xrzL<4IMs>Hs4z&X zj!ScZ+=MKff?0@UlETrB1b%gfq*UC5)F(p8L8mR9uZ`Bp{!{CmmwH_|pOi{lG(U`b zBc}S@eX@N2``@y5JXB6n zuEr?^fGcx`Nk(PQIK)j*CXpAyxJ^(-EuR4FwCzgdc?-4p^I`8f3$>B}R9ZT`g=LRM z&Bn)auQhBO{RD-5S9@y~LW(MtS$+3=Yo&A?C)nA2F?)NSy?MtiJRJ4^NB}-1jQ)`T zSOAa*DQ&eCEi0E!{<(;=uW*o*(Zb`iJQ~+ z?=#P_CGP!spZUZ$g&>Pj*!m;C+;ak{sBMG)GH`PMkEKd(&_a+$O|xuAoa7 zO@bw8fZ!I~T|0OPPH=a3C%6R&?(P!Y8h0nSHNo9oyBoKL$N!J4nYZq{@6FtKYwiBd zuJ3g9Ijc)fRqa!IQzr2xWMw#{sTMWU((dmh@#SPW*h!UN<0LJa9{6ihva0wZ{h!v^_qI_F~abrJSb>suY0MXIWyOb zg^!+_biBF>L%tm52PtanMqdszp^fG%o4)k=t4@Se&-sXCmri*0ds*AA^G5URv60sL zz*;y@FHca``$LMyYPsFQdTFP)cZJ@0wy2Ir^Ns#lNn`GupXg(rTQ*OLuhb*SnS0Pu zZ>X~5Ah67e51qCEjdv4wHTn@M^|9EG5Kko&>T%C+*}7?U#_5zq7+E04U_YU1Le>Gd zb4NlU5PRnFmLEc)|7XktfuB7<14^hrMC5_p{&5Is^poKZ@H-d#0kGAT76_{mM(+vG zjImwScDK~6N(=$XOUk+yk&3vWdX6(MYXQTi9s6kKheF;V&dg2 zJz%X+rfpkE3=EmIjh*~)>yM>S2;ycu7z;`5?<^Z@)JTh7iP|bI#8He$(H1$0>Tqe2|%0oc3119svI@Vo7sYDC=_h>B$dd`qF zsOFi&_J_-^i4F%&@XGjO)3{lcUJTS@{3$m5h5b_4{CQ~nCGDP!^TlM}|Nn$s8GmUi z4_bxlx(h6jOafm^x#0Lduk~2GWBXoSuD_yO|N05-EK}5l0X3zoXz(GA#RFUf|pScCOCeP0c=zmrQ>*iooOu7DEw;O6!n>>zR2 zKoC}Ah5O(bY8#i4pq++R``t*dL4c}ZWWz`^oc<)M3HJd*{@A)%_qiU6J1^0a9#bz< zHTw-!^lZ?g6S+#R0nAgf}}j>jKw zfpAgO-(d#Z^iRlrcic^zyo(W-QQOTmLg^(+e>m~`>OIhRoT4quF~4)?mq~EVg%uM{ zsZwTGe^dGIlh`?bDh?24`Y;Sd9ko5oSIKgMC9&STM87mv=k11)SK#VX)(Gddv?l`IZ@gkT>Vff-F^R|B^pB-+=gxBN19IjJi zFioaaUHbnP0E^wq+@Q+S21(dBt@43$3=!bQj(F!LkH(|Pn$du;m(DNJPU;ygqFh5@ zJ^X{`b|at0wO2=SD4P1&1z${avGP;tmoDbUST}>SPiKD1Ucy_Jty>9oo&*Jytf!WCWC?=HlEhSsq(gFL5d? z5c+4clMPKk&Zu*qKDYniYB?$%y7h^k#ImaEQRC$}Ko zE?+mob5@F1Hy-XeAUyN*Y#`pPh@7E3=>Gv3BEAsr85BI(B>6{QR4YAmk9JGkFVOv0 z$cZcHh_E`w%h+NkS8oZjPkGOOhB!~A^T}6VFM+wnaL)upP|hdfOtzo?z2;Bv5Cmdq zw<-J?E=vCEVCtJ~H8KLx8b!)TGB419EaaYWIGkI63?vlbg5OfS8W$Y=d2 zgO~>&HfnA$pA?&Emw_j0uQ9c4+Q5f$*@+=cHA<++9G%|@lt+MMlIg{po1q2~M>ELt z%O3%f-d06T5~mVp|%d6OG?y8|8mv_W9Z?>Xp{@ za#bz%7ywzS*{%;yo^x6(u1yLL26#$ab2RAoAdC0fyB|54^CCt+Eeua{6lTl z|7VKBpY&Hc>$a?BXm?L46vqb#;Dcr`#0&Z81^MoS^16`vH?q6mV5|Mk;V_a+cGdI7 z-aRHX0lALZ>A>QBA?3r0I0WVYE7JLhI2Gjd-vNKCZPxEkMd96C&{Ue|>3)NZJ6Y`i z6Y@_GpE=rkfcv%~aiEwJKDs1fv^TbD$Z&H)K~HLh^m@CKVQP0yuZ{3Gy{U4wK2f z%)DujWzMD`N7Nh7qauqcLp1hOGXN^l6!V5P{kbRQFu{W*Lb= z-i_zLdOBywj-|3?-c$EPfV3mRBzq`Sqip12uk-hz9-}e;H`~y#vyaI(;>Mxx$0NHs z4p*osq~_XJ|gBi zWkReL&2Q7~iXJ+$)*j57lk0T4Pn(q8PEyy@i(_`5W*mQX09>JyxgW*N5}#calN0VzjyW3h@)IO zD71*DQu7Z34&O&41S{7c+9cWPk|lFf|NpAExBve8o+7W8+=sIgiuYpLAuV0|GdAxJyG8@wBw-mI|0D!B! z{6AGbvwu0hQdQ|Y8L#l4&;RqQF$MeomSv|3V4d@Q!o5pPMIaw^c#tQ2<@t;&{AXiJ z=?ULI*1rea11kvsD`t1U${kJ!)W){gp$3N%f51VhYvbQXt99=u3$6b*voF=?e;Q6} zSc?sXPh;U6Kg-8cuY+*wJuPW5&QQ@OPFaVDBfL7uT*z}xQ}Rff;qgMv#WSWtGWJ>dmGI$w4P()jUev{OEk284=tP)0C%D-`^)P<&QD&=SCt z6jeK3HMFmh0!@szY5{l|56oXJRdX}1GhyIZ;OnFf7la0qDr-p z&IP8r%kAkYC?;yftT^(Y_hcXb(YvGik2577u1c^Wz=R0PG@~BT>@Yn;q*;f>?hN}TscVM2S1Kp1)94N`2Px7!x(!yO6eUqTqRJ) z8g`08(S9*pmBpHN>;FdqqGH=4Y(nW5l52vE2w`1}GRXTm1kF7~aq8mO7>JPMLVB#| zMJlhfI3B!9E)4Pg3=lqNebGU7Q}qk%lrgQwTB`VV!w|nruFU_;GcUwS|f|uXfbx*|l;T1LT z%q@fqc{mGy{OB6Ukk3N@#O9%$-O<_iD6fX0ul~w}vabf3-SG(p=uBw|Q3J;r)YQ5v zHng>ZE}lxZfj2*N&JLQEO`?|-qSgIkAJ#o)pDq7IRKE+9(~zoR$Cign&h-~qZ!2*_ zOEWxFJDp8*W!B6a?HAkzh{npZvo5#S%ZD2ef)dM{kdDepNV^Yf1s8I3Ex}7RlS?O@ zf}8&o5wfEQ7W=yD4xDCaZXHXT&rQ2-H}ATxATM9p!>7`{3RZOUyVXqJ^9i9_^IY%x z$gzs$v`obWZqs2uSn$Gl{^fM5Q&*t3u?Akk{L4eXIXzwgma z{llIJka4TFF&px(4%?(^(f~4-b&H@4Vz4}k92Tty~mC+D^CXFuG zJ?j|HmZ#5|57QrnmX9}zTLU$(m8Is7>{Qg4BB2^eCAD2)VRTXhyGl&^MnHbQu2^wp z>3?_!1=|CsddsyVfVUQ<76(-^_|xlf>So~6X(-I;4SIh%RN{C^N|30`g7Vt7FeiGp zKHiH5(LF67M4I!jAtK@W!y1rIU-jB&RkKm-F@K(xixO?yf$P4>hU>oAhV5TJj<>ve zP}ee~iD5jm%<4@WXv(bEVYo(7ms$5RQFC#Zjrt3rup`W2H(hf3tc;BCkNj2d_u?6|8e$xVcSDi?_+hjEJ9fu zEU4!EuZQ=Vkw^2;4BOfc;#v4|A{!Cy&_+dOq)JWC<&0AbyM@iBVRHPB6!#d=HZ7<*J(2|t`{rF@Zb9R=5RMM4P2);_$ zox3Vvu~Y|L%_cjo^pQ#(0ZkhsW#g_ zuBBfDsxG=>51C(*uRej>gBVU2{n6~2RbixRf1ECk8@qXNu_j8+d4n*vBkz#A246_O z-h<1#_0reau6>_A-}9f4dA-JIQuan$29_)tTMsuHlv^<5&U&9ao}n$cA&{R*G!Wg- zidSH&hwkA(ee50cwD(2Y(5#y9pT9ox<@B&Z8Er*B>^%4*<=8gwtKU;>{F&Or!55yz)579dkh@^|JIOVWSo zN`D%6_Vb3drFh*}t0`$jE>``?wYH_VZV2R27mZ$4jBJEhA5%9$Q>+!kBD4#(gTDo( zG9koAdIY@rfc5n~e!THMEQd33f@aCE#cIR-=5ht#!heu{ATSB`1f@$iiK0ptuyYXx zktC_x7=|J){(kFbDN@0XZv^0Btktr*c~_RlDg{Si_y)hS(;JWxv9&e^JxAAAw3bFPgjO-nrt-j>zKI|>ez`ROZ6MFa7w=paI_}SwTT@H#cmKzoS z#$RW6BX~)B&M&*Mi$4IjsSJYz720n2Ha*%k=sEW0Fz&_uq`r|oh!eH0?gxyDm$oY% zYr+yhi{cW?`sMpQV+g+DI0T;fp<`jXf;d;wQ%L`|ic`9~R`*O!%EQL9)z79Cm$lra zlhii<*$zaq=qSje8@o1dlLJ)c8S{#tIdrZ_1bQ~cz)q4omDk@Bz9A;(Z<2VuXd);_Wkm4- zTRKhZ&o_=GqVYvbK_2bc=y{WZ>qW~>h?QOErmY$&@j>)6&>_Slid$L-Z2P173XqF` z$5Pp_m>zmg)2qqNHjjGc&e%vCelB4%xV--~D-cF1v>2{*8NV-L5iV6Ap^4POZKje~ zSWIF4B~%+xc}&WBBqdY3X+%PMV+%gs%2Q%IJq?=9NwI@cLT6II`SsTbR3c#~nreth zI)*oa*nz4MPw5ffQFaYBf3;fVbVmj=;*4ddVl0YiCB5X}CdB z!$C|lA}@zMe}>?HJ)c9+&l$A8bxJhu^&Y0Zm1Kf9Dmw=K>uhU+sIN_``&OO9ugXks z2ztFtV_Gvsk8F?lebWZChKQfJ)3~?T|7k*Ux6{M%BN%PFlZAGV&nzRcY6qW^k{^Sp z?ZXr4>Oid(aeL+|uUaSb?87X!f}o@Y4eQ6?q!JeMUy3L^Ve$I@sbTs#!n}vP4;u)k z9$%1_M1R@hDm|KFHkCw_ven|HmdyI^YW?g&8trymM`cqP!1lTln)gS*_=%M4-^4W> zs)cuiuk!h2@By5cc2Ur9nP%^u;FI9{8dxKsr1q!se0@(n1G*D5j@KCMQ;TpnWO+mn_qT-dCU$w@CF2RQoF z;Z0`T>l3fp5+!v}vqq2VFxt21%M#71NI#i{d5!wirsE!3WoX=vlS6NFj}HVrZzB+8 z*kj!UCUhqX!#>{y|L*@H4KVrMfjHVjzZ?`6F2HJ zA)-GTiv8ZA2E&cBU1Ur*0#AB7vksx{41on0$tz%e^UYtRD+JiAfnLMxqE(MVtMG!8 zLjQ?N*uueLdJ=|{@|ly!kmn_5f_rqaRUH>d@c2>e|Sy2k(x0tm*!!$*{F@2`M zHLbKO8_9Fvv=$|~!=egLfP?J3Jpk;yb{b}a-v(z1i%5filTsRQ%kIKQB-8ZDBra3n z9&~{KmwXlLa$IHIc(~kkzMj9!<)ZQl&EYZTpm)T2u0Uf3%vHB7opY8jUOQ z_!Ec8%;SW|KhIFmnrGuT5{^*v1kq$G^vHdYOsScHuLA~L8KQM+h^gaHRz$?B4gCFq zroFyzO@L+~bI-w1T>DvakGOKhN+6)set%I92zbA+4!nq?!erJWb^g^mJZ;EDuuwT& zI=zhrDFcP5>@3T;axwtJ`}x(~-QPfhKJ(3tWnodXEFzS}P;$(DOt%h`<94j^dT9tb zRE5*w>G{dcW`M?{SW$3{T`Bt`MNceuVR}LK=%ncCO!@K+M{F-h`JozDq3ZXGbvR2S z)b`%x49M+agSM`{V?Inw+x&;$=CEG-!HOQ%kmRQ=v%%C@V2aipxYEOAL655+6ue-# z#jWXqhO1A>GDR7|P?Anu_9|MkjWMnyniz44ew0kDBu_*>vQ(HoZ?FpAkSXpgz%*~+ z&-t3>PsLiv_&(kRAUwbk6~b|YCQN0NNGTa=`}Q404}H6}`43>mdf{U~T+%4BwK8QGW_Kl|~wssv#o zgSYO7OMesw(qcw~ebDRru6mK2y{3^mOxgx61{QW-unZsw=Hm+kx; zm)Ra-G&V`NN_JF1UPC8wO&v^I_5y4jkIJ8}I93uZA2GV%b;}18HPoz*!XpWGG+fsAdbcde7poB~#KU-?1pY6r`dWwWbu8 z_(}X8oVYx?cR!+ZRRh-RlO(@}HIs+u;bAAVHtrN(3aSF?vTTl1TVJ6G72VclzjNVJ zs-a!x?@>~61H6hr=c-VeZ(k36lGvu4ZBeLSq>oUWRkFI-uU+q10|nd>Uu3Zt$t}ti zSYyuZud(_udbV!_O#p-xx*+P&!-720@9|oWxqHfu+c4(Rj8w&RZr>8~v{A@5#{-)b z8Di}Y{RjV8tq{r7tpPI+CxRP61O=7?gP_IxPXa(x1;)OaQAk4_>h&X@D3@ADaY{iM z2Unx6jf^Pb~ z)@15*q}>=t?5Wd%RQ1WGjR}?N2?H{9n$oz8BZkxjl~h5=rqv0jY6*=pb?Vad3?rJ< zOXXCu$)dr{ZxRwGr0W3EG_)hTROwk%-if9T38&u^TBSL7rT1w@R;ki6saz6GEfY|` zCuEnMibcS-&S-x8eQ&_)RBgRp^&!VLkT$brNa9>6dUk%A*VHo~>0lwh1QDbWUy$Nr z187!9omX%q$|A75M=XfHHn&UV{Ck5os6KB{+d1J|PzReqIrxz;!hC9gvNQg3&4vKy zwd_`rXU3({CIs{ZKZL~F7$p+0*)vD!pzO^5scU2#M#XQ$l>i1S*%-}g<2S0`tqk0D z*+(rvANkD%5(e$bh*u05PQn6pdhH%YHqc9kGsphkH?!fR?H#>r&Gn~A!6vIzD`h8s zNcpZC!m8dDl+0HwF7GoH=g0{DQP)_{d#UbzaF_yE7OrRR5HZya{Pxfz(ANlANZxWa z^UzDrU^bGAaJHJ5eKBeaaQgbr{iKZupJu zLs$hS*e7P>sV~UAeF`<`5v`WwERcN(3Rq2|lqC|p%L#Ju3%29E^f`jA-!x$yyoO;9 z4YQS~r97I!U%Hi&sH2QGMD`^ra4@;Di_&Gw{HG9oDE_;^UI&hsVh?_fnc84~;Fs_p zIs~WTpPKc4*r6_g7vySz#iCD(AUf7>=H+mb{qfZshP4t{e|RXRQdh&OUvJzoM>#vb9PUB_STy7U^ z#=!k=P~OzlxH_qA`s#|<#>xTMl~ z5N~yWR+XzvYv7@{6=xB%t~c7jtJSJcokRzFv2D3EXE|qvd#i7@CVN^NRBmzNAm6AJ zB`(Ym;y8#6l7n^X5?k(tx6Xg3F#e92KL0ho%-_2f{>Ssgz}H8$cnghM{hno5^nf#L zCBpa0prfH{W#dMJ#S`{2^6VUsGmg8p=@?H&Oit08*i*J$vnh3Lv#Se8s+a%aPyP+Y z()!RyVsyOW|HI$AMhgG9xikC%jbdz($~lT=Uguj(I$DTJlWFyGBDLwm(nBhd%QrCi z$@Nn0L${-Sxw=(_VWPNOaa#+@SS^i%_+r{~hCULHX z!*y}}Ur?StMPc2~dlGm5ywDs?)KtJ#I$^D}a60ESBw4Wk6de#phnhs_X87v&oeimj z?&9n*Zr3W_Y?8;;8{GpvS{Ng)FNYPmRg4k#4pWAVwQjnaEu_R?g2aF^fAu>5>cq%N zwuAi7HZz1L4TC|1TJ!TCD{y!X&O5vy_D#Ic<^DnSf4zQQ6JLSWrY8YcF7jS13&CHW zW#}GQzHJ1*SokwH2)l;^0qFNXDT62`1%h#JL#l_>&munQc{P4tpqL|+V-)N85>G^j zvw&zGc@zLJZWGkmU3TelF};`!x|jETz|lPP)5YAbd~YF+}Hm@*~;ht$%H=)uehj)*DNV*%5o8B_h`clg%(wFfK_|lP$8-mgM z=Jh#n+P?DlD;~g!ZFu2|X+Jkh-D#3LT@=S(!KSzgT2dyx$VSZ3jNwH^cOshM%(M-B zskjHr)oi1=toz%0m>mL)u&?o%&$8OzX+#N8&BD=sdK@=fZh1K3czozUeg2^T791cR z1r~;%`;3S?y>Ji^*`n`cL#m&R)V#m7#jM)}tu`ChE@5F$fAzs(!oh?sW2wxrJ2jU1INq zA#xhBJ)EoVCH3OxeTsWss$3hcKhm$0(>-QG#=Yvz(!4a;LOLqtPul}76Ef_)cARdr z@L?2II=vcs1U_g@;pGkfk&4Uc5a!pid4G?cM|y}d zE#mK3GyH-0&$C#sNE1?kNzd!B-cjI=o-g;ZCZ$K*kZa|T+7YLPFptcr;LN8XJGSX^ z%1vk)B)M{L$xmi?P!LbdrCdtTru6Nv6nwO0lLRFu7nUd`z>)&#dujWGVsE+#EZ;n03NMowfzkdO3i+uYoeyR(>;lq5M~WZJ znC~dA3JsFOnK2VK3_t2W>fkHM5r4X)#}|)rB3;2#B$f5Vvf&ky)Vb$@Y@j{E@5m$FDn4`4;iMbmdLSePEiCb3 zbo8!ujCeZK`VoyI;pAa;^gT0(Fkyn7&XG376wz=4sSUZEyqFIvDedoT0=~=>9bT&I zKy2TfRes}VoC1xuXsAYf-N2-XT>Z>?<{Q5!oQArm*kb(|A3h|opl7P)xV94N=Nu-` zkZu+4@Oy%(AzfNNUh?0>B6bLa4L9{4Cq z?kXfgf}!m9UH~+#1B_&R>kcK07w@AmbAIbJW=>zL8=?oi#0wD}-pW=z1IHU2 zo8~?nwQn!)r-Z-uv&so$>%#yos8MqOg&atkC0P7|m^In72v~3wFaQr^);ezDmMp#pNru!iI*LB>2eTj&)|H6`11C?;#9 zJ^H)I=bw;`=9%6Mim;#NZcKIZhkh<7u-hc6A$eLUt66{N5Oh0oGUsO#yZ(83KkD!b zH{K{$Zd`c>lrQf>EICmBKt&+A}>BD zdkHu&$2PTO@!stv^{kPkKUG5Zj%y8{hQDdyqW3;kI7x5Fk&f1yO%q4+oQ)fr^VE$W zNKZG8>&o4|RUYpAp3Uu|}*Pu|*$@^KWW(o=q`oQNQ_zE-0a9@K@9t$DUp!VsMTi1jD^XyoKe^`9~| zZ`eo!75X4n_(EuXB}R9gtHH5qPP}TX-_<0^REUxNCAKEmItW5|`yl4{>!^L{MtmyK z?fH-*LT~Y{5jp{aVA=wRDL&amAnn|tIX|h|G1L@42emKJh>rtRGGuF*jhG;WvJYbN z$q%(J*65BMRXAj8i0uhKgltZe1(`KuYk;i-KLoE2l21q<41K9NcySTbx9vZ;-2B6) ziywm0=V*k_5*0Dahrx9uG$D@CYDtdAyz6p%pZ(+?cVKf*0;K3A?IU>_omh0=SFuZ( zB8*}ff*Wrfnk-aKOz>SZ$I6e6HPB|L+e@oJ3F&rbEr zcH-)6OQ>~WEMX8*qf{50BqB)iJ}L;O++uR#S^XG5MByj~Zy(l!hS@?M_#z2;dH+n- z`$GApi`8_EaK~4#|6Z)MJ;3lIK61=Eh8wc62dbVswCg_yn}$ymHq_pT|LD^^NXFqD@^*NaUT{yEdwmq&;!DRB{fQLOf_P^=zPPT#GUV*Os$W?@1(5}IP%QH1Y6f8Ntj^kJu2S(7J}X^uj+@ypfMF#Y#i&8_;Z zzYJH2y(r+@HEZnAD>LCv_Iug@SMtLqYjLS0$uvjFA3L$~HNIZSgz0~XPuFI1K<~uP zcmH}NAGZEsil5wz_8a(@;d<7uajtI)!G~pW3o5_m2{e&Nr4Q3T3StKak04_KzL|wc z5uf*y6l?y$AE@_tQmh*$KG^KH%wm&GH?_~__P3gUo=-vfk&~!cudO9jxW7~vM<<&# z?Q{bP&EamqJ?~2w3va6XtDdsBk%@v*F!cM-iB9qYkPwT0*}2pr=k%u2iKx?QMcyL# zDk|76Q3g#xx$lS01hEk9zEYonb=tw4VuoK) z&R%2$b`84hI2ENIzJq_TGr$9<1JSLf8iCLFi-0gmPA>YSLNnqHqhx|sjtD>pbs&PN zayanPrIre1eKPpAr0;R2mS!wtpmp-6Op~z4ALRmtO#)4uCL?SVTUOj%>wPcn1OJtH zAAWWtzJCaLYTBDrqQ3ACWF@hZNE-M-H67xb`Z%wrQkvx_wf4!ajHyO1DU|T7F5*PQ z^CYw<^RI;()Kcz{JeB1D8^ypy;4O?_HKVn^$>??Gds zI~^%}59(RCxg~srrLV*9&1{lZ8>WK>FWZx0?Fkm4Jjns4bE8jK*XK;3{A1wotYpR_}M%V4N64G_s%71%bX6qzRK^7ZOws-Bqv78m3m~Tm?XY* z1PZn3Cq)!=dhXIqi^sD>{7|A=i7{P?x8+X|k7tT7Rie@fH9hIL-=Xtj6>laljHJ-x zG6L~M{Fv%70dXj_Nifl(tc7%V?l2VU{@g1x1kh{B4^No%yZz9TL&v_^k8h@gUP?XD zVXa6BC=f^X1N2jpBl}yWvSd@{LYXQswA9I1$414sS6l4Jq*>e3)xWLW!jCe{WDGo8 z{LFOPqj2g3wdE-3e%s$OHyGWgT;|A`Cs@o!cO$zNu#W@%(LKW1X#NZnD9k0g4eE>U z>fHUxWSvUcB;5r{6u=XlyuJ{lc4EP@vAQ0HcazLdmTJHXfB39Kb{1~0Z%H{N98VYc ztu@D@NrvlvIBvL!+s)J1*w+vmQ}T4Z@kDC#&%qxEq$-9&u6;D?EUb2}7v+RyBfYmN z^+005v$~OfARbh`eR|v#>8|Y5I0pyG+?6SdoS`4Ul(>>5dt8q}GeOo{^>I8Imn{b@|sd_Z#jfq5Cuy<^#Z7uS5+2SJ|D#oj5WXxmR2`QGV>9 zEd6(QafNsmd9z1dr?>G3#_UQ_A9=%c2JW}roKo+C={{c)OLnwM>av_u)9i&I_1ii% z()CH6f3Ei-JM$SXQGAk}jqHxFlfZxm)^^u+d#oJV6-L}k2=9m}S!sq)uX8^T9YtLu z;!8$gMD0W~LBlaQBq9`|FQYC87$}W(>8ztr&g!vMbjrxi{8^pOJB>(q0!Tt z$LgU~621Zv5`IOL_Kt{&Alb^I;VjY7Ye+JDxWc4I0^x*CGlv~`&z}N4cdSbqH{5l5 z0T&`BEmyMLPWhl+8A1%AvdZA0nFqw$CqwE<^Z1?03ka%8g z(bcE%H_@f9PS7Ao+~ww2NMou_Tp;2dCEEQy`27MGFp$RJkm`=#JmPKk+bPsXQONR1 zT8M&-y?Cs9j5gYPSLMQLM+hJ*Wb4bZP?XP(&?t?kkPnAdcWXY;qQWzS{HW$WS=<`U-89#3oi>*(|N=p{{Qr@h=a zE%&ISU4~jLnAs#knsXz%%;BlMOly_7dvCP@6WqmlhQZ!?X1@@=xH?DpC%m}72A&4P zx>Nlj3Q&c3gl8RC^N7{6&r9}&y?=mzM#qrwntyD^!lWb!G6|VX;)LDagA;G>$u5K$ zz_-HZ{>nnztk=SfkubAoyj|>P=NJA9`j>Yv-WTF8NY80LOWlhvtv+)GCmVDXPX=0# zBWbQblgTx7khIe4roPO6QMIo{)CwH|&STDhT(TuGBcblD^)n@5Y}Ogl>Dz0be}D36 zra`_@p8K{QR3nio2$ZcXO*e{e986E2X9bQ;hyjUh0s+Hq%WZ?i#(Fk-7Nk~dhI{FK zmGtwUE;UcoPtY&$ZPUs^ajbq@w;%9!gRVMT-V!kCG zCP!<-!h4U+@t$;Z>CMv~&wb%{!YENZxgT_KTUN73((qdbeb^oKHgPYLMf^4u_W1+6 z-*HX^2Ry#JO(#P_hQmmcg~LFKn7|1bdKa5%051bqKRy?*6ad)I=vnQF+;8il4PYH_ z>&fULtS7HwsR6Bi(j?P#;6dbp=Sj8$ zUr5wY-1&`W_8uED6*08XwNUMKZeDCgBpq*#ZsO6S1abGaB~kZ2Z1U3QE`F39_2M5m zkH08dn>l~21LtP9->qt3O~PgsYa8+k_oG6KLVSBfj~~4iN8KK!yftMaeX|5tEfy(H zReS}{aukY$4 z?Z+=0ir#g;?O?h`(nr#b_mBFI`WwXzCOT)nmPFLiq`{}Ju!5PL`8W`_}!n+pC@o3_m z?vMp5gQbI0-GF)r?SHD8Pkc3sbL0I2z#2z*#Rj{XNza#8xsUczvBd`a?d-m~4;~xe zk5WrsHyu#JMz1P-RA#EBC$HC%{q!Cjd=Ut0qtd{!1hO0{59c7wOr?W%S`(YWg)Ra( z2{gV9_wG1hKk0$2nVc^UNiB-H9bFr^`$_J>9A0 zlr1_Rr}kXS?X|TE9x^*m+>1yZ)@U+|Y*voXt?IdeMGu`69San>b5fmcjiK4h?K8-Y zr8XJuo;Uhkk=YG(W~tTM`#}CH@e@*?j**q~eLcR3k?UzcVV&?lF`Q0#*C0)4go!*HxnDs*JtWDpI&kdOz@6)sL5j z<(eD`j$M^R#a3J+>n&KrmMXi|fQi?&4>7Rbr9D!(6ZLEptYz(DnDMo{Q%nWifXPFI z*#@vxP^aOW>)L_8U8W3%-Mlq5z(PxBM5_{9=rp-&tMO>9fvBh6)f}>3g)p&Ew)UVG zqd!RczHJik-1GXjH|NpKi3b4YyUhMB+(3Muf6*vdWnwf0oEOwHrIYrtG++kFDJImI z&;c!KLB~JLT~`2(8jUL3=SH1xUUW9+8nHv77aA6|h&P5$jk}l2H(juoj=sysH!IwG zNgt@knRBcvU#&f_uJbSBXQo|XZXlcJdRUA3~pO&ONIR|)#M&>K(qmT@~{p_?(R$6PN9XK0>X-9?lo zSOyGPw9ByqhO7<4uXa%x?P18~ng_JD=YIKD}LC7J};PJ5jf70tH>%{8x2# z+W3cL?SKD#g>}X{)7w4T{Nf*Ua3i2T@^s?4=1AqwLYZr3p-mV3J8*Rex=-P^x@@y0EY3_au5 zapMch;&=5FYo{doa&G1RV+rKbr?pk7=qWoiKCo6To0({~26EuH=+TR(t6q z_5n69C}v6;yg<#3RAhk$>2meb)de?R(=ZFmRta{mB{S?eOEy;M6fJmYIRIUSR5tWR z3MRGiSm&(l*M|x)fz@l7%|tD!;`jP^2Qm{%EHgBhk@D)$J|?@S!seJG#|CAK%j9-d zlbQ8++uKxmPu21C<0p0}`OeJi(?lWX9B>Ux9Phw2Zs9)JrTAffk9UQ{Q{^ofynM;o zE>O3CXUA>^1@^hFAb;_9lxUa*5P($maz13@l*Q%{Wu1;s>CENzNAinjT+Yt-XG;hU zM2=-Cc@Yy%dly5?3>AX;N1X>}GRLmE${y;q_b{U3x~{b8ofhBSNDs(Jz=5$B8a#^i159Ak{S0?>b{VEsspy@Nm{gob*c)$W@Zj?;T ziu3Ev#ZmcXvZ?tE=@<;s9`f5h}t8gNN{$+k4JAa`)FJ1GtdD=g1*{Rh@h=M_*>_%lEijLwI`Mv z&4|7>+k!}`EG`KQ>LAk55{>5N*~?)4o5ZE2l1S=V;1~BU(_^=~HYE-916mz#vnAff zXIhrEOoNm0(DQLckJuG;y46G(!=cG<<{A!Et?SDvf&&{u7H}5pxYYel&TpX#pAV2FjRzMzf>Pv_cF~J70MLzWTwQ7t~dt%{52iCFUlj zF;mSY*WeV|>EZII7e$oiy6znXoXj}EzCD>P7W537CTaG|<&^feIC>7_QR0`;03EDr z=KZ?(DoC1kq?-+y_47&fn@U@qUj~QPTHgtrbfD)%gERNXosqK;Kq_Zdy8B5k_A4sV z+=-4EVcqHDEk%9UvGR7!g5EmOg5bU8!1!vG=NpqCQh+D0w7IiQYet4`01=YrmnlyfQ&qZyv zupC#+gVmyx!Q97ZQNK*~+L~r`4t^{Pw=cZzB0JWbVhM%`9ayP7YvXPZims&0$5s?5 zF@KlG0I!W81M!6P4O9=c+Rd!Hd07wl|CDptm4F?~X~)MP6mtfcokM4lBj=o^YdUjY zIqHJZEK}-v>)M3C12t^z%i~PxjnpI0-I5<!62ut0ru zFq7{Kiq3{xo@CeG_4SE(dyO4SnCYS~#i@{z;tDlLR=>Io#;~7CHC2<5UZu`-1sgB+ z@0NY?1#?WuCF@PvP=AxVX3+&`>!w|Gq+J#WriKsK$Vp~8UpIXzUA?cLnb*Jc@upQ` z+R7LK0;vU;qi^}$wcBrRiknuwcw+#~=UUm)D@S+ZCJp#Bi0|}nd>nU48%0P!C!5)N z9iT>_y;*dQgWIKpg_~=*1q674?oTkk=SpVe8IhUV&}EUZn>F7}z|bQY*P>{YMxeW8qrS@dU@cpJrfRb7_F2@%=XCp!MHmKl^cDYFTyMT{FP@N6 zAAEtnkW(MLTkoDK{lPAI;LM*Q7usW%Ny<#tI2&JdeRzkf!TRl4o&W?fE6dHH$pi+RoKT{msc!tY{kFV*=upQLA-c#wkP%5y}&Z^9JJQ-=i5 z7O}4^he`i+p!{+GVcXW}cZ*&YV*Zcdhr)}} zs;ctys@vm7>S}{g{WUtST}}Y?zAQYHT$mTiwyV#rrN?|*W@X*B zT5Vpwbdi@)u&?=bLd`)-xwBxs_Dewa^-q``K)^5-0|yl-wYxVY7 zmI@5XKZg}vir$re*44{4*9RW>aI@sD!-R!?j!ZT+Dq~Js2QF8UvLv~QHs2kO`J;i1 z*%T%HZ7Br?a(jn(oLR^v*{+E*y+@X?xufGB_4Y1p{0Exuj#rWICA-4_seH{^w_lq1 z-=1*CxI$B~-S>5DUc1tZCNs zCKGFtOl;e>Z6_1w#I|kQwsm6r#C9gOt%+~Gb@%RCRZn;AUcLWyS5;TNO}{OBdA9Uy z{xve<)zo%TgsQP2pATx*-7dn=BsdLu{qG#`5wBUBE&gR9J3qUxpQm_xc$o$s zVO|pCq@EHU5@f~h3{QHA@zTl{hbMwI73hg#5t1;;!3T=W%EU|J(xu$l%I??O9oh4o ziSbey$pOiM+Zo15aAW;;SzQKAunkgL2jZ3zre&2ZQY44FU1{9$NEN8lW=dw`;^Sqw zr2Drkm_^jZk{Piz^Y2h8oro7@P+ znZm_)D&gW$EJ$O71u*6?qm5}}1|{iBq%gU~g&?CSaNrIfAra)^vhC-SBfj`Tm z10@fC3tP$=78^wp<_IYj!$uNiq+2*7PfA#dxXlqa-TbIl_^)~fuo#XnL0wArz$%?v zaLgF$H|H4J{D?iSU&g^0iq?bz&w|rGfGEM#2hk5G5RHpM^QdY!aGsa=mKc;7W9!6<-!zms5Q~FN(8HQxbA24 z?l~`lIjHU|NfoU6t{^5zR6FSiI8aErfONX#6-Jam!Lx%AuV)@1dC_wfsQKiX+kwwB zo7`43ZUN-1!y_`;*Zdp~;g0wm=~V%2Q+SV&1_?U|phb!8{bxyx{~JjuL6a6=d<<$2 z{EUeIH-QocP{bSFBW_iM50thib4K?hjN}zjH>9yBae?}#_}Tmq`|u6qo9su@BlOa` z_oJ4Z5>dH?lN3=Yg_9Ohh2u8oUu;LzHRzf0OX%JIjsO%#S%9%N>MEZ;n(0J>0xJThhDz&N>nXJd0+EDb7G`!m5x<; zhE~&K5eRw^o;aCbu-joi{*))d{A8YDW-lXyh$~6E$T&j`HlO+n&q|R4NK+%^MuBjy|DgzFZ-g?@tO&Qp?{hP z#98Ur>*ssFiM@#>_Zs(#!aPkpO(a`5w*_<1o?vy}N=3stT*DPyWn7Lq> zoxt~EknU-C-oNSrBJEX*JQ?y{USAN*`8GF{=SV9`IhRVSS0tC6RkEJt&#OVYC})g| zkbwDxcBWHKKcrT)NI6=xgt>@SH9U_6sVkIQO ztFoYY49SLf$g)J+bfdwBa|v#@D}P+se)24jCW_a1tqF_}4n>~Ucox*luYWCvS|n+E zQfmHb^Qp@xb!b`P38?_c_!GTA-)QkcF9ZhL+q_sW$?>t!S4Yf@TSE zR;Nm%WR~(Lq|vUDL#gLaO=;;F-6MJm=44o6vnAb~izVK0ywaN_qs9dcppX)ugL_O^IO1o~n~a(V1KO9|!5 zh*a?bQ5lj$Qf`;>+=z_O#147g%EMx=Q`Pk``}#<(j956Ak5_sAGgf=-#2Jf&-}%kM@_@v?OtI0Z93vg=z2tn~iUlw>ZEm`Xo`rFXkVMC_ zZ077`d8=^Z zGk+HU#O#1+!D#z77BG_DKCF;b28Yk!xmYK9ktvwz!{VHX=@fIDL?;9j9zTcD{OyYA zm=lK%mY}~pEIC=_MNW-Qa5;yQj-~}8z1*#a@2xzoMMt=1h|^oU8v%Fi(>l=y@@Dv+ zw>-X0xb|S?TnE9kUaK(smEovDy?x`0lLjUS-wamsg^1b}ohPbd(PPyE^RRD<@;}>B z+@LHfs5TFFv@B?g#mRiL1Hl=}h!beGIVHRjWxNHZQNj69jI%c-vjpECF8*Z|lRFmF z9PXKauz2Nc;B&>tu)85&{&b_02`;svmt(JhsgXccmYNDK>6Z7cFRi0Fmb4~fdv$tL zl`pPuuH%vMb@5e9u1~B-jdy=P70s=27}z#99B1&i!hYSy9y3Ko*NWGQIy@UZ*^ynx zUNaJ7(AN;RNPt6{ewfbo~OBTG_s3P#M&JOl2(U-v-upD1b>A z(2-zxTyJ=MEjrE#li+wxPH-44I$8z`ivwV+GyI(rmSkVO59Fli2&K$rf2)%}$&*0s z9}5&uB&Y~fa^xyHc#2NsVV1rcqHJd=I-rkElwgv+8mDYWp?sm=SlX22az@%j@<9IO zgvb}HDin2UNL?V|pGD)JmG)!*6R#pLH@_r44=l0vN1`5N>MiY!Gt2OTN#DX(Y3c*7 zGF<(K24QdHA{gZxTl9@fF?!!$^4eF}VrIgt6iR)FY+Z3Xl9c~!dV>{EF@nivOTE-;kBL>i;2byp1%W(jKGk+&w)|*?Um=AnI%(w|OJw zi0Ko%6m~x#9M}ac@-Qi1gB5@BecL+;T}lZ8{?4G2m&=vJ_g$q7prEI)1kUgv_Lqel zC%`A`;H>h60KGEHY32#Rfg~L6d@;A4u=|g!!{=1dD=b)b>(MJ{`;WQND_$&m*Awo# zEP69wdNV~omGl=SdS42EIVJ(1^&(M}0#mahm2bjK3%L$b`yQGDPPLU9C{ayLfI3Y9 z8|ah*V(EC-%%V^RAFOjy&V}52v<~RwJW$E7T_&P8r#YtSxATAv!Jti^Pe$;eW^j+|%^w48_k~UFvr-Q zCe%B*JzIlkuRbj43>J8^X~uZ2LHi^4V-~YEf3893BY2Vwmh74AU9fK{oh90MnlYPe zuzeD18ZgZm%r&U^t;%f18OJsF>j+-tdj_Lv#&oVh!Xx;g{|B0-dHc{GT+<02SvUNx<)Fc<)p`Wj8U+IDPxwqQD!a3_8e;{k8oV!!2_{7;)9|? z^GdRjQKnIfQJB%PQL0e@vp9lWwhnbX+yU6Z^SD=qB7HJkMX$Fczv#=|_1*PoUcAE2 zMdO{;;#b-`##tA=ei<<;5ylHQj4BbwD1s_2$9N2@;8ik@QiF`Iw4AJ}4t0yYA~-5i z8n#w*&EL^;O_y?@+DfI&u_pb5*dtxup-8TY$*#3X710@vt8>B9w57!3|Gac(rke(G z68sAtXfG_wEQ>MiDrlVZs5>&Dcpm++smihERQAO>_M|%$D>4Ssa{bBbiZUzGHznvh zGF6J7#{LRd ze-$5i)07{k5KWh_uv21BFn3n~MBm+$fm5)r$9_%5<8v-)9efp-7VFm};oajBs-Rydog zAU0M|o2sBUR*>*g=d`PIeB^%+{$<^$h_qD`9~< z>wh0H{8TZiYtkreR(qn(W_ur*crT00P~g7Lb~a@`oz&}K@jC6l02w~bN3F>am@<5% zce`hF8?y+EL9&cN%~<4P|DeG!oe#~B3ZYgF>D!i5MYWuGFNS|FrmAQ%Hiy5 z3>i`;^&A()&WMvS5f?(aCfCjs&J@bI zYG>33p_j=l>!;(^6k%)fxtRr~2E3v7s*J}Lm9`qKBJ7i8$r%bxru-%b{6v-o1Ju#3 z#0Eli{ef3PFJLYN(w~s%i`ca0Oyd6-+Z46!3q}+_+dOgE()=+}f-v|3fFB|ss22}X z_Qg+=3EY7sd|_s942&g>=~OPJrHdgM^OUC2x*1ez%qrA?(#3=fWeihkGZvNc|5QBT z0PMI_5;aOzie_}2%2-at(npdxOXSTkBx{8&{wSSORhO#Tmx?@ueuex(ww%fe zN0L;Qt$z_*n2{p6k#thAyanUaSdROl&D7BRT0T}+6`2w zEKC>pD`CL3OvC*~&`8nV}>t#wS= zQm1sPIGpHo2b;mZr=6^B$WBKM!gbqAKHfOo5J4lqV*g$Pb-G*%&w9?~LH}O1V8m6& zRmUh)J5-Tz_nQ;;(bi>!NHcE|ZxZDk%MuIP3r;Ra`Rsk^u^jbH*P#d89rg_N*|pZW zmdr~oT`t|?Y~y+(lo^scV&OZ~3=(C^NosM>OM5m@LtukPJK8uP5MD5{(PbFI8UoE z(YN>qa1Y%(0e;|i)jt5<;eVL{)^&OF3MwVOLf^M3G#;%+HO#9=4dU!nBtBw&p(dSj z^dvSP(7PcH^G+1vuUFpYj)Z*Txz9yjf4R(sJsMUTldnZ&80S7)U$3e5cLDkChhrx( zd6)r{fML!4Xy78xBoF+ZJ>xL5Y4qVF=DH`tgC4X;lN+mx=@w_C2cX0)+715DeZ+HQ zw-ROxW^w+_>^iR^$u7ta746^FeRtS9V4I%$&gbY2{>69uKg$E210K;BNl%Wr`O?{Q{cQ155j&DR?^UsdLInbYsQQYh_P3*E=JxYsW~ z&(BLqZ;G{HnBJ($EgxED#~2N(M~ab|;f4Df*8BUPY_S%}r&)e^$pU8teyaM90;h*& zdd5pEvEo8Jmz0=UzMqS+U7di>zfrMq`Rb?`b-pffnSR@jmcUedkfsjPl8#?fOc9+! z&%ucXZMj=^n#NtB<3pNoG#UmPAheH+UD*__mY0(df7Nv$lGI7rI3oGx(M_s%NV09vN3yWd$R zm+CCG@8RxGNljN1+|x(m9{h^z(m7OaogOCGkXTKn9{qCjj(dH-fIin;pHp{T+yP~d zkK^0CZ;dWD8nLP;lMMic^>?e8h+NmlSN*!%dzTy0k<%J3e;+5-D^H*AckkEwdd~Jw(-PM0_M3|fh=@EZmt}>&pNGJ!m(y#315B?y z>XYm6!<+YkY`%7__j@k)yC*D#m*l$FC5N1ijy}5w3c7cc(y#0A#NKAWl#~yX(blH5WXxU3tt zOP~cAR)*aLOkrbBW;n zuJPaI{R?z$%E;{OnC|o2(Y@3)#FGSpdne?1#=k$k5r3@I1@6h+FRLQvmEz><(Q_9u zKg}GLKN&6`#@1t0te<<2SnB`HvH1Pld^f{;@wtB~juY7NEA_>}_&QUQk?#~?If~s0 zx>oO1=`KIgm(V`sbm_en5CZjWEx?a+CN4<%HCu7oxmZ3bp|_k;9vg{!%RHv^hNdY# zWAqxl-Wq@EUr^W`|F&7ITbte&uZC>=v$(HP0dDDZ&o zO*P<^V03gknr8nWipPLxs$RR}G%n&~bcl zyssm3j;>>j((Ll=@>Xp=wCJK;%c-~3bVpk2nS4{@haTyjavoQyw;Ob( z+l`J-e5e;*$(J!izR177Y3S^CI|vW-VhSM9Kj+-ODm8oKFIOgWeC zv|vs~`e8HU#C0&@iJpCe9A{&<3~R2UQAovEy*+lIU+SVu7&8P93 zUP?CLYCffXL$+c#bcxQDxt&iXEQzWLl-jG6=$9!utWK4>tAE>jsFQjW&&C`(n zrbKMGZ&0123ttH?Y*bsE&Ne}smk~Y40eegud&oq#TZp$IYh+AnXiWdtWQ=NL0+)RP zypf#if?X6EuE+$RJyjYy<2sQ_+TJ>#R4U(e%mKt!0F~uoX7l|h)eB!3?zK!Git)|P zf{X!kaxGHEOCtkx{J%3tyMmk&fQcKR_B52oyAlfvyIrovXbF2~O#dOAWG0axvbF?vt znUBEBHF4xV;utmg`tCwFtCLT^(74WwfbH4)@&%ji+3Tt3(2jRo@N@Z|&Uha*H|aF$ z6y6Z6n=iW>^0Tte>h#Z|B*mHNIEz=I3XQJzN-43f#7YSyw_KSLAg6Z00lg&%c6Fhs zHIFQ=rDYWpH9*2+*taZ3^-zY9n&>Vc{o{1oNFG@W{a(zKz|DjabOLlq3F z5S*}a#?e_)Zw;~T68&@b)WOFVKz1h1uUk?jd3x2sv$VwLjKs`S_gskH(RwA<-Vw(i zrqj`T6_*MA@FSZomo$@4O8Sw}hku-55rdeZL}HhEm0>jPe1b?}5p`~W)Q7G8k?r-* z`0~o>xxH&-ZlG)FSw(!^%8Cg4Cq>DtxDUyT!S%PV-p%Ja5la0UFv{c8S)Ks&QN?Mo z6EJz}xy2*okV+WJ?J>DH)t>x+Hl5pJR$pdk_4H6Cf$%T3cu(^Lk|mC~Tu&oUUho>ok0aC~TvA>x}32kbMs%ce`7C4TOI zsdi(nL^v`zbStB5@i9&D;cOcr+*SiQjNoz&OSDf_N5=i}X1@Q%a;<(JD;39;7up~;Plr7L_#^CL$KF$T_30Qjx?-ZH<(uXFy#SoUd*iOChzVMcPsejB< zDr{U|i`me8`Ob7Otx?{)y%zWG@8nPW6r6McL$QWRzvff$CR}-le;nFv8nr#kw|-gX zY5gp-iPT9@%KJ=mMN!e?RpCW-P_{8anDt1Qw-VHHrLl2dj#md;vsyG=4U1=`9wMrT zMyrR0ZJ^ech_bpZ-_V<*g+r`KarOAU_G&2Gr#_X7fMcWcy46>VdMG{J8Sd);sH{IW zFJjWJ){fRfQ2@`I7a7M!QQPTszOd`hU{CWhW(<57UZ+&w(nz9Ze=6B2>A~dJjx>7gR%N&2zmE!+bk82HW|mXMMd#2mgV$rZ>{t`*-mj zhWU~XtnrvHee}04lg65vC9@M2#YV7}tq-@r`I8y~dHYZ|Yj9rrQPYdX(rPg<2V z3OB0%!?ONhaaPzwZ3lja)W7)<;UEpDYJLU8#}F8jYx`x@_>nx3$Sw^6As6RJ9-tSQ zXoMi^eulgf`ydWRp>$TDxVGs1p5XkVq60r7jRT_mMV@q1)^vy3H*DkPJ5Np~(o z2pC4+w3qVZ>2}9(f%WYPfwf*D#$N(X;8pJ?0W*O;1~PtH_Imb)_7Q#xH(Y)_y-B^j zevX73ifCtF`Yn>MpH#Ng(`{+4D%=}vVClCg)W6_bMkYabK@t0CnOS<;uI3(VjM%~2-}hV)kU6C1Lna5?t} z#Ql3nKVtuJAo7>!*LuL>&XeSdWZX&hX!+>QXz^%s0uHg81cn&;-db&JbyPrC_u*E?jAfZWEesllH#Ww;?}RO^=$%{B4~vw$|k6fr>N+Gx9hlPetz^w zx~NTTFa9S>YhQB_YvYT|Re`}Y(ZrzhBeNN|u(y9qI0F^CGy_h9&mmt}zO&l`O+=hC zy%b&KUDT`;?^UlG&r%N4wpc!W`-NxO<|6=mBdH-uJ z+(o#>*1*@m(nIfRRZN!4btG)9W=+FtD&p+-kkA%QG4ckI0GW+oh@%gC{gWy1vH1{r zU-4U%sk`yWo3M0(O z{g^?xYy{%@1tVmm;6gA@aeZfXr`#X$WM_KE)~`fBz@70QfRadcq?gy;w47BH{p@#T za1T6;H;y~)jloV{z_AFN0m9L19-t96L`D)faM-XZCOH@H7fBZY6 zb}!RjG=d4DQU`2dI`PuKgg;%APsmC8mDEW6*evJpSo2WKk@ctxE6)D6woH!L*zk*SPArcYQMvvh~s`_H3}x$8p7#~V?Kq{^yKv$`gLhjNcg<}3spdH zdk{(F*DHUY7d$p>1VV&_3Q^uq*G!lf)zPxq8ULKbIqT7k__En`Lqo&elbrhSdgzC! z`q6sHCQNiR^pGtCFJ9S*)Pcf5qgk)r@ApI_PLvNNL>;YH`5m^q?qAJbtGQeR71M*& z;ox}KT!(UrYSA|3esZ2*FT$1F>&i}TvD^~YQqoD#juZ?*<-BU1NUw^I-Xp}r+s+G= zThLqhXFjzmS|Q&OhuXI27xKo76GPkaaa<+j5}C8UizYDLZC^dK%Fo8TVRKEsp>HIOn2-ze8!pMdcCzqP!AHn z4dSu{ugId2z|XC=@G0c9aG6!G|GDZu0?o-Yfns~G4iH`%Ph3E<8}?41KFT&pPuL}j z03jsMk0Laj=pt^2@fO=P50gwBD6;2b1pl@@#CfZ7p)iy+l(niK-Wslji|jPC?q1$? zj)z2%8e#HIWE8{MM-ncwr|>UnC=VcVQ+D_P<1T)24`kT$Lw##rt=l~|(vSRr{EY4b z|8FL$CU$9O24o3f*b4z70Ml+U09i&^H)%#$00j57in?5C$jjjy<(qY5X|9-oUq)_U z+i+3H2*gy7Lxv7Yyz%x_O4P~p(%fUTF>U0<+VkM2sRDofhVgF9ItM>WK4JZud;c4E z7S1@|D|A+;PGgNy#JS z^qB{Dz_HxAxfbm9`t%XF?mfyo8rd}YtP$i)J`!b)N2mOS0S?-`6!huq6S6qjmoNdp z5;WkeKd<}cRVS_!)0yec_HwpXb*eD~!CZ$9=?I<_a2`)EjJg9B&^M{ZTTg5Q*;3Gb zC>ZJfOA?w?Dr*nuJmR;7x1;?J-9qZO=(HUw)R5k7hnF5Msz!0=9=GICaB*T~F-rU- z<*12D$93F8-c#%NhZ|IWC~@y{9fljo>l4vIIXmD}H@UP}i|RX4uSX(bXiH z89iYfvIK)^{FQSk9c&FDy7fqsPpTdexh4N`X<`Qpz%;Jq*Gug$OEkLa&9v*4d; zCo^Jxh?|J7Jzv-l5*z?tCj1AXS%S?-51J#6lfm@uVe3Mu?=o86;UUBC^ha)*nv=bt zcN}#5`>=EY1EeuzF)bsZ+)c#Rn!Nd-+Yxb!Q zebUNcjbz8a-P&NOB$!8CyjUlDMx`Gwii`cb;Aml&d4D|SCeM4zDAOzkBb;LneL^#WxyEe2Ia}j5r$}wUWw=ID!_SS*xEH1Z0*V$fHpv zOkCZn)t$-Y-^2_u;upxuho4c}LhYndqrf5Sv5z#zc56u|!ZcN-MC=S0pok7C#}J>x zHV~F>^ci&zfeLl_7k$YOhen-Zz^^~kB~wPts(r)>XxO+I?Of~;InKQHyz%pGT=~r= z75GO-ndaabc>m?dPw*w7{_=`kq{5eCK{=I7Ju1;Xl9UG5N(tZ?09TO@tRC(INd2r7 zppk*Klm{cHOJ@F{(}7Y1G$;<)2=xF)mj-Hpu<@4E53XTrx97#!N8xZOEqF-&4r+)| z0tyEooKSiU11SmtkABu~Up3YOI&ZU?)^Do_56r@;mvMDpy$oFgPNbC8F)hM|!|j$d zWvM^=dl*zb7i>;jXzM1{=`g#3;wf|#p{26>$6?M}9Cv>>X5XX#oex=Gth5V1eUy7+ z_m(hf1ISPQh8r>hqDTgPJH=2;6Q_TOXBjht>>VJXP5kLYm_KA0x@^O#;srFSA1)b{ zCP^9RB)Ft3)o=~qJo2tt4^e(@V_l0)fE_lZyeab~4A>;zm~f)=qGaqKwlGXLj`bjP zEHaJ!7V!aDr*3q(BU$nq$awQOR_!r$Wu}A8B&6Jn-4`v3>sQ3@cOx~A+-s%sX}3>7 z6lug;Fz(sbO^^Id?B=i9*{6f!A6wbyu@SqHEl3Zk!HHJb=Zt$PVAhF0HSk4M2f z&OkG$bDaCx4c#*FARMKn+{y_f%Z6gylr^8YDA6ii70a~)6dwcIhwxy^5%g+u{{hG| zUiNv>i>k?%tw;NN?^Cu3)nnbc)j+6&;o6M>5)ZvEjY^8OinWqOH2Z~8odRZY9gs_K zkJNR#nCzxljyxWWO9WCkr+I$r_eta%%o^#WonW-`2^>qJi-rlrzdjHY@pZRE*J&2l9yjY;NVk!x5Vmykal@oH*4n5>|6+NFhEn;XgEuTLJT0(_lfl zlG`5f%O1=>lrJ9TMllvUFGtHn`Z4-^c&sA`>&N=0LHu-*(j!&Ha{3|h0Gih0Brg8$ zx*%K<3W53mBs+VQujzz#Y3|TqT77O^mm7`&FSJCs7X|6b&5~lN9-Tf*>Opn=E7ZUE zvvg%Li)k%_>0lha8}_@BDbON=Rf)-gS+c-Il*P#Z3@-WeuazvaVf+;UknQ-AYSsnm zq%pHzJ-!k>c5xZW^8Vg}9g6F8H-7W|U+tshGW4_V;99bDTpADqr>OG=Ely)hhLbrk z>Oe>*9+NnXqY#^Of43!`Gr6W1cakoOE{ClsVKOPtiEe&<%E^~-MQa(TD0TM{IC zytdvHHM+aNlw|JC2I~SL1}ee-{0v)IJ1G7|38)v`Q(wipd_zXbqMn z$jKfeSMck?Y;{JF@`?S49d>Z5e@ke0wR5%egy@3rg70@gcU*TI{;+S*2c(!$)+)K@ z&oT#Wv0d8fLJ1LN5#_mvSq%|=vAB>=%7>8?;}gvj%t#nrgzk{=*_c^`hq2kIS-NCQ zPYP!!AMOXF0zbjAg14Ou{(`o`wm|0J;vvW%F@sQ7ZmQY_l~>s6D*UE2Cy6rb!wWqv=p^*>g1|w zb@d{%6t;2fY4>W7MIzOTp!q^HnF>8qS-xv$Iz`fKE? z*;!rz@uNW17nYCON6V{?YV~LP>+y-$BhQ(eQp9W8nfA%K!-B&?IlC>nEu_Vs>AvY) zNLzawS8+^MT$Y531INB?;j2m>UrK1thr`Cze%t1VL+4k8L+4GX{h)sLBhBd@+8t@D zwH6r-ZI%3iYPyA4rpeH__Hz!T8AV02X7-@&$Z+Em^s!6P1lMV{VbUbUU!0u}+zHNu z%F_-B%baXJuq`Zm2A<;@ylEGw?8XEQ&bXS7TGU$6o3i_^=*E1T%@7 zvxz>Mb*`~l#w-JTvql!(1D#5fyOw|Oikcc677v?l-V+~G{u6} zhT{s*BtnjPDno&D!90prd8N&2am~WAgsxVrqt0gl->?fX;V`{A)1Ios&vJ=v6L-PQ zxb3jHCs*6K2pkzg*^bpVwl-mH@Er}dkeZcxjr#oE6cPi%q$0cZbPm`! ziO-?4k9BWwn_jd;XYH?Mx46vU&FEHYK%)`M9rMxq_Wd=Cy)WNDl^5nDDbAE<#f94TIN2TdN{&->w=))7{|Fcck*IuHAEmI=~fy>r%c+hF0Ps+ z8|JAMnMs_xz-prPP}j}6Qe44vD?Tn=6E0~&$_ULCJ;%h7n_8&Sg(_uv5}m1b`O7Ru z=72LD&|)~N2j>&Ge#%YQd`Wv^udH3d+bWNGQrbtWseUTtVVVOtGB$-f;@`j$lehQU z=qW*Z$hGd>m4)6);epHUK60A=(JHIXNmC#SE5}pkWK{~oK9+G*?Y5jno}DqxY&(&0 zo*mXSAi9v{O>uHveE##q4sQFL+L$LsEteBOOt7S9xapWvRJQTfHPCS=Wh||0wmx%n zA04yY1oK`fAy#*1K@Z1ejO8+?NT4aQ?zvLywU&7qxgWRbHO<7IbXE*Ur#2AGw5hX~ zVUloKtSHT}#*v|1FfcU1PUP&*FJ)cS*ykN3z~0J;R_bn<_1Cs@i#(kqnD}Zm^V0ga z=3N(V_g?JJnnul&g8S@UTRM+H)}QRo(8?W$4qC$%q|ezOwN8B|7Io}$m<$~<1(%Qj zZY|h`KhD=m-P7xfwQr*yGalcmK9(@rou~in+1l8v*mIrKy7Yv-4X=(rF0olEdm!~nj5)nqVuNJg{AHFi z_UEBTj*`iTUX~|&9UoW zt@IgjUr@vNk>^$C@rKg|SPcu(os>69&a`Z28DFd5SvP7; z9nCOG>0;6T3Li3kO$`LwyQ~d z;ur#Tz|5m@hI~h>!4y}&*`MKl@#}jCdN?^R>FgLr@MHJ+lRYl}zKg8stiAz0>={st z5qsqJk(;i^Vr>}+P_RGA@8R+|TQ6>$xTMP9H`6Zs=(@RY<&NrycR`(YX^ivolOI%4 zV4=+*AiKSXq(ki+eHHYm^||>A|5g0txA(+5cDT}3uOnF7wV^YlvNdBN21fK@jxd8@ zB+~F5KXUXT*-wB+M8D=%S)fwa!f0gn$--#NJ0+Sf1mp+Uual}1nG^0;Cho9Oq8uo& z?uZ^-<5{yHKLiq_4-~qh<3Qe5?|2EgZzguy2cZKygqBL&S^#qv&`L048%7+h?q^Y?9xoK7%Fpq4*k8LE zwutgMV%I+bvDc7*Sb}frMH0txyTS6t|KRaOZM)~UKSt+{ zk3fw|j6n7Jy$x~$j`;I@h35=C-wGH?zt0ds^FR!}P(F>tj|dypmlSQ$N?I^4`iq465#aG)vY~V}rz{?NP&efWJy1D=2bgvM zO|DKZ!3eCIc!)^(CLfVfg=*nag$ug?p8a}hlP+fbH=dUVg=*=weCz(63Tw3%07gn3 z3O6jk>s8rNRL+JPp8X&N90lWc^WN&RyjB3*>5${T7w`IsBF{f`Q2E`YWlaJpvqQ> zZLPy^h4M!6;w@z@yj0C>U^nWQ0qv!-RC+eFrL3ijeqn=FK@9XjYpYtFF&PHgR;H?5 z8(xo6FdFqL)>Qb0byvN1pV2=tRPrtHKNXw_#sE5nwmukMn%pmbNphg`z%pOu9VYDn zp#)pkR`nN;7iad6#+;)BV4Z39C>DKPe)#EZ)?9&7&iEhW?1lM3ND9imrM?JX(XRwc z0{uycnDn2?-$!@+Pp$m*uc2O2fraqn@mrmDEw0?Cp_OCcF(6OV=7$2bUQtc~G{enHj4xHkhE)Q22E9C5i*3277Z zwZ#33eedG5CB>(}ACU`=RNS|@OA2=9L6*rL;0Y%shPh6B!D$_RkI^>y9JXQh+jk`n zbBCmeU_hPOt?ojFaGRKU+tn*fcZYc%oB6l9DGG7h`p@mK?Cs_nd7HE+-@)g?^7>xDBaHFtSbL3+wzzKl=jqX=Q|b^6nZx%@KiSgz)9BNx|QD{fhuBXB(WG0oH@J zh4Tp%uOfK74gC`A4e2eJ=pCs)Y9{|}=78))5}_ykNa@w@LGHpw_|z@_t%=HF$TlG& zR{mS95Zf8~^p`xFW}_l>Ny%#kOk0&@bl{4kCF~Z>sdSn6POX1taHmcss_!0yhSD14 z!J#8{(EOm8S%vLC+KhQc)(tYn7<&mtlbicG8dh}PIBX(XXD(-!)y|(U&V6ZWU(X>L z&e_F(rdSq#HY!$`{)a?Rsr#Og@=*LYCwu*idrM^4!Y zYeHNg3w~fm^vvcOzG)c8KMq4if(L^bAk{*kQ`zO1)U@g(rvl$JS==hFJ(DrM&XM8t z;H}M?MA3SU=_K1whDUDh19g^!d+&H2i`J%XFA7{!G)o5H{M~ZdIOmkAbHi6oIKmPa zL15~T>D)dwGxx+flMj9|H-W5xP$5t;BBjj^Imb0Ay%@2fWw9ci1h=tH3I#IqlPAa< zh!-4oPSRcdEHhGYao6gy<%s07|xMY6DYv1_owxBe#X+&m=I*)f%8?=wu4mGVP zLB29l%FS%z;lMpTiO>MI!Pz-D#eCSIOJYc8HwlnVuO1dHji+Ko(fwc*a=OSZO0RV| zXqdRb?%a@9VdswcQ{`8vvLfN1C|&+N9wa>1Vk>!dxd zUeB)8aiL>xnjrF@(;`-~ZEexK(h*}Hym37iVq%OL#VTD3^ue#G7H(*Fw?SmYyj;kP zO|!RxucgV-YUKR?x=0{ci|3H-AGjfL2dkG82Dc3C`l3q$NWBEL@deL4Px3?`72#rn z&_%;k5}bw4k%Jc4avC3gY|7AS!f6-bpdK!|CT<#D4MOh(t_fUgy5aJmb7e=_Z}d1W zIBYWQa~k}~k526{WKQC!AhMjGjmN0L$gnMqn|_gmB9xkh_Gs=L8o?yYUsRTY}YY zM>{fm3Xg=^dKlFuS?#{D1}obllA6T*q;;1vr$=Bo9|jd(GI0H`;JXq zC44i+w)0I4Y-cA-m4oiH>V|a1nw~jlWp)ee^KdlLK~chVya>i8QV#;am| zFx5-(Ez7M6fn7c=az-d?5HGAzv)!{_f|L(&1#>Om0XS+j$ zos)%S$d&&GnLuX0src`9g&gb3>PX#+E}-qX(5*?iKwnC-MYo>O47ZoqQuRl*)3zdQ z(WQgSwz}}9vzK@3jtzYm#;v2q+t%5RBI~BkV2iY!)C|`rHudR`j0v{Z%QhQt%jhU- z(&@FDfWEapy>|J^9n#XA+Zbn0ut}{w%}I?}nn`lgjwQNQWH%Ol$f;{_5 z4w-eir#_u5Z_c$V8rJLtl<9A1Xyu!8$kpab>SS%HA(1+L0k`$oqb_vY%bFK;m34%6 z3-}|&KA$91o@0#p!G+Wl3LF+ugKET+|wUv zH)^M~N0)8-jK=Z0G^4dL3uddgS*K}BW1ihT8BMnvdd2NqzKr_%Z-WkzZ-d-a2Sni{4<+4q)dwBxp zZ|RlY%R86%np*VHP->Tqdu6vayQ!s#uFaR{-oD#3*gQ|3XgaGuYF^Q64TV=Mb?a15 z?XqE9-)|__?;HB+!fQ)4lbUkc~hG&4U$4NXhT3GJRfo58Q#(XX}j z>oe@Vh7tQ%?LN6=Cn-rYMr!Px_F+Sz{rZIw%2u0UPtYILC)PITTWeFvk&bw6e{*s3 zV)J%Wx~+qXriW|yZRczEFO1Ojx?{5MQl@pPZpN@$%j;G;idw4;K7F>WRF`SJt4Xom zHwI*_xL}qo##W&}Y17x{%UWTxwWexz4OJJ$uUM|o%>~va>#8l@c3L-Y%Qo)XisXCa zfGyNktr@W8x1O{~)?3zb>rKtDjlD9cjjjuCUa{V>MccGjx($8S2igVgf@adzU_GoY zx-h7@-qfcFKnge9(H(=GOxvdQJEY4dH8kj1+col*y%<;}`odYV94yOB>h%4#8}{7R zeLYWF$R*niD%;lIyhs(1CH72miaJv_K;F0YlPy$*euJ#CCy}Fe)Lc*cY)4n}$nMtj z+R{rYMx+VUr-N-qHJci=WI7dpxkn>V`I_t6(hGh1y{1Dm%&cZiKhcn?*>0Y%JHBFR zF3?rdX|;QFW?R0j$*o{t`fR#We}?X@E0Z;uzTUi|UC{HO?LC?S(0hgHEL~|kLpPcd zwF}_O!M$;~T}PA6CTa_6nxqq`BRWd2rN^2Lb>Q{YF4IYL87=6JYx7O#v=y!Km&WKE zQ;VK&-oA7|2lS_#(&-ufL|qh}3szWayJjfV9qX$v+ypoaCw;B)&8RsXUNgyA?H+lk zU$8CMmZ@mXO!Kx)YAz-(>Q?00ujQNPFN~9$6knS`@#G!*m_ECXfO_Eqdo*1b(GcMI z9np)eLz>CjqKyWL!-%d~G(*Yq9K9Fxo>8m1`d$AuC7zWrFMH*7Yf)+NZE6}3jKUHCujeGgC@ z*_~#0BeN_agn&$B)=LP(It<1PVHjD)gpp;;Fdz#L7Lt&S45HPR1Qt>cL8AY63o|Uo zv6PQxJ%kXBCB(&X3h{b4;vZa`ir&ZbHvX>#(t7n^L>msTq8U`C1nirY1<`=jZ2mio~liaX}x8U8) zN6n$C0x;VyG$VIypjL}?ee=FA>h4-&U-Qo0;dek=G$Wv7-M|;-o0r~+AoIy0N?kRE z$29i&jO23lEbyC6{2`H5t7*!s+4pvO`@CRgXc}p1c4v4hfp;!~eoU&V4d#kd_SUA+ zrdco=G^8?E>ubU-cO#pQL7AW1JDTdHXVS`Dg|sGZ+|BU1eTK%pyV|>@O-_fdVFP%3 zzCRqaX@hURsx+7uG>{QNYcO2?&bK3t(bpUg#I0bZZ&I2jO?A;hlFXCzlD?{d$@Y4s zPEgzJyEbo&cerWbE?zxa)lH_8Ssp81>No=ZvG4Vg9xz`%CL_E|RR(#@w+N1Gm zci*iCwR#9<+CHz%zEfxSERnswRZxo};ES1_{ibzqA8qn=R6qB2gK?@062MQRf>zSx z*_XPdVQHeNEto0I`BIvunzot_Kux!suHDVPt0n7+ENQUGRI}7%_jU(kn~J18dskCE zzGC08PXZ1SgRY<}2!j3`{W*dvMihSrn9Hc*F%qtrP|P8pQYP*-t-1wP2U2!W!|KRn*3E{2AM?+kUhNxHThDg$zO*|sthtI6J%0m$fPXD zuK<%OhfL}wWKtD?Nqru%K@LSj4#h$a#X%0mLk=ZC4kbbk6@(nB338}r$f4eW9I6F! zs6T`psugmme+6~>cBtETK;3>A%LV)>1o_bq;hx}MKz)8o*5^@7*5}c1c~3CQ(Eld$DGXD(lpGc&tLWG%Sw+VZWECCzJ!Pk| z6FV)lD(v@_3nwuwQRYzCTQY~jN@dL)yDn?ySeeY8FpJEduyUC_VK-&=gjLAw3G+bZ zybiFZ_b@M1#s3(p;_u4L2>T|~!$VLH{}$B4N1z`5ZK#JognIa&K|TBt)WhF{diW^R z!~cW4?-?7D_dR1jf-3iaf-3hiRJnf&Rqhpe-!t~J&+V&DW2=B$rG%Z3xm8${%&o#c zEpw}|Xqj7ueMaV1VKIPPRfT<4W>sMqWL6dSy3DG=v@)v-yCk!!FrCb*!Y-@0Q(mX!hW!Mp#D9yRs0Qu%h|64W`xlo!R?+s{r;3m;&%H7oc*i`gWjWxri86rC zIIl$I0;{3sG_bs;JQ6?N=x|m0-vT?B@l1*nd6^h$C z?$yRF{sBM9FY%i~grE`f1(Q%OveybPWEOYoJea z64y>AbDb`)T#niWe5Sg9>!wq=K02F|uRkfSiQ7ViI4GFJLvWA#5+avKiV}7u6)4pi z(IO>EDPpITCS`(p>w`~hi*zSF#;wrX+#YvWM)I+|3O7_(n8})Y(-eE3E@kgkMDn%9 zF+7D2@EqU7ckn%Ye_17M;nl2CZed#wpVqi@r;@fYO}vrDK}i<*Ny#b&gb0ZflB6E# zfiw?FV)}=2@Jpg4m=`pOok3@?KG+;=6K%nJ!TZ6X;An7MB7;dmrC2Jrsq{kH51t8n zf*RoLvh&D3@>T&-3(7QJkeXc3md z@!VE;^L}HOeB4pJy~*^r_JDWjm_;g@(ojS0)ylcXo?H2B5=F7S?8x=!OgKB<_{d$0 zchGYTXpP24>_B6P8UemCMy0z_*(|E9Dv=&$m3StjrY9(ju>#LpW$(L}s8J@DdP*%* z&#CpsuD3Vu054>f)HS+=J=3^PCE#k7awjseOd{i$Mqb6&^0Bm+?&iDf&zUCMVsM$S z;Zd> z8yTX4sf(!{r0!F_jgyU!8)w*Su8cb&w&*LJl$~-?PpH}3q1z#L`Bom?#~90WHwV~t zc8fubTHMG*y7ssjywbgDOlBT1{Y;2?%#|{&Oa~XwrE(cKcYBq+$=a!UPRkYCq&N#T z&Q6*8I9r8{3U!o z^(#mak)yB6s5b$k-qR5EejcLUB#3&y08wuWM7@6iQSTXudQ&0leHo(OG>Cf7Le!fM zQSU1d^=3lU`z45a4G{HSgQ)i{hb(w8uMwhN6GXjcha{}Ddjq20n-KL@ zK-6o4zZ_IyUj|6m4v{X0y^sA6>4LjVzAmF!@JvB-avQ7ke6b^m#& z`>#RWe;w-ne+_m24XFG77a7GOe*;h~hU}bBoCrsD;co!{75)aW4}Syr;6(I^Xyo8T z%n2p(xA2#MV~BJSh;&hiZZU{%!yvjUb80;JPM~&x zMcJ3ARq)*kH4Us7>{mXWKB zy@jr&Nji=0pnK?fD?%^Y`{*M)qOu<^V$Lw>Rpa&raGw=w+de_7=t8=ZCg?P~REf~@ z^b&*N5ljNzZ=a~{xFKBE;_KEZYbI0ApRtCl`^-}!);{LIamv)f_qumYZo^{n>WwT% z4v}Js=CjNM_X1z$c9?u?)SV$~h?xa>o|sy!iAM73ilK*Zb1?iU^^9r0y1+l-pYrv$ zo-ujC!tEqsgHYX8T951tmXYgoVqtY5u_RiJhN=ihC)Z&OnJdM~$`GC}ZnB*>ridQl z89@l!_>>rKwu-r;j#x4jmLG~uVypOAoD`Qt0-wTfG8z%K4>@Tx+)A}CTxIBa&^{#f zOm3aZ5IxW0R-|kMkFX4}UM8Jwuy-5Oh9$PtP|4a@H`_vVxwqI(A=1%VG{<%eF^-3p z^y(e^Lu;mxO!Rp4rWT@K$fyhn**C5cAt8rN7PRaj@kp+dBeFc_wvyA5~?DM21lo;5+@y@D0pr{Xd>f(~#2dY$jDB7Pn-H79N^fZXF79wxrwX)wPy`+gYIB zV!2hzfngE${LXF68WP4T5l8#&BukO7U=G|)a?eVd+e#@<6Bf2*%^4y{~GV)|mt502q-wbS@oWvZxK~(RJ;0tu@M0WR2qQ zG4)KnqktbGVvVFVlNb2=%!oCGA1_|zpPPx=5TE2Y&D>-aYz%(PpW&OCoBTRcL~#7U zogrq6ck;82F?y9d;z#+d8yY^^z06;8?_SmNS)dRrlpPg0VSnSTvH{ zCO^eYG0*v3^JejkBiW%R)WVuMP_D&~g$;a4I5Y<=%a(OBA|~1w#1x}W_GGbAB&s6B z4zWjkWJr@eS)3PNT=G&46P&N-Pu~SVK3aB;YG>H57vGwT2kfXGC zhB1*Zs^=XFM&74@1ES(`pHis=>86jSZmXuNwt7Y}9#BQ4= ztOyvX6YL7R#_rj>tD884&ZVZgLQcmSIBV5-)i~G6kz9`<(_-h;T&}%^J>;Ue6grpd z=Mt$Edfwdz#`PFG&2=#8rU`D5-Kd-4V!1TV$kmo*xeyI7`ZxiX^*b6d$irifPh-G*XO6qvHIH zsT))5nlvjtuU@nW#*j30eNJ*p_0m0X)^n+iAS~-*Y*mDm4vwd6XSp`0z%|k}Ns#WF zTBIp6B2oC0Y8C#J+rJ^$njP^)sfG}LjTv#ol<)C*zz;{Ncdi#OyUa0f=Wp`VEj>XH znQXE-)11k6^CRWm)<@<|ew4Y-^wuIwGgE(OnMiTu;9L9_e_R{7e%h)wr0^Jtq! zDUQ>8k)SBo64pwNsB{cp-E(wTjpMzJKAYXt0%puwB0zAK=LTyrLLh8pH9<6))#Wkf z2NuERBwC4%>J-~7m|w$hWW62DP!4a^6hGjY&_8j^=?^M5!Kl@+r;9foHYURQ0L&M8 zj0vo*>C7^-&Ir7R@4aIJH5~wbyUcHKFT7`%Yj=itC7(d6m{~r88RDPTMX@;1VKe}A z5T@8s>>!BZ*NR^wXxyc^OK^A3Ckpo`3il@p_rC~*8|eTe>O)kYJM>}tSmsfP`BRXv z(oWARc*ow@^E?Bu+vZ8|nc$i819tJob4x3*NYA*}h+wuce=HK_)%#=pfQP&>?HdE% znLK?By9iclFqZD?7Lj z&a5+7DEZ8~SW~t++#lmV?YH@d{bT+)|1W`@l$z>qa zZ%mi=nhLbLb-J=+Py)SN0%J;@&bxfI;mtEkQu6OV7Mdz0bYJ zfk%PIftkR3ATzKSAOoubLtwMqYdQ8-G8$ z>-rndTpA=3!I4I07G+=WB-LbY;K=vPsM|R$O7r}-*Ox5E zMcE!(!;~r8(*VlXU8gGyfgXKsG?pgGb*_t&+q^uZF4Gffq2xM)++B5DM#5BJ!_0_w zpy7!}YS?PnZ8&H+E?NNhU_6p%&NKa1M`6exS>A3cDD7<+Z5&K;5hU@^sh8Ltqb=nJT0CDe?0g++n?j_^AGwb0*IgS zOTf3_;eArx9@zJec*niF-cj$A_n&O&iI`lO(tb1}A6MSQG z50zz=WnH&5w7u1FX|Q<7H|!fOJFfSd#_Aq7tX~>zRC-G5bT+I`R~#x18M(UtqHMCz zXES&CT6}%JIp11g$ac_}2g;0C1I*{vk2UHEqfv!Nu_4YuMKiRMK=IIqUB)gWICcdqKpfbc*qg|0 zOpoaiCsu})Auh}eT+$8K;u^RX*Tbj5TH(`R?Jxq>AHiqBI$#82{StW>s&(B^t@|qcs~kPp9=3;k4f_E50O^H#+}FXHt3di-+^PW>x9S@(Zq?w4 zPoIcEzIj4<;w19#V8p6_4$JPM=);HdoXU*&tTlDRT#JG z=P+*7e}-|ZUck6jzl3qCHelSUU%|Ll`(VvYMm|ucC{xfd*bCDtZY} z(fd89=$(d&9$1T&3uq#Ia_jSQq%8Cca-=LYS&o#2z9dJ=LQ~{OS?C{}{OZZCqGwKi z?c~?dFP`i_`KM^w$#0ze2AY2I!N~{cxs#!j-$FCw6&cNxqiLbpCpS)RplW$VM$gMD zGOCeRWb}f(@}fEN%8OoRTwI`nKvJ z%BkK{y@v{_$EtBuR86QR&?eRUs`t^msu|Th+N^q_`b+d*tNu#$WAu+yAE-V+J5@)j zBlM3?<)11*yH1s!Dn;KtWjSReYhRWHKFmcG{awCICxGW&$hP zd&V09tZ;B%m>2P?+XvRBZv|K{>W+Mezcp`s^fXh)iB=e$tNo7Zqx zWr?6Ro=?)Oc}I1*C8HX}rIoz)lF|H!=atz5`FK%FeztsOi4%Oc?cMb$eA!@~=?1IP z1W1vvo@Rj-s$S7aDW?C+TMt|iz)_Yt}BLX|@Y@YONYY zag;jca?)Gj#r@ax^3~<*>2kGOCHF2Rmk1YPi>5D?Ub5&`FAK%ivSV`-`B*!pw(55B zv*ot9Qg}J~{IV{We3Xx?D}C|gB&Zjt5jjK7lZ(D=aQBY4jATzf{+bumK}{MoF|T=j z!{9!al4dgj+M`Q8eEPC87t*|2YL$1qWc1Bhxwd8Fm-;k%?{jr!UZ-5=ybZa{Ur)Q1 z`r1PFh+Jpw)|>Y)4;5FQPr9Nm+{u6Fo%KGsJpTHOF0*VvSD25NY0C0+`(+*-qE6B6 zyh(w+Q2_ifb$;2qu2!8Fu56kK?{Z$B*{E@=jp`lUl5Qz`{6c1#{mpxztyPyJ0Mgj? z9{Wy%p33%3`)p(`Xh*#-**8swgVz{R=UX6Cd=GsRS?Jj&39^N?Ih2Fl+qTfWpf#Fs%vk+D9lZ_jr~R+82?DbfJiDc+Yus($0y)4-=2 zz$e{4MpFQ0rkBxgqu&M-(|hQ9V3zt0`W*yAzl(ks2}7sQDMW$Jpfkt`bPkgc2pN^$sDI_|UiDi(_#B#A5 z5)&)L3dm<;rC14xjctl;LgHeZW1A6W+~?y`k&|&5aXHB6N*!$fdZ7xC%rUcPs7|ayhOlt_sPItB$KiuEaUw97sW&GtP;; zk?_5Q?;(W=-%t2H@@B&O3GX9C34fmO=SXqF4-$TW=o9`T;V%F(`vl8XBYZ1J5xF*48{jLYD5U?cI0RlADJgyPfD6j}u53nj-wXRlRSzIZ94sAwdC!&NO1n@C&fLh4)YV==oC;SZ@c{J2kz46L<5q$`AzVA| z2zRtQ%bno9=6dW3;dXcZMO-dJ*2YDB2Bou}Q@uXv+&({~AC*gxj=K^w^0fo!mP&*i z;l`+bKO82h&peEAwxF#OA6O)9oCi!+-^^v=+COaeRyeB*Ftmm>R zgQ_V=Ltc-{xS6x7JwB)U&GmW!y6M%n=?9#HIZrAUYozqyH{x>=&X3l#XfiSewA5MZ zLap2uS1PXPS>Pf*{{iPCDz1T2whRv zvf`OrDx z+;Fa42v0*UgsWeGzM-6*&c1VLF7?Ii^XZxm{iySq^Duv+V9I4Ur_!WqQZKgTZCu9A z+t2TwOM5jO^pe$Oggw>cPIu?sZX;IRf~(c-bbDM)F4EoW*0}Gv6I`3_0r#kT+&$%< z1$jVEg1$^}?YoT51y}f`Zs(jml~{EV_?hZfSD?Dpjk)t(ldhR_J)lo}&ZW7xilb_@ z?x$C*?qm0|`+1F`ru3paEp)L{pME9tY>{*D@@RUF_V~hnjl0I1-y-)={&xPh_GwK+ z#*>0G1ykB(?Xq+G@_KsC<*ak6oF_FlBK!)Mm*Yyj*m<$@Jm|{|WlejH{^G+LOAUU0 zIZpvvcc-Qs^i-dVs2K#F$hnJv@0r|f)l05<*CI$uL?xc?)VuGypSY78sklsQ8kQviWLC z2KA+Md^~eg&L!tKd+?=$msXP7&bDRsmAhYB$&AIHzO;Q|F=Y~8{-QA}KKWY4xFgbW z+L7(hIxG&aqruT$;w%vy4;>SZ6~_jchEhOM6S>#)j%`N_VIYizl^{T#c#x+6-DaA+;$z+0YGMQwC%w#f?gpdT90!?YkN1y@Hgl0Z7K}wNE zN>j?Eks=3?lOiG_MdTm{b2*3@DF-nZ5or!0B2q*|iili9T2qRM6lrqS`mI!}k9zfw z``ml(E%VGT@4Rd6_5Ja_Yj0+Dir7b+4~v*X24Y@mu1*G$O9Nhad1ABky7NM4eeUJL zC85sTY+q$gx_@zQcJA54ww!Zg%0f#6Yl@B+?RHm1_g3_lZ%FK}sF!6*u1{`it`~WA zBrPJ3u4Jby(KN9zigLM{=hjY2x~2^m<=LM+=wIxva?W($_KDpuaVxkncW~ag(82rK zCalXj7pe>1NOb2GxULp#7p*iT=UmRtoSp6~rF%kaic=rGB0l>Ab;YTPQ?iBgEWwL8 z`$BbYr#szU?%FR(;umE(pS&c>aiU`T}{aVq2*vs;d}pfl9@V7lw-$PK{-4<<&%au-&f8Qmsx%-NT- zPqdQAXOtGa;jRj~g1wddL*B%p=-%f1W`DA+xtvikNwis$e3FV0wXAu&?7!xVjHlsA zuNWEgWdDgebtNYzBchKJ&52}d^YrG^&9|GEh?bq+yrtPGv^SC?M5r7O#mxsq{FOp0 z#$j{47^6GIxNN9BPHH2>FoG9w9 zZV%mbT@5;e&cxbLV-rVw4es=jGjk3n)>fXWp5VS1GRNYm!@&J-LI&?-ldW8|)pkIw*1sjL1oM=LZ7K#=}Dj zm#DGlx|(w$aoO$2Ii0gFxG1wh^|QV zIS&P|6s;}V;Tlxb9h%poCEG;p&L=k|uZeLuxMipqiT37>mI-2H)yQ!uW@bb4l9u_R zt)0z>TWVWsr_K@a+$}>zi*$)GJ52ORLe$`V@_fq*F>~5lwk2;S@3a)Ol(o!knbTa} zlA60MmI-|H@~ZqM0Q-R`R_>#a0hV$6h=yUUAaC$1+h zSM=tlir3}D@zSNij$m)%ROOjqxhpXGWNBOVgbG8fPmYkwH@vhbv0+9{NTlmO>zpau zY{I(4+F-BqRH!p_Q-+OhsK~E8pF1<>KxkfKcd$Blb>X7i?ocFfHE=bzAhBa?Q{gh_ zZeN4zSnf7w_sG7`#F4emQ;FAej}$I(`vX&4LxPK3TN9hboIV$7b)U4jml1Hm^=_LvVUvc=@5C3%QG(-J>+o;v+^K z8MWBG&L0c}+(uxyoB^e6qiWt+gM&BZ`Ww3Bx?0pOXOkRdV*Tw7ZY*3h@>b>kksI>r zq8mbW%~$y5xbGW3c<+Bgy!SsL{>%SQh(Gy0#^Fxhf76a?y4ZBZqT5IK_KLq+=$LPp zMYE?*zG%^#j)d+sofW!$fhLO{>I(H1dqw=N;5hMVTj)ZQu%kkoN=I1qj0>TYO?xd` zrZfMh2wPcnvuW46X4N16@57+fA%C>+KDb=JGqpD>;=bnC?lE(ghHf<-u-|DqS7X|f zO;?(3WNi%(3J(vvGM3F~@~+JoHlupl;=I(7Jxv`=>zX!t-Ay~24mX{4p0+1l6YNP5 z+Ys-JOgF19rPvcr!oUYmd*2FLsv(2FE7^YI00_UDi#X zJ1dg0FTc3<+Wp5Osrjcfv+Wao1&`jz+gp6V-WeI{n-iK-l60iI*5>WbT^DituSB%^ zG`Cq&7s-wkxFf~G@~6k@JO{ImMap6g&a}*h`O7M9)|BQQsazNt>*xp#jm^v07+ad* z_b!etk4%WIiq!g6$U5CW&a)|Ww(wwZk0ap=x;N!rmo=JI;I)TDt=v=GrH&i!wyEbD z_vM`xrQDPiacp$t*ItV(%sST4K50RD$D?;5srJrV(>KSxt0Y-?K9ribJ8NFkjmQ!I zu;K%u?##2^LzBlvj%V&Inw}T)F3il1oGNK8JQLYF#XWk1z0+IP*p-oHpXc1^xa}^D zbvpdP%8Ezz9z zmqqQz<=l*?2FhY5{nKMNg8_G)XPh^?aDP@$M!Ijqh{2Oi$9Lp!^c7@{%jr^s~z=@Et6OI>x(ve4(6Y5_{Z5V9)SG!+%mLF|6CRX*J8!0#34yU&9sA^r$u0K9 zau*dZC|+hy+LM{bn{J5fZWk|T+R}8ier|Y(V_oo=Bazk9w0&x?`RVX1y+QwjkyuN85Vg4UEUSm6}~dxw#Kgf zmHsL*KdbUr`pU8*fneUL;4vu~UK<};yewYO zbRs@Ge`CDHH``lV(OS6Q-db|WUFw4DuE@5=93BGu^wg_Q-d{-ncH-X2023Z@=jqn|aG?7k#i&z8yCr zE9}R_=UwsD@wLv={@%#onlrHmk0ms;c%A=7WN6`<$coIfg(LijBXjb!$l}O~$cD(; zk|E9;4edFXW>iIX=k63Uc~hjj;*#TH(~W7V&PkCSVqUKHc1N}qj;QO7Y!2*pbopkB zwI>#tA30RAD{?k+A<}N2H)+wNgnNIe-F|F(m9tCqXqWF$ywAHKwkx)0TCC_|bXm^L z5?4`I$(h)h#wD>!;&nCH>MipQ4GawiVq0VT9m`@pzHKE}-OK&wB5u#6z-)J2{8qw< zUGvTN42lf(7iR@x2V=+bch-&w)HdDrFUo9p?##@NZw?j2cL#!z!I_&UAI!N~KFoi* za8Ufzn7NskMQ>afbIyG!P!Kv&yd{3z7cA;^x5kfn?ueE5(8Jl8XB~!EcQ?eh*@wF( zjAi-d4!^_iOpDHq3TAAKP7-^>nxezb zo#8#<{aJ&8`wP#H-VmEIc~$tT!tp{@iF+I2lexkA~-kTcf?D_M&}b zM`U)#0?}c)I~$i&RYh+3FWTpM3p|}A^TM6c1;s}AWcZBlP~(!4Gesv#&SWhQpATR1 zoeI~vC+2tM1--|M(~8qPCu5a`!!z46*Ln-QM;f<#CPwRH6FsHH&d5;Deotp?Ty$e} zU380cuD8a~;poWdEm>bOG2@(PSM>JivEhTR>!UB&JF|w2H9dozJN*|!**P~0dt75< zmW+!*SI(5+R;MG{m2=6tGk=}0J!@;UJX#&Q+xWbhghr?5%#leZ;U754} ziNa*m89g0tijVj^lq(xndf{oJ-^C7Dbg2Sns+?vbl%9hnR8Q~vRKc*_kSGT z`#%ov{U3+_GXKZnPtIrW?)lq(#jx|CVv9cP%-{m?R~vR>uuJf0-YKCw?3tH$NPOzf zJ1IWx9h@fqYQuKb4-%g`@3|xXYQwh7x+Oksyr*~8>*CYeyyfE4>U%DTzwfLZfAA`- zC$*E@^DnnNEXw8oU%c1-+2^@`$2IT7`%7_~2Hx+;3;sf!1q1mm7-&5|t6mOAuFR?tF7U4B0txmk!#NVajQ=ND(O#rELwrq%D+ll13SelLi#--l^*fhL%I#(C9V{G z>;1pzNr1|GD=h^)58%7E`rhdlKhFbH@H{{z&jXC%d4RDz4{#sP161)m!2LWAFplQ| z#`8SD1fBHj=#`@6#b+FORN7VouxC49rcTgsc?mEMYhJpa-6-zv+y>-hJ?d#6l)sZM__ ze*3%f_(#jN_+9cg@!s)=&vR{u<;$F6F0~!79WaNOgT$xhW}Uf8yc&dNm6;TpI zPd@T>>|N{;u^Y^j1Ftg!uk!;hS!NmQl6h7B6?1Xy|0BQGT5)fMn5pttTgURNt@rV( ztyTPL>;3#{>o|V3bv(b?I)PtpeSlwWt>#x-ALLhCC-SSU5Amz5HT-Jp!~AONB!0DZ zGQZk7gzw!6{r^zA zTdiK}O02x2mO|0`7Y5$9{wV7s)LZKK`;N}_$2gkvPp|n)Z!KNCCk?#Q|9bp)^3x3U zw)Xu|MxXwtab&oV3#|@b`PO`Go_MvwHf^c4Tw88+Xsfg}+Ik_+6XDC1PG~m~uT^|r zCH`&|?@saB%Bxj`w+j7w8ApuJ_YHhI*^xNPCxB|Tc`35|M zW)bp6*b3*stMD}JBW4Vy!g7coqn(BAa2;F)FG=cNI2+!PHKmo74YX1kHQG-bj)mD! zgL~luNIHGPAgR6Gi#!PVmc^=%;rY)}STaD-@_HunZuk_>qc|aPwEqq};STs!d6l-> zB34c9duU$dT62Ih^alFdupfR0{u=HfW*PDe@If@W$X|hi-Ns2xG+g zE_?v)qWo)+Yl!nz{(sv}ytze?^sUs_N*u8&Nj?EvxQg8M)ui?`{FwAjZJ$Pd9bP5n z>BMxvN8o5!3@1Q4ydRE*?T}HeuOhWC!}X;3S@e`v{}fEZuMuZ0wc7+KkM*8AKt9>1Qi#UskpF+%TG?S6HB72E>82RH+ zwaF<+3ALjZ;l=CUroOdsK75Gy9mF{ZUnb>e(JzIRR&SyV_ac87W8uhXbM^gtES*F3~ z1s|8P%|MfcACojjAg4%b7Zj~F!Jo^kv@?W$1AZHRhpV1Mo-LWOOVN5=#Qz;B+#$z% zkT1hy@VoF5JP!NdTS}Jsigi!QyGj4okobBpyhUiMq*)?qjlvj=Lsjb&$Wve~npfb< zP}TGY@T>4N{0aOiaR$?3_fp>j$XuoGhfl+2VH@R9E&0zdF(Au!Si`l=a18nYd;~s5 z`m~i8A(D?m)$;Xl77W8_lyJSGc9+mZ&_~GY%gEc|TIh$H$^A91>Vf};{tE3wKWeJQ zegzwde-izV;4g?jgPKwoeG8mR`S%d#=V&@0H8s>2JB5ZZU@j#l?W3tSq=m&!I*mPa z8vCi#TaeFKerl0Blq?S=7xP!@zmM!g-bDQ0!#Ay86{HsWSxD|iDb(N((Z2yznJ<#s zoA4SM>T7!&GCpmpPY;sP17PWj`0l{$HtChW6ifctM)HKC-)r`@<)(Mq&=(~tUv9RBZ5OD zwWWmKBW*cNm5_B_Q|tWa`p(PMgU~2tn+a7(7E0MR5(Z!qp>qj+9QkqNDUcmgt5+oS zA^6|Wu!d{Plm@PrRksYJ=W1CPCF=?BK@Ja^kI*>?A3%042mPtjt(gY>L%pUg$rz0z8?LpS^$q&NP??4qMUul&en2n8tpXE!)$`lhhtlHHA;8tI)@#H>7`#x(uP0TWF1H;=DzTdZj0# z&FWh&#~3lO9`$6O*yHpj_#~W)zNPP*)cqjsFMJd2ORDaKHpza`o{?irpNEX)tksa? zc=&+y-Hel5r7W4{l*&(NOp#WlJT^7P;?j~dw$p|klyeQ&{#vB~8NEg}qY+EYhFz^Q zUv%X)49r3JGk6i+Mf{PZ@B^q)-Ug|ot}J9VW@bQa8~w*z`+hXa&iO6+gAglPSN_g7 z3B?{WegqTfKL(Y&1v1}tX0g7Pn99z?qcM)FzJT~gI%}GK9&R8GR++)tsK1Gft*gC; zjK!|cK~9IPQAQQ|)5yILU(djg(`j4%f1tSx@vU@aCo8-61jI_$@g)s4dRbKrVj4ez z{{k(@k#tnof%>`%jr2CGuX_cZWIbo@;{0>6m<6^Ko45a0Mdp;(f-j;07I zPXSpEK?^I)hmf&UHSBin_mCFW@QK8JElDeBi~)^4)m1qQ;RoQugsy|%WF*te8g{a- zJWV_xP4y8zl*WwH{O~dOHf3f_Fz_P`yedQW;{wu|36=G(Z008kU4g9jMEXM84;f1u z9)U*dX=)AsjW$&9Ch}tZxTjzpz`}zqYSkgFk5vWsr^rQ z2Mr@fS9`0pvv^XRTIlqbu2zh+fiWgY&l-3@ z!k&~ex!5wWZE9fUfSvO^V@%5Pv60-!AHgD;1k2EbU^z6Q4Hm;}h-IkbF9TX1)Gm*BcM z8{8LXaUS1$@B7`~AHP?xrhBG)PMk4h0&2pPw{)J48xro%)>^JfSMUZQKHie}E@ zNrOuzfUZ<3Z)bHofkByqhkylwAoKU*ehR0|I8 zZ;FYLN@OF6e91aElX@Zf;h61zT@fu=IrlQ;tm29F>M!_y78jv$8sC(=akO+fFs7mu z6ez?7FTx+>nB6xrKaU@g-g-4(LEFXu{_)Gx2e(1jS*<4O@+igSsUwETUe3v3&Phg2 zC0$N1X_UHf6!w(aWKj+Oa%u+mXtVFli$SQIJoWnBqYeRN)st1=!T^knJj#Mb9*(l=VTi*Jo?z^S9_$kPmbx5wZ^a@K; zM7{F9LXd_rO!1x|(~lrC7Vn5CILp8S#+E(IFlKKGs<^D?x!x*&Mm7Q6~Y#+*DtS z(w}$7@(I<+#76xApytapgxAT1dVTbxBhag~UQ}0GtKAm&VdDHTHhG5h z*L8aK`!k9}&jMqAJo$nlaBvq9>o1`ZBbT%#F`CLS zuK0zHStGHH832FOqo`-iq%z3)NE8N22V`ESmt`&J zG`G#=j#fWB0I1cMVxVfw!C6*i0;t+E2=0h#^Q8jdqTVu-E$XyUrT&*iS;ag0%L2&> z0vr1*wj$F;f}@R(r`6^5(yH!QE#Btenruh)w2G(enfE1FtW#7g{b|kBEtuv<3IGa| zd5U0`1a&XH)FAq=FJ8Elyn9lxA>G`K;1Y%FzC*aejk%Pm(ODDKtuqFR>3^;`d8>_$8LYow3AL|&AR z%K%szHX9%~8VBrF-ByFb!9f(LhZz-{+)AnnntWKxLo8MdfB^4MZm?c}ko<6d^Nb0N zZ^K1up?@6Y`zb*v{e4A&qSa5CBl|Ds1lyJVO}0jBqp9^&>ihJg0wWae_z%Wa4_qBz z{80TQ4$OFg-*M;(BajSY_Hb1UXU9CTKXLC0qIJuH zx)n0}9f+SW*Q6{(F0Tei!=IE7azw9)Ip5>`#{GxMYy3}lvlO3|Vyf`V>erwkOD?JW z*Ds|(aa#SwBSEQBG(-rvPN&M7j(2+3XmP)z++?Ih;M3+C+GTBd9_-P(Lz9^#eSZPF zr4EQW$2MiIIX3rartRqU83oz@o}NdXQ#l@RIkT<}H&&xR5af3MNSxvh#a14D{m|T( zgZ|356A;Uu(U4K9n|-(UUPd-DOJ5`SCw2PcwBUz~f9PWMaT=AU=f{==vB#TacS2j` zGnf+DfiFl$m)@L_$i~ewp5GpZYllcvrmXOmavlUHy<=peqFgtMl*;G%&c!70%d{x` z5S&O#y2C5uC* z`*X^Q#`LEhoJqTp168sfP^HeqNm%8nnQp_xoLL{ZQ;~=r*fYhD7C;*1*2ZSKYVF?@ zO%E($FEh?@En{zlIfWWtzb<<{&|PDZfeP#;MLzLi;~&evvZs@l7=FLP8m-4dA<6W` zjA}FW{RpB>N97Wmo(^tPlHJIIR_7u)#=oLJ1Xv2c6Zu#l=9xWRe?ELJ9asjg=`XE8 z-$R#Pj=~<9?9?@P9 zmc2h@t%Mh`^KXNbJm9+v&O0F%4hhZ<0$*iwj}; z^7S@$)w6E5!N?Rl0>P%b0~_1bW~Zg#w}5%O+?ZT?N@7P zSlw!@>YcIzbW>Y6rOZL&WKnTNio}+lY4QZQxc{8+k~oE<#=Y{SM>;<$*3S0dJ8)Oz zQKO;f@Rex&ss7`4mJ5Q4251yzjFA3z;|=*5P0`$kD#woH`MwYo0lb=S5EtXpHB`=z z_TXHx*YRr!i4Tv-3Exc{Jq%P7>I`80>GNZV({Hpf#%fA-l=h-wxyEo7uNoxv4R@;; z4}XM3_SshUlzz;-muP4~!j%=v`Fyka7QT1!EAnh{* zO{hjyn1`;)fL=@K?qez2Mg!W&+pr4nf2huC0Lq zf<>IT6@)v_s>)<#a_ho$y%GC!!3C6T*0veaIN@lYV3jLN102s$DtQlda40^#pyOrd z)TJ%w?r&-b2BvM6)vx#ZdEBM1)JHd%eA&sn&0W-5ruTxmFEl3!^E9JGH>s}ev9$SV zYkt~Q{v%js0>^wKFxXl0Gu>GQ5oh(SER3Kl;alSonrODuy&@)mkRmh9PsM6 zdXUIo>wu0LPICA4TlPiPfOaR{i`8RoYF!Zsytt=DqZ$~~fhMx|1C-J) zHT7uVvi{Py@RsaH@v-ShZTO1DjWVW-6Ho4}nj#2bA@%9#ZOsk7o@yB3SXihd-pD3< z{1k0rqg946sev-j8NDVJjg&+HQ#d1^5Uu%LpQSpll=TZl9P@$|IeYtJ;3On%SI2~@ zZ^Z|Un=-yd7M^3Z6qF<7x*cm@jhc7wR9L=cFgIizV-j>+riuACteDqW&DJ+8A9X0% zrHE91&?x6+n^QPJkpqYa&G%`%GLZhp22pv}WVcBiROdd+r(rk^wq&?ikFbeZ$IMNt zTdpGWW=+!^q-00iq6+Etmy`tW)_jfLJE{H3?Y!`V7paTe0pSfPY1quiG`1qn_j`71 zXyXjyV>&QIFJx>P`NFml<6w-wxJ?ffartUkWMnp$M*XuFgKiF>IM$$&k83%#_tJ>t z$-MeQNsYy-|zK%U7MfNi{WZJFF=BbAnL_TMCU)lq1MDh9b26A)Pih_zdh`=_58BFvGayCPnzd7 zf{wFA7=9gVl$?m>&Iyxa-;6;k6v~+e9q23xiv;k`5Ns!s#kRvZAHHN8J+tFOR1@Lv z5gKvZcuub@mm1lTmzcD+MlOG6Ut;HrMhvGn8uq?rn_CJzQLTOF>wbruA2t*GxdKfl zM^#M(d=}@~n?l`KTcH1CtkUy0r7`(W&?gf8?}u6UzPRf?=Z2xVz_#hd9*R58@&kNq=kKrIO!aQ9_#T+JND$mMDfM?# zrl?JHY?F@lMnNN)?M0CizVN>C?1Me*n@~^WeGi2F68a<0Q~|*&XGDQaT1JJNCnR^o zNH#*1-h=|Xi*|E$> zofavRWc9pT&7-aV>8sb1J|QgnaYfYM zovIZMIU?8ns(_}gwVs}8gj}laGMl$*&Ky9!&(q>JtIp2=Pv)!ZS-l?Y}WZC_;!&x)B zyXvtzMz6WcZsAq)*@C~Es=D2adRKtV>m86YbA<5fszpbD@TO(8|K(0obE4wWM0d=1 z+`Vx)P_*8-Q_Q!7^|N9`iakztr_9<}Yo^6T-fOiO&|uIviQ(4jM{en@8oS{Ri5sKm znmy-ybV{}0TZp)ZPf)1|ZAVI$Bo3qH*z=?ZrTJKbmm39X8F0d>Tl>ar9R@rAGchka zCnW#KovYFfJ^Q|r)SmO|c!av1vhTKI$4C$ucw>tF;Lp&t>a}j~XBwNIR_&w=cj^|# z3aBW{-ZZS>VeY~yZ7Kj+nHr8x^z*o%wU5kfc%*iEuVR9jznv1>-v%K}(vBm8q>n{?q(vVZgNh~}^5nf@_0AGv6@H~~2XU=ZpOs8@P(Gt_rQVtIfH`Z(ZnSUCFzl*t|9mIGQLpYGchfrQU8Yxc+QXFUm( zD8NcSGyUE(#_1(d$6;)KuiP zYR&SU9lt6_oohjWrvlRI&|T!Ue{_Re8|gWMR1Ie52eYk3opbZPQ(ENgY$2uHAwGxa zB~TiGU7cf41vo5F4JOYCQKsmY*x1-HguaA;4j6CA@AK^zNZiko+r5*y zjk-kfR(>5qvAVFE^??0kwmk)j3BvW=4q zE_%eLy{R8)dkFs>$2OU9i#JDsu=%J>V-e?U?}`8MkXO#1pmcvR05mHn{p*bNwH`nc z2XK^9COi=)7IPsZJx{tEL-FazTh)$5CjdQzf#dydu>_oxn?)9Bi=wbn_wQ=l`h2@a zmrO;E1%7>s?OZRY&5W(c%14?Ob?qAk=IIsLBMn%hzYTA+i4TBU9d<9;lDXSF4Nzwam7%r&6^XG zST;aZo8ovLu z+k8!$JU>|$Pc{ut&yizDZo`CRB_jpAWv+O-dwS+Lwdm~DBbE={B&<#0l26iG%p6m> zpWh}tOwA&<|DJGJ>%pQN*k1izNyk%mVjFsr-tRF`L@BJ#K zzXxaN#^k*Y(m_%qnR1?a6tv^xD8ow(3u$>vbLWb|2WnceHAqyzJ{z`{Tm3h&>j>%4 zSxaec7l5(}m)ys@k(gbMy=OO@uEQ?N|Pt)SGL(>hUnCfm{C9%H&?m z^Emy*%@7~jN(K9p=)DI|93Ax1>(Xu2wj1EqC*fYU2e*hN)ovdWuo-cVllse%_kG?V zI}GSGU7CLIWnxN3!vd&+LLVT#9xem-OHwin^it^R_m1SW#x;Ki7TGC#OF#ecF zGNR2RZpUW-9RGvbiFemMUpw$$Mi$oE_`j>A20j8VB>gNq!wIum31C(GQKk1W=dyhr zVii39a{lr8l#>xS0g)xJ%J)ol?fNCpg-2i?u8{78Gg1F04XW$e(PPYd;l(RsWz`=o zrXL6{e38B)zWYGFy5*L0z|V_+c|xO{J5+w07GXH`sc1b)5W|_46%tl91FuofkxS5y zqjB2!*@v$TD>BK{q2&)mLyIXP)i+l{_^tnG#l$nUo5wT6YBNqyZ`{1*p3es1`Z zOOdrbzZ}n4u!=glm{0oG?O$&+3yLL1pv$}++P;O*zGM3>KUhQax&GQFp>w*rMm_5$ zB6Gs-NcWO-2MP&>^%tHa@uJl=>vxIr2eNtcJL4Y4cIlU%mGoIoN;_dgnm_#|@vbKY z7$uCP0&=GZ68G9Fsq zx9W1fIItCkawEhDGoJJvkm_z1fR~vrCI9)S#7#|jqMxI*(&bPYxC7B0F;r?sKcJmU z|1%&6-y^8F9ZjviNWvFit!aov=`c@E#Wi;&OkZ@p69w(Nls)TXNvGwCkR{c4KmmRp z6gmyTT39OC`>~gmPNLL>CuCeK_sq?>5xm3csN5?;;TVRnz#H)R&F72IyD7W6DeyKF zyCWc3p*rz|I=OmI*9{XWu(^(f|C@jf=`34hONT0*j+H~!6!&H!#3!1D#hlJB#`}-( z8PjXiWk=giYl%oRo=7(MuoQ|S`Da9MOH|befv1Ftr#npWS(k*tt%A`c-F+7JmV!6wxj1 zJN;Q!^Ut10+@*0ahu283-<$K)pE*+`>q zWWo5y7vZmQA9{{@RTB1Ucd&l7^2Oh%ON+k5jGZZ0`$Seo7|uO1Hyl6%y0~-vAp5qe zHaN;WO>9qmL}}G)h5X=S+chi&KV34n0$L&9cJEz*%Rf%9atn0?7YleMqX2mWweC3S zq{n78J)y@e!K$^h(#w=3YmVKs-Ls@ekf&PfYsf_^1FNm~H0K_k^L2;ZM1{h(qk4DF zN*R8%RZ~6KQYiZ7_qWPMulnzE(AwmbUia{@u zmg=T7bMbMB{+91-%13T`ztq_m85M1h!Tutrzsvk$s5_`=uiQ;Ne*F?jfKq#D@zZX^ z5(v~RbV0cwYr>({w1^5Hl(h8*_dvIXaV#5eB*Tbx;Rqu!fei@Bc+}ihC?{-kOmhU< z=7~$iTs0GPwQ4}4Tvd~DaF0^{fJvn)y}0e!WFqY{piq8_nI~*lDojH!05f69{%MIl zyJ_prG0f`GgXZ=^;e=nVVkb@8J#lH2qxOQXHr2x9P}PKIYG5P(|IqI${{`tVVgtC< z7))Rr0uC89w=2rYcR8kG0_}jrrA4k9B>LJqpb@^B32?DTxL{zb%D+<>tGyk;%^l@L zO0MFJVCjORmYlwJ0B97p*ppo_KvM0mAseP)2p8c;gF{1&i-Hibx6rz|6<1pbduyv(pRM)7wC>}m{qIFc`F-V28nRKM;BN2YppkO{q zDvxSWjgl~sWOdAFilXddfnvf!9|u0N1sU!JqlH<=VMyj$j1f!FUPwAd;E^Gezkrp$ z^vgX+uxU^QddheEc1pzTRr^(vA;9cktVPFZ;VZK$F?43gw(=_PIu2;OLN~VDE|`tO zX)aLM^w$`nxM-mvpA0CEBxDP3b!K#YWPLOmFy~^2B_)Jhl{mu-ENNe)d_-Mv0XU$6 z?`#sgHyn97mBrE#jwbOQEl!KNo4B5;IMFSlE*Lx!*;~M^j4h>2jLN~vExQZb3*w7E zsVpS;8@_!G+u=o4z3&=~agu`}TtD-c5!?dTjqI05QSp5j1KTH59hfpd75Cvg+@5d3 zqB!>ZH5@qB5S4qb(v#UtPM%>p+zS04nEJVEgibh}o(%dct7>?N-i7qmIxu7k?QM8N z>u`E^9k}#)exAU=bTa;Fwh%*uA2-Q8T*jaKhqY<{(ch5^zWG)4NP8L6N#Hd5(Ho2( zd~detd)RH@R{ND|7*8Bu?=Vb-I*mnmjWUzbg8To`@!}{2s&7Ujl}QQKZ~C-+VhLc} zbjE@b3(VG|+6C(U<8Jv3&2WI6J7x!*;|an~^~G>@n)C&_@pyo~AL?m$KKnYQ=P;WiL)Nb#KISHz}M3v!kJF>M*1>S}%$ zp(Qgk4>fG~n<`lN?@}$x!(^ zCV|mxr(Z<$w11bK!u0dO_}=q^w+&At=LAUkHZGiA1aOgYLsVSO1|}73Zg~6S70W{> zCbw*e8K&b_dp^!Vts84^84HzDEhZQ>dq#C_D_As1fi+x1=`=M2lx6F;KjC%tadq`! zmX7QDSc}#qCO0@5m)pR`ifg8h+qSX^+P?DRBNTnTGIyFEmB|KHHNf3wt=;C6zuC@l{buFS)!xogXzQ)bnW1>8!db+v>g@8g zj5rQhG=z;bwvc$AK6^EH-rjqYw%k6H&j7dmT>mvLP6+Ag!>k?GA6Jg`)-T!STL@j{ z|ABjxAZRb0UMC{Wm+d8&?Rl5&w~)_5Mxwj!I=k+!yYBss%Aj_TE%Tc2!HPcW+Vqy! zaN{CGe}2o$G2)n-xoWYg#Sj(-q51IHw8G03DvgLunxb)J{dV75J#=q;76&U#C{L=CW|$BDC^J9EiLts+-u> zd|?6d6F-(&DLW3-6^O)T93XL2(@$<16>ki;r3K(fIf0xawj%y&eRZ{!o{ud4Bjx$* zp4&FySFU+wUwX62<_m~P^wO_fn_uu9T->%VZ+t%cG3gSa6k+nDWi8ny zdQY+iySZyWf>FDIQXz{X7?+DlvC<6We(Fe`4VZQDfJXKO_eW~?)xYb)x1Ml0JQvH4 zvN=2Qg4 z+Lj!|;uqr~c5nvqo)^If3H%32$%Iw4{CIzRN*(a}%)|D=_(C((y`YiaW-YCpWv_g9 zMsUwsj$vzMz`ni6H$B;!9MbFQVM5J>7G3;>$kWv(j5l|2&!af=lqSP-YbomJKg=;&D zv5Rpp41Uxi;0*<7ll7k|>dn@1JCnypR>_u}`=!d>2y zh0ou+_$B)_n>D5l?k=0_uZWR)k$MB7`7v+MM58SeEs8|!c06{tX9N%qx3K;pJJaTC zf^IHf#_~uJJipk5p`1vOzXaQPj;arlB7}a)zAshgJ(NPpU%bi$HR{0X+of@;F_7&P zHsxuoxF%X?n0!dLSK6$uQ5yIGkT#PJNL%0s=oB}0vKQZUuvc?+)ctX7uQLR?nzQlq zJk;5!*dL@mNipHe|J~DO0qblOHMTi*fOkfbYN541`BaY`c1?A?87+WOm6`djjZRhI z+0o%fU(Lz6be;P^@ZZsUT|&m3c>?WLGVT?Y(X(ahcC+icF}DQAh&PNoQ=f&Gif5ht z>h%pfd!KcvnLGExVRw?%nl;1W73bNC*5ZBg3ns zUzhHheD&~QgNtuI4%2PIEmnNkFeD;}y$eeOOT<(m3?LWDQ$#~c<7e{Ze3=q$Y`Fh1 z^Ot9Lg4^sKZ}Cpz_!%z`pTWe%B*&zab6$O)j+K&AwtF^DF)u4GYpQw{%B1|B_~cZk z;$Hvc*yPwAZA=H&?p%qrR1i>l@dI4-FUZ4YRYPwTE>}E4!=xk>OQHX>DokUfF!hJnxnC zVbme>o^@p|w_l#?+#Y{r61QL3&CH%xWf(VLp5M}0{2}Ywdrv-1I8AuZO-L@x|LD~) zNwo~Lt2nFr47u`?Ef6MTl4I^WXrAZ_mzaQ7ID<(SzCJ61;rG1oo6lzDNpcseFH=d> ziDqndo}`-19e*^NU+66)2W+L%o*+d)4sn>Hk8zkc=4{n7|JXiQX80~dU$Pef^`PKJ zX2^UaGwfg`+1u524Ae%mz@)U0>yyHNl7Bp%S}H%Xl%KQVAuZDBD7ITCVj5v&6Bo&h zU>fmvNo`_j%hcwAqv<1_-tS0e@}cBUrt*okgFkI#*=Xk3Xm;?ikRy?9B9Txck*J3P zrG^6QNKhma-k4E{Aav?r=6eG;-@ipE1|cts1ZCicq0`p zd%?naORC)nR}yi3Y+&Do6)WpM?8=J8b7)A@c4SD?RpOm?Q01N0q61^UFkc^&P<}Ji zdNb<$55F0LTv^r6#1~@bGgNLUXDS}!TB39yr){KR{%>r5L_!6fewO?KewOr+hvBkG zz;GRlp{!dh>wp1=HXHmyMgx2_{!A}L;2`M3`IWfdEoJ0s$R%KXJ5N-?r|(>`XEt$|UeASV&9b0>qa&Qdx+Q;C*OgbDR9#seP+ec0 zQC(aeQ@zYH%`?E$$FssS$@7)PDc$;B4y*`nGmEK071bAw42JB;6)G%Q?w; z1G>xE2OI#l0GohQz%k?>(IAJu=--_AeVU)X=Ir>7^jC$#6Fr=_Q$r=e%OXRYUV&sNW6PgzfT&qGg954h*H z2io(}liM@X6V_AOlh)JPGuX5H=aW}}zY*ubN9SI(8rK?w8q*s28t)pd8v7bQ2NefP z2Qvo+2OkF~2QLRr2SW#A2U!P62UiCJ2U7=m2R#QZ2f(?}xy-r8x!JkPxy`xQx!Sq) z2=cvHoC-xE3buHqn5{UmSeE#@n2QQH$N9ES3Q>_*Eu&LckC@WYcSlVEr<82dcV`!sk6KU~Kapuu|_v`N8UCmv|-O}B_-TdA7UB_MC-Q```UHaX_UC|xz zZP_Pu0e3-pfpvklMLIM!ED{co#S1%OvhA|LGH5yA?R9N0CoIn`*DrrwmR~M+)y%49QA;Tq z17jcSE;Lpit1Pxw=^0eF`MSa#2ZN)^2(@@x?WERE+U{K=j*=HDE4-`h4AzI*m|a(o z+!jvD1+?7@pdRag+vZ#?j#=gn%G%TGox1d?Qbx?32ldPKSM@{m_w}3gr}T65o$ZY5 zWb7pDT~%+1i=f0qvyi08kaEHq;F20=0pPLDitv8>5ex zaXu6|6S!BEm$p~LmswZqmqJ&d%ZYpcd-8jXd$#+qd#ih$`}_OBd+huD%j2tztJTZ) z%g0N^E9uMOE845#D~l`K%alv4&zikjpE&UWK>{KU>s)}XJ(>%ORC0N!B9b8!D_=`!)(KP!g9hZNHNtelxNuSB6&!k_4 zd$aNI9n`Qrpd)F16HuvP%n zy7PQppI07GZZeLW7tX3gRQw8FB%Tp(ERI>h0D9fQ?`*m*;jJd6OKnS4OSNzRm(Hc~ zrRJq>-V)vh-ZI`Q-d5gx-sYB?mWr0LmZFxfmeQ8Smd=*;mTr#{j|PuCk1~%Uk1CH^ zk5*Am55f;9GYG}xiz?QZ>(f=ars65VP?S!B2d*zRcq`w^jP?6>g7HzD32``??6fy( z%8V8JAA%K8^az`HPVAN-4keqG{b9lCC>8{hT>3UGYV2|gg|X?nMe;#vt@B0mUGt^$ zjq~~Q?eo=~e>ht>D>%zIn>cGZ8#(hi+c~=%N*XE}>aO*z46ID8pO*yC8psPq`^Xz{4U z=>90~SW1ROLNopJS6ioaC&j`du;OVtKewyZ(Z+mvslEDZk*K10h7@;{6#;~^)yiwG zqR3P6b4D^}rKRqALz9*G++NXQx*O-I75}tL%c1t%qarCMsN`ot@IQLV{*RlYC8qbEw#B!~WnMIAVg$ci zzgPSG<1LjWNed}SAirJgH*&R4Sd5YFIPT1RrPM*XJF2rWTZGhhUm9y5J%HXJspzR41R$YmuA#Y|q`pon>56yPVIn z0?vrkvc${&qi&MYj&IA5RLdwGEiijR2ceaq5MYAU7WU^_3isMA0 ze30}<4U#c`(i1FKTd6-wQ_7wUtzKM|dokg5T#FNg>6a~QF4Bj1( zJEr30Dl<6Yz_^A43AFEZ|5K)?*w+-ifNdAF`bVh|p*f}j6nKF#q!rhV1o?gToj4+0 z)d#T+Q-hm5R8Yd2TwW2;D zAmiG0wpkVeHfKGfGOO#eRVm&kbCl^7g_0?6Ds3t`S96lj1uDEXFuDI#9j|E4yN_cs z%2zPe)&)+H|DQtn*BR2mf|Xz3-EyJhk$5 zeI$aH?q_2`;v<0tu*3-ldY8UDSTW5$Pia?3Q%Gi&Gds}7Tbvsxjx`M<;pe`ADW-q@-xVW0!Y9HW;z|e1%rC`#Rw~00Z5Me{$CzqQ zX*AwNIg2oLyR2aK+~jVV5nQBu6Un;I&8P`)*7onSwx#0)2|(|JKNa_c{Ogar(qqge z@rMM(^bMc;A-?iq3-@SuVZj0%kbOQKeck_|wkE$s>mZ`B33o2a3orc9wWD~=V+L?c zps`j`YDx!FTH}u@#J0Zo4)lqMJ$rj+j>q4oH1FO~(r)J_(+R&L4OIUper`N8RGFj_ z({t7*y=i)t3D+>1)$+ftsuUlT7vNFYd}=oMucrvEM!mt_7jp7gAK|fq*tOeT z2@a7PJAz}m0xL>o+_u2RPH!_^$^%ZD_@e((Jvf*n@nXqSb~%4^+J%|kPaRNJbyLT1 z0Ic9a1?aPpm9z0n+cG{$I=J-{+8D_$XT1hd0>9o$_*;nfAJ{Fp<>eIo5WieVih8c0A2Nj&|B-da7 zknX*JWoKHXsh(B~rL|Z&rDYazu6>nVPwA1?Fnb0&wF}5DqR7H3^_nx@kp~hl_pxM< zqksP(gAPYg_wf@sSs=B{lBgLPSw^T0+`%{GgO-26q2J%(>r1JkzsHCJK_u@cg$!7( zhG0K8t{#0Mk0&{=W%HH%`}41wi+uYu&F6$r652l^?v$E|7=)rH*bxNsEoW@sGuseX zA)QN7R#9JLbxJZsK;`nbPrR5C}3>SBmm?)DG8+JvbpqBWe^T?r1@`>i#*o4*J ziK*Lmz2h(&8BX#kT!{*&HHVjeYe%*aFOG9}2H%nqlCPzS@v=v%Ilw2xYqOT->oyxA zoA#-BG=4owjbu}1+Y%fYgr1eI-ywI{7WgQph&0>x3EA*?M9LfvWwIJkaT8OIyJ^KQ zfNkTd+nLezx+1hF@l$_)>4?-+984}Wt&;8XCe^|+p&V# zX@kB&GxylXL_~dy^P}jwmtwG=@7Q5oPs(`?*Rzromih^i2@;j6o@E|zUXv>DM7 zNz~~Ko~d*@Y-obr0n8TX`X0w#Itb>5{?Buffn&$4UtsBxy}f<}g(` zS)#OGYTrx>3Tq7IEXWbRO*ve}uzNIqIr>JKUZecsCr2ShXG>nhdUgfE-p9C(o#s}t z-#%E5pSLszY(q0Jnkk_YYe9G1TkR}u?VtY%6{XK_Em zELbf9qWr@ds0>|2=b^NdUJEB!B=$LeX3MOB7oS;4Dk925SK=*P=tyn5|3wg@8s=1SN$C*0Q3^ z^d;2rjRk)i>FH?UcMJYxeoajH?WCrngnXHicdt0}RAlL^&e=_$4*5D^AHK&Ud6g0I zv`5k1I%3aq`F};->4Bwxd5^dazs@Lqf1MK6zL0OB4wwuyqeFUy?S>!&>jLjygPEa3 z-+vY)o*iC-41E7o+s}*mm5dR$F@bmW+I*y8BJZe8OD%y6E9v1)MR`f3mgWq)Y2mkp zc_6DL5tPSb<5$j1J%VVtepM@829*8eVAHv4?bM9Uz9ge+2kLiSF?a8q><1n~LIuzx zFd$++h>tBN1^Fn4mg4*?vC-WBU2ON`Luo<0p!{DGRHehhSC$^)Q1L|=o%(){PsayG zZSiO4OJb})Ccn`u>Jly1aT+f-*6`0f+qAfHI&v&(vp307k7gw~tjRoYMT-1YwwB_FnRCjuHr*Y^W0JxM01 z(e~qUt$H6*LSU?x?7S!Wo4EODXQ#8s@)k~IU=#L@(p<|mEUxqHinM%KK50neK zE#Hndz+(41!O)xjPmQc9H3n>8NUDHdwSZ5S7O8;QN;+QF`>uudn+t7{4BFj1xsWVC zE#;aPZsggF3?G3~D)!>rmSqk7Dvc_q6N;5KOXXVVWE9HQ( zHw`$IlH9XjS3+&_qO6?j(u!uecZ61=n`i|rrB~uk^3oa*mleHdvv)qPWZcp|9=_v` zCCUpp_~aCbGaa@=1?(Y+Wjyf(r|O#<=#V;PMH#EpnaeL>67+M|Ma@sWZ40XRZkXB6 zYTx2`XCxcxE#VMM-PUz-_H>y-X2=BoDyc?f8C#T0Ox9lgs2w|DM{yjbM{y1jXrN*p zl%IRcwTxwDl|3*v!`?wrEi;Bt1P`93f}KrU*7pSWSTtz-yXq0;|K>m^W9b_UpMS7r zr0^}91#J?ICI9&MSODVzW3NWN%d@_6U#yQUnN6mv}QGfa7PG1lDI#a9eyj#$?b=+T#tt=J?fB*fIX)|C_WZY0Ayu{^51xuT6yb}&2>4U%zp zB;7PN8sOXQhF7>+Ayu|${}xXDZ=E)#3`^+%Wi4erXC-nBi!whvts`foqtu-vH?6C5 ztpp1-%S8wy=0#nnwX3=`h9j|$TKMfM)M)2rO&j?uCkcQHp00x)ss`$dktj;^#fh~u z^k+Z5aq}f*$_u?T0ZZ3y2NZtl>YPj%`glGPwu!0Q(oZ;h-?=}( zms0vS-W=jPJ)Su~o;f?72_Da!8P8mZ%$$qNT#VG8kJO)y)CWiE&qV4kMCva_u1!a- z{XdMo1CV9SvMAi{Y1_7K+qP}nwmof5bK15sZFf)Gw#~P{bI*BJSD>JJS zRaraM-nFtS7h^Z(V>gy!H|AnLim}=&vDz_=NM%_`wg*32Bj^c9mJ^c*zA;IR(2YnZ zNn%6eevlX`geKK-3`lZP0}6M8`T!G>`M}o?79%7ha$E5Xs1ZO(k7PuSk6}cH7sZ5v z1h7>D*szR9Z6z?Fc#y;ge*GZXbqq~%l$w$h4ozZo!-9I>NJWnKz=En27?re|lEj*l zEHp2!GAET{Nv^`8s>LcVz$*WZRbGr$UWip*fmM#KMYH?P%JP?ug^iVkjg6(5m8F@D z#Eq52jg91ymE@6)1df%YBr(Z(RMO0&Bvj>#kR*S$* zT3p*we4dr0nw8`O`e%vg&ThH=c6J%j@g zp$s&02W~)~~^QE`|bJz5@KpO0FDgm?8zEd~{(o z8z8pV9b`6Ku+Bc-!nq9~=Xil>ejV5p=*9>zc*wkXaXmaIYkmdW`w6uU=mWWT_U=lP zlf58+(dLg?+^+h`oSJ#?Brk?%zO)j1%&m2B+-UMvIcSN zBix{OkvUAQ-@$GLJ?|vk=XGIRPrcvRZlyo(e+FFlbh_-yd8s6B!)}GQ65(&fx02{@<+W1qx8)}!QEF<57=0mK${D#*$4WcJbv3NpQUia|?KH=A8 z6(&X)G;@Gn(h2(5%;w#8t_4IOU|s@u5&&IV6(j{++6kHX%wV7^ewA}_FXyav%~9gXiFwZjdd-`+MZeJI#}+HHf_+p0q*{@YndQV*0A-b=qb`?2 zbF+*Lx01>dl$o1vf;ELSvqGkmNU`$L4pJ{pwKUTPZwRw~;MdMwDqthB_zj08f~TFn zRP<;Cx|YaZ_$=}?8_HfXW$E$;bbv@_iESsPGv~UN)$+^kG$c{UboQwU^Z*rMPCik^ zwG?52{sAdVtaIM}L1`_QU)*PQglOgjTuYoFOYVK%ze!*!$QFM;JI<`Jr;6Zw#(4!O zZ33c!mpu~BT%nH0mU6;kaK({5IL;K@7S$&?&O9u!GuCW>#gjcq&NOAkls#<9lw+07 zJ^OR?sxE&;&m92-d>rd|V+a50kRSg~kr(Wm{tPJZC>?$K6xsnj5&jXG zS8#Uk4Rd1ePq#*lyvd1s=)`{2y;LtWeYL#w^g}lp!FaEP!A9R@GFQba4E$3azX@b zA%$6-2k@fcxx~+x5MoORlMu3Cr~a1$*zoGwYLO+5C8P65x5c+5ZgW2iyw;vpc})RL zifWZ5tMgd5C2ot{R(eg0YMCXo^Jurf9p-wi_L>~kI!kuv66f)cD85%(&!n_eqh_$D zN&2TLO3d2BlD(+&KkMz?N%l7{#IpSGJmw$uu^!E8NUNe#F~!r;SW0;`16@^QPkx>lZiup_&K6Q%RBlN=ZD_V7 zSs#Zq4+BC2$#A)HCAo~r0X ztq-oMs3lll{nJ@hGE7Y>wLrR(nOZ4TO{yYCTK!NBTutS#acSTQ!0h_v< z8p~f@z5-=6nAB433Uxpx7^O=!$iGT_#oXnxk9B8-_)1z8m1m{+YMXyeDk8jfA62{6 z2vV!xD*P*Y$CW@;Yf`S7+}Akmav^iw<--@YPIp{g@twK3GUY9fjml!~BU27t-8#4u zxHof0a`313OvC(gY|CmFW=^jU+E#zDAT|sNCF1b!!a9WuyK_!rUBw1|)b(K< z@}9=JL+3IjQpCFq^PuEJ0ba~Du>A2F&phM3lyxcPVHvO(uoyfZI3C0pz!*#)NFUS~ z&=_1E;27W-Y?W^D_^u$oJc4YxPJi26l7SSF-7h%;trcKWEs`=opHtMvG7LR zX88mJw(*5tXZnX+XW|b(%O>pjluF$4EjR#*$xEJXAKpw(P!{#$1Qn;#5IIx@u#t0XaHPVOQXG(gvYh|vIv~jhin9&y9j=3@9eIFZ_?`@+Hb*OMJsg%-K3g4x_RbY-_3dR9W+s< z%F+_-f(c$=zK2lD5n2{~1Zv{no>;y`=V&DSw_ClZaF+qQ;NPo|OTgF9mD}&Dl^@?n z-~Nxz_kA|Y?|%^ZY0?3&;W78&IF=kq;ue;uxCD@`M!^v+bn9!z!tH+&;b^rsCxCtb z4zEPAE~Zv2T1>HSqEXOz&Wf55dA@klfQ$cGC3MARvyzGsDN;0c=$;d>f&Cz=GBhp7Pj zV!w;D)46%i1@E=TD|EBjG6JFSDZayVv#34`qQJ+)iNourR2K;md>?#o$=F8T7Os8e z0#02mN|U*!4qgdDXQkFqF%NdmUr8?4WUb?7)u6U54af<@T8UR}(%kAjORla!6VcKN zp%ZdSvZQE(In^Mp3I3oI34An*zoct}G}W3WNP1KJ81)FgY3XN$S5P}~eBj)nRr9m* zw9`3GS7tk%VHEBGv|Xx4-eY3_j`VYdozVPcqXvv=ki(t92Z+xIp|NZZ=85(l{HXrh z_}a|uQsE+{Dr_)Uy{c2?0JT2#SA+;cquQ>>E{d%i;HYL+pLSF6G1wNUe9pFjFszv4 zlqu3b9VJr&O&7%7FJ&JrUmk!AqQTe426weD!2XE=QwV@f_D24p1c%#qCLcWhIRP^Y zHv}(I{?YlR3UlQTR@`y&Wh^JM+%eOoE|y5SGRJeT4_F<6^u;kJ#vP&jGU@ZjC(LiW zdede1SiZ0X6C<~`z99L4qf^Fwp##nkn&l1^?yX*$hWc16DN@WxV`uoz1bcKP&vsoB z@Lx8HC?0G?2fi6vIu$$=-4DhTUN{u|H|~8fhh)5FDMrugIuJ$JOc68Nw@~-UZ;FR# z9L5NwetwLV4mr@Q6FIrB(2Ie%cWh>@xa;tQaJox$vPcDfUVu=+bgr^RZW;CxryBJ_ zCsthHi&*#Jr^s8k^T3qD@W@ywf9GG6Cp;}0UcFNq)s^9|Eg0*}1e>ES@u9-Hq@M`M-S64?a zsSESioMnE;UOFwy_2Eey+BZOaS7$w5-Rsqn$s!Y7SBh(NIEc&&?CQYSY;IsE(mLc4qBHrna$NlTzWyug=DcbS?cT!%J34mzVrlaNpIK)8w+{zD0C-t6LdAO>e>BHTpXF z8f>~3rJfKvFKk6h14b~9rci$tPNCr@A{VU>tEW%=#^^L&2K5%MN1WKXW);8&dUl-I9h$w5u+eyh+2K{ z0Wj`O$%yCbKnx2wPqpuaU-+P%&#EiESwcD8$xZP?FhXds`{UVy6sPDEns*#@-&qtM zvXmJ&*-X`v#)9A%fha$~2ZEA=LIukOPX#jtLj*8PWlr+Mwa1ZnT9yn;B7 z)b7LI-|@DgoFlf(AYzQ1Cd2)RqSTE4_Ajso|7bz8fvmSdKL_sAp+8t8>ED($URc3x z38XWlS>=90_DQuf*I99IiSQeEY81J^$9{j#mSJwe>WuZf8fzF<+7ESFYO~#7y%OHQ1D$KWl)54HqV}rrIrGH!%JR|nTJz%e zYT)JLUCq;-L7b7C!JHwTVV%L90hv*rk)Gk6k;&8G%jVPJUFY-R&G&rrf%l5{lJ}nW zsqwb=iCR8K+X`I1O?x8usr0n*KKH`$QR%Mk25jQ$-t6M*{_OJF^1Y_K=DbF|hP~Fk zCcb9Aw!V(pg4AvdTH|e1?sG7M81N`cQ?y>G! z>w)Mg?O`?0F_198Fz_&NFo<`kb7*sDatL;)a7c6LafotgcZhT7c1XE~+wSbK>(T4+ z>zVO`^pk+PZ$*^@(upb!JT1gBw3)-Li}M7ktCj@!Rcr#XrI-g|5tZqCDnv7cOoCrg z>U$pjPP7DFk!k{;L`48`N52FjK*tKy1M`IXCMg6pOgs6pqQ(ohBIgR?t7;13j&Y-R zCqTZVb97DA0mM&_4}3w@0OS)@6WA@r(Z|21)MpFqlhIr230s$c0=#0t3!gzk2>pbB z*bU?&=Fk^Zh+vpE3V}=d1_F=%36zic2^D$gpP=9G4sd1RewN`b{EID3Iij zVIRmX*bXIAD5KJtZ0H*(h;NmET42CkFZB}Wms%jjeJ`=0#+?9FI7mGDYhai$<_;zk zu45G@FsFPh7%l^0^rHe|5fDW*1u#X_TwsbA(GDsT#0?b_x?=?<2cCl+V18i?LHA*Ri-LX$#HaG63F2s|D_%(1+Y0-U9M9=z?lf>%+hJ7VH9V zlk0+e`Q-@-h|%5_+9cWn-Jog#LXUX{_K2zu?EC{6=rhFLmoO9&=<~F8XQEEkq0;hv=BV)*-UKb&#w0ZwV*xoA^MVgKsHa&@PG%9yg7Rz-v4t4&d@O z@X;YVLHa%wXps%zhsb=O?mhYfg$>YH=6@|E zfd}B>Or^kEb5_GXuwMFLa?#iUX7B=5Il=W~IyuJqWABfQN}WvY}cd z?#-;~BB(9-87MnOBF5V`Dh{v#3IlKty*|VSEjw@znSPL)KM6i2sKR%48DudgzuOI# zu-?b}&$mel4Q(f8qwN~ zTUb~|*&0Juqc#|MvU8(w9-GLdiZS2PZbn}BKY@Es6Wm5#O17V9diN1t2fvcPzyhcO ztOBqC3VU+|Rt=W&4;Zd%cWO^+4{9%J_iE2-kG>A!Gf%(Pov-c@24EK=$-)`7FbMSx zWDIDK4}Io2vW8ytpX>;UD=4k$qvGC}&fueBdKfymp+r3r{9`re7K$todEUBD=!T+t zQ2jDPO~yx5389$uOgfV0nHo)w1pPsi)&gRKQg_?xs!rIGP75b6Biq-3GFsZaM5Pm_ zm+}X9rrMI6X!hlYy9-i)Fcp~cOuB|V<8IUHs2h9gy6S@K3hR>V8tS6!!t3(tdg_Ae ze$^$_)z?MUmDgp~wbzB!mDHuyW!H7qMbwqmrPsCACDhf{<=6E(209ivCMsqshAE~h z#wq41hA5^e#wcdj#npv4MmlCV7CSaMRylS#7CJUKRyc+)`j>|&N0h`%(`}f z_PGw3_AdsqibEpTn_G*=CNuFHdqPgGL-)0GL#LoCPGYX)%>cEWxMW0UjAvG8Wr_*i zX%f|0gn67d8BSMh>^8te@V&D_cTBu$(p zaY<~PVRVEz^rWl*apA=U1JAGV*C#j zU^NR1GoXfz8BoK*$^1_Npq&3SWMlisivO|b5$X~Cx1r?v|Az9P;rs8Of6M+i6`=GV z8~%m;UsU`{J>$PD{;$&hFOC67{I^s7B^%%p!2RFu_y_v$uJ~7*|0?-E;QyEv{}-qH zi|_y74FLWBVR^g&&ls&Y$*^fa$p&%{yY9mYf6520Rol z^+=NucU+y@G){R!CtT}4L6S>JbYu;rq+In@AP^0^#dJEsGE}pv`r|YsdX{YlF!aTO zKD+#D%F^$YY!h@pg&o$Gg~yG11CDU18k~qO{rtM0^`-!)gw9L~e1F_KxO9Pn0-=LJ zudKCnyNI|wnzGb2ssMqLT+-R`arOGXQvi`11GNb>x7ylwAI{d80KK09t(3#rUE&>W zuL$?`pa3cAw-}w5tUrGus6#sL(AK@tu-k6WHGGt;Z}#D@LnBV~x^}v#Jr9=g0B0OK zY9u&};{0V`(uXl*5c4I6ea)Z7wU`E8l^)|YV_X9F(1;O-&=)R>q2*P`= z?Rz}xpFIgYx)~!1495rhTn6#4y-~LO{5u+eF})1oDEMxd3-#WHFAXXZ1$ert5C)(h z9s|zKN(ggnwbEAnDI%Ju2*_H;rT(ZF2*1&Laz=D5$@<>5Yor^1ef(PIFUpz_ zaz1*08{hYJsG773nqIx);8u z=#~24nMD@;$IHomUPce4(uHxngW^7_^&KMWvm#{~^gmRXp)iyc*Mo-`!s%4s&Cz>K zH{D%q%#i%#LkBuCH(uTwK!_m6}SInvQ>OhkauE?i0|7{0AOTGT^nl zBcL5FJNEN`yj}yeHD4(h?*d6MVG4}53P^hMzZ98c;j+*%+zj{VW@Bxmu2I|JS<+}NR$}rhhBh%iA$=($^FkJbfwmqE zT@C)4*0qsi+ekHGIeXrO-7HS(K^J2MmIv?BF$Yvp~*-k`yJHGE`dnd zno-S`f>D=N!imyz^jV?Kx{)n7XPk=NU+tqW_>@>#t-lyz^4#}0L$ zN`nYcK}bX8vJoUcEJ5@+so~in#Za~;4%vnRrouPp$hOPkOC-G!zQ~nzMF-9lAOE9= zi^Zr1sy;I*T8#lxB2l%<-)W&cA%zn(15W-8&ek78RxA%bxDfsHo*s|UIT%pnK{Pf9 z50QWLbUgMD?Zc)}cB0zXDG7)7*FirxpP;HCe|5)U`c1bX-uOgjGvfQ;Ok3&rB&5l% z4&nN?#H_;4MVby*>eoB%UoH_UbnNd-c-`8ga@e(m3c7;OMDuUik8CDtz2~7DBU_By zF5>WjTjMS}F)+kGUMKm^_z<6dlkJ<&-KaxpLtci^oC<5D23sH?c_pOdHu@n5_-`mA zcn9OdeWp5WFNkAnMQ$PRI6h8qJq31ueuR5EincYp+Q>)`2}5de@^8tDK0s4;lQPTa zq~{NXPW2b?Ru@)A@E1g^0eQH3t#8~V%GRaOlCb2lw|0s)@FYi{H583g^9aauR!j`> zMzkNmPRmvQzBs$Gb7-7fh_SV~?%=3y;Xt}x%fdFVl4QB^T_8XGZPVFplYIalM0)ce z2|QU!n^4Tmclh@6@6*rF>$A%`56|Hdo(tcRHj51(Z}+P0>Fmq>6o^63rp>{H8wf4DPMOKgB?;NT{g7SCdzOIRJgd?TDy%x+^G&!eC!d(0 zq({S34h6Ollk)66A;nn>8AP^)?eU?s&`m`cCIb?m=^(MGm!livh2bvg&5*4V?aou*cpuh#;OWaiFHeYARK~C-;F(#{a-`^h@>X)46 z()=DA`$=+pxsSiPFrPqX03mF++ej3*8b8t~^{~q2?mR$Y<(<;#t_2xIqZ1`sKSpPs zv_Wg$Ed)GnV{>`Pgkp4HU-V;p8Zxq8Y->SWC3roJ-`CrHZ9!a_Fj`j9wjqY(rz+3# zvbw7N@1lfXMFu_tc$R|nHHV%cJrJ!WbMp%{Hs#ag5~!<{fQ;8yzS1#L*sS~z`cZ8S zCy?r{i^S*IS7EAKe_6`XTd;B~Wz53!^y>$cOz9svIBicig&S!9O4ewvAkSvI5MnYayS|7(c5ALc)O#soTy}Y$%v}0(%WVjHp6oy=yyS#vL_z(@51e6%*Y%N z+K(scZk@WsWTA?Xo}xC73emU-M#Fc6Z-BIoMogbItDr_OaSm@3t_!hW!XZQOCR~f) zT*4Jr=^Q-2XW}3x^h&n1h5qo8f!0N?J_O2th<+xPbLScQ?LJX9IcI^m~kDfEr z-TW-kziLgVv_gv|VSv^3AwboUTbfB1DGy<@@*0pdHOll4&o_UX+_ z+i=?rh?D`g$(al5J{^^Ip)0k+y$DBpyHP~<_zFa@(S-7K_e)6@`WucdD4ZM zpz4e4{zb(vcEkzOp}Ht`Bng^+lrP22s@IFQ<7oNOVpHb_y{@-%HS)yR@*O3IAd{i& zXlyg=PSvuxLcCJb|3qc$Vbn>mKDhE=DcNZg`uf+^U+9)aK|Ncc~ zEmQmuM@Dc&hS`iael$PpQ{vu2Ya{&f<>Zx4Mz*~<-V6K=^Y>EAZ~gPeH~eR(t{KY; zijY*Cw4Z;ouOAKc0**udq8?lB4j)_P7~|tmCd*T*27Mb=)xPgjV)dJ%B1G-GlayGb zT`eGslJlWo%U#{#L-sjaaO&a+)VXT9!<}%uv`^dKX6MO9;925}R^ai}xobwubxi7) zv}xJWa{i*LH2?b+E5j3M!w)&y0=lazmYHJ(4G4@ zB4AeSYjeo;birlbPEt8bD~Fqc){W59H46; z9Sn=v`x@yt%Qda);NHvd5($JK$3_R(V$3u{cJFb0#9q>UxSr^CO88D}p{JXtx5lJi z>equnPF&i#U^3sofZ7vY3gO>!+M`iqSfXX$cHJLlE+&UKT-p=mTe(Jo_~#j}uN@=B zT+qGDCv>k>`@MXvASaAa0B7yM`kF5sM;cvmUU0sn~iCuAB zX}a6UjYFfkA_05jk+pb%OXN)blzL*YjPltrjSDAjJ~K(S-5 zqcA6ZEDXmFiO|6TqFwJ@?pWUv?6jNJ#>RXy#Q|XR4l-YRB|I>eR{JN~m`d|&@#qVfSCDLR`-k*Z_yL$3 zFuWeLVZy)}C{FnEK2QyR$`k>;QF#}bg`q`e8pcY0V0%M#;{xs7P~M*C^1#}XAGP5| zp4eBRJUir(B0xn?2#j#cyRrhGYXz#2zI2+v?!n~E66h-60bqum7>GMqp2$?rj$c-7 zAmV`JL}5OB2n@S9koqHh(-Yd6!TXdWn=c<=Es!Us0#6CEOh{lGcsu%${iW^M<@g|Q z*@Ex7G47e+7EYF!?t&`T5fJ8FZ{He<*R=(vWt!l;GhLu6Z6jLbFcSEEC<-hLee&{Q z%6Y+!bqI(4{zvVZ2Ge1}9IJh$rl)jYVYYD;ZbbudA9mV=Y|yrto^ z^?a70aeqINwoFUos=mD5*>NweLDysN^tbRVK4v_7$*qdATvuJG3OeA*g{79#KEOlp z_KD~D*8?oF zlf)tT_3rot_&F~5J!eOztq<2($`t#tYHdZeo=R@D@@jfo16!qwbfv~2%@RQ)g!k3Q zM|J+$Ml<4t~mDfGw9#?jVlAy`g)&-Eq`;C6sPryYk#+$ zOxU5d6t1n6*wBvKG&JH^r_pw|L|a+cTFr|gC^qy_a9q2o0<(o)=s&urQw9745bSIs5J>+^^e@;bi zZL}_5(#|)VcOz(Ax&)AYeM;b7K`a_>Uua#;Y-mx6;_=hk)CJ8PzCdZPrZXMVk9D(p zc+?Q*PfY!F>JZx~gi4==4U5gAIcW2x|1OT1UlWOotv1dhLIa3wp!NYqYNP;Ct->91CH>BaWk>)8Hqe+bigvp+eW zaJkQTPGDTtZGEkP+g7vP=qOQm7qmRS0OYs0Jh`jMI zT%k}>d301>N+}AgK8}Wtxw0~Wrkl8;qoL_8tDaO%%55f&nczOvHmcz-R<735t*3pS zH7>-&)|U>CI*n(9M)_)Q;cRJc6`H(CNrl}F1(Zm;=EI&I)*c(WMiq& z!}ZGi0p|@n4GlYIJ(p$qV(VbGwFxubVPneId;uatZn?BQNoPU#Xv1sMjDfhfSC|gJbDQp&Dy7V3c;D96fEV3P~rozvw)wg`RiLt^P?pY^ljPn%op-IN> z#!C(l5A;Plb?#KD!@*$jb)gB|FX;sER$WileZFs&)EK6GU0Tb`Lr5&15A8M&kNVTE z1)R-oH!pMy-tA)9`0i8If)v^Vo)#vqK*zRl>pi$+$CQ`NSiEO5*s9VND0Qp&C3;n7 z%xF+O|Kzw*O&&g{rLA3C(Xbt2Xv17vHCpRhyNPiP4;QK)(R)jeuS)GFu@roxYfUNa zf~s(H+5Rt>Vp-n2;elmU=Qu9@s-Px!rs)=;5YDem@aW=XN~rsw{HVNll+wP4`5N{y8c9 zle#-%HJ!flHIwb8zJ~6}?$f3VCmpiKqu^fjK(Rk7ts+e(ngd?HzP6mnRcAZhf7JBx zvAMeU_pf0iyOWJ}^W$IeB3ll+crC+gcWc%o4R}d%>){;fT;F(XI^kJnXuW~PZE8;= z!u!K!k!UE4%_9m)tzZshK z+-#RM*j>yVYuIPJBb7%dHYj?Tl$xIf+`Uc7PAz^HKU!pFmH&^|+jfbxfOohZhA>GL z7(99iv}z**5ij#QWT*sH7u2p&jr$YqhUBgs>Q*!>ph9|A?uWweD9w)qWlt1gAc}Ru z@5Jn+T**&CUGz{(g*Q8+AeB*0P%T}-VXfJdWL8|(6JzEYpvtR^SQ?~Wg<-YG{3Iu~ zt|A}(VYWKmZMuE!lUV_peeP!Z=5%~|7SxG0U~1U0?qp^cs?3yLp{{Yq&RCWLc3!G| zTFOb`yVeP#B(LmPnm)rVvVG~HLFO9a4{9upL7{sjtmVKzAADHL!F<^%PIw-i0C~8p zhs^eYT^9%X;^r=wx%M_s}+=UM|~d@^mt7EtLAw7bc9WV-W>p)%fSj#4wo z^r!#-$_+{%(0($$P9l)OzClD!Bh>ssL`VUC6vRNnJziKsG0b;fYw=b$A{_ma6pS;d%4Im6)AqqZ_4op@Ydm|BiHo-GO&$KjHHb#2T~%Jrv1) z67i!VPLkZd7}ww~4aK9K6t7pRs)3}}WAb~VXtkY+n48m)_OC^G7%8+bpktWjIj<{_ zL)J(Wri+mzV)5oAK}k;rUw5l#gz;u}InV>rc`anuUdrb1^t<$F>YY)4@4FxI-z6#1 z-cQqW<@sxD#3HAv$o#S0lwrK7?gV^s0)HYD!xQ%g=}-%@VuV3C>#xe1qpcSu{3zq? z0+o|fMI=-DP?AvK=UK#)1}Q%ih>*8A_e8URb8v<~$D|n^vyomXHUiL&4gm*{tfV1a z2z~7Vb6F_|NKGILXeV?Dzg!I03sJk}Jbkdn8+&>i*HRzsl%P{kJSo#j<_Y`uDcDiX zvW3cMw%iIz_Zn#ix$vJ6A+z;&S@onewHKQh&-}O$vrRM(#xNx-*E`MB%HEKw-IFwS9sO|?bVo%?Jt&=_}Slo;=Mnm5LV{0-I| z%qrpzzo!{__pCydyqKI8@|(trRh*Ab+)uV)kv}>?c?~QzVpKD8oQJ4`SkR2LEbZeD z&AAcL)oGUWIFhW_wHJ*f6UC|A{IM6-)3_F4PJ>a-_@!J-378&Eng*Fi^k_ZV9GnuC z$ivTMb01}-oFs}RVD4Sk&aY$DwZJ54$%$|U1sp)jGqVlZ9yYxtCu-z|TZ z*;2|Zt-Z%b5gFtEU5+rUn)60ErY9^-<7ACSbuGz{UxbXH;!`T)udg#tM{?MAkH4Rv z9z=>4YJ{cN7;#1n?DFaR1wZK8jQY#z)%|wDS%_)`1;v)I}5^zC!8VO|S;Ji&i* z(Zyp+fsci7TMjv2NQ=RLThxJK>CtEh~CAmL1?<&XFl6Y(Stn;kQHoEBLpgDclejlPawF>D{n(U{A+FT43w|sQRd!QR2%D(Omtf|(vI6{S zIUJn0E^JM>z-4|@7bbm-i?sX~_JMlBzRPlrWVIe=#b?8^WZF$BuM&5+K|EpJkrhL# zUu2#a1L?L$SAbL6$@joE!O`(5-U>{q{o$qReiYYpu1gRHJ;4;T(QCKTxSbB=w`3L^ z_u&S|clgz>RaRl9DE0AlAFH0%-g|g)=e5`8y0G@V{PgxulwRw@ac_T_S&Wz=5>Tif zHsly_<1JA} zAj#N-P>mr!CT84wpD;tu#OH8uexzNIq)~l;Mr5RyPvD%m;ox1cnp^Uhmqd)#D9GBo zk;<28Fte^10-VFo_e4hg$G2qL!ulWM;-VtsEd?Ho$WP%Xu=5nb{1;$d{hE}RPa~&{ z(YUyRtVa?~!k)kVzGf*26o!a*`=wDyG4Jk!Bxya>NOSuBSREuQhC(K(a0draMmPM* z`8lXBkg!jwog?7}{=vkLbW_*`)j-Ld(^nHfd4+IEGI9n5w*N5MV~F}ZG_6RQw=;FXIIT$X;pDD2Uj_ zGfLcEgCVTb2C&;H!fV8b5v!4D;5I=N6iu+mmJspcNF-76k!Vu*egl%<7Nr_9I)5H{hQ}1n~**j}pQSq&TxK&-15CbDE5yX_|dg5lLKUl&DcCIHF9{ z!A^_lyYWwD+E5EGLJ86@-6Ey~0>Q3PoVV>iuHoQc%SDhf854tV!QKdOx9S3V4+OU` zo6ixcsU$(DF~ut5#Zx*er2p86j0e&sCC&;Kwm&gHAQCIesrgm&b_P$DX08zw{D<|o6Od1tvzY_x+fl^QCy`J`i zn}qHm2JfGAL%{ zX>pUn=thze>ouj52`UVNl({5O!C6Ew6tVF)C0d)`$kF3svm|5+G&jX9S2Ch+P*d~E zP$V22OmcguAusj-T(N3s`0zfGgq-T_ST~8$!&CH*SO(48SmAxufYcs1S>XYzp0R1c zfUojLiF;XAnpbrRh$@&bF)twt|9(1DZ+iHxAM%!%z}H#??JQe%Cs5`(XGsw3dFU74R~{L@zkxwma?O zE+hN|h2q;$VSKaEB5W^Kq6GPaxe#7=k_5g{6M-6D+2zUIe$G@^gtgm?GCde;W& zIjqe;ikv7Tx$}TkW`cR>{(e^ZBB=?HO11Drk)Ceyv^TObroAi+`imA zgvy_>(sUDrz^O-ZexRVB4hD&|-yIqXQ?AjNEKR3+!;b!r=s1mh-1rxlT2# z$-LZf^Je9$8Uo>m2G5mhvDzUzy&P`lqSfHdPaY2__~ku(rRpr!m%zerE5Oari`LXx z$5q;6zyFdb$V!}(Pg|!Jq=t!{y3&rbq#`T)GJU8x&g;A#e!auO)LU|8<;Kf(_u0sk zscZ4l%{y)MhAUeB#b)oVp+?o>B0l8&Y7r;gE8kHlQ+Swy}CJbd~U-iu@ z+Hgf;S_Xb@=(*)lZ!ha6MJgJle?7{YwZ$tP1`uU+Vs5Mc2CBb5vE5Qq9ZM2g)_y(8 zSRl}T9rX5;X@uzG#ZAw)TUO1DGKv3nZ2)2~i5{Cz%b1qvFpM8haw5Yd)EHLtL^ucv`(SX!EV}s-MnTz?IRFKHU3?RB@E887 zj~FXqqY2VBixh|ymn8E_6edWgZGjv(9nS0UGZ zDL1@bz}HL=r5WX>*qKw4^yEXhhVqOajL%HlMtP=r7F$4fek$?4-{{fh`lA6|Wiz!u z9>yHI3rg?{`oo{?57AuSD-E*NYk62&w>jBcdvDLJ{Ky#jUR{oTdN^AHUQ62_`nRWY zw|y+HddA@15tFWF6EiKG;8&bwhZ%6XD%Zh`L6^73JHj+{)~|Dx?Jfa6$_b>U;n z0*e_evX~`{nOU-!EM{hAW@cs{F*94t%*@t^nWZ;AXLsN3yZgtxZ{z+E8DD3Am6cW9 z(@B9V1~bQL+ePFsY4A!=(%hzqA6rTht=KDc7ypQ`C$s>@#>kU-6(>(qIwV!f0d}K{g=iDK*ybL{HCrx>Mh19{q~5iXH9LWKN`I zUynWKlRP#vMO_IE{^KgsSfA_MHVy(2~ z(yN!NV|^;HOvCj5XtyBxF)PZ z79oZ?Nbk3sS|B+bIy^jle@mq#cPt;Z-sIYyGTv< z+uj1C_^h#%c)3hDUe&ZUJGB36QO}b7&>o zQHwpH!Fy%Sl(ERQ=yY_2*K>twG9rmlZPJ9dZgH&5_;zN6E8{+`!DGR_u5Fw)v%}hH z{G^rL+taGgzAkGtood{YeUamSJj0ZI)ILdp(cH;&!o4NaPKFM%d5XEs$QEc%gq}Rn zaBw^7PHru&WxIjxn$F(2wUpGvdwvo(N3xp~G3$jvm)gE(;brzly>fquv7dbCo#OrN z-R14*1yO@CguJ=tYio`qzeZ2FA2>M76`d^(^$;Cfef{l>u4M6kwpMFS&gcv-PFpgb zhMUKct9rn=-m$S{6Ssc4(P$0Y%1I*}OYpe<^@^E=W8-z8o$m3^yFks#GT2Dq)J?P5 zAO?^9Yrbx_wsSGd*+Nlpt4!sJZs4*vj+y!FCS2PuH_n}rN)tB?wBtbGMcywvZ5RFM ztNI}?zs%<9+ifiKOPSxzbIbY*4-S>2XdI#`&1yQP6kO!ytDS7kP8cQkw_9eIg(uk&Ob3X2Z6m7+`J-k;mw9`7ct zb7Z70@hw-=*GlNk%wXCyuwKK8$~fk7gjQ@F*O)`AtNmD~FEFipr-fSP#o7Q*(*D-~ zQ3n#wsjFWjwAMl@=or^+XpDK>>}q%lFGg$&YHHMU&9WB;Qqvuy>NMvwIoW+C-`V7` z6H+(QD(_m5yXe!v_UN-pa=m+z=06f%zO7{ z>sE|vKc?zB;Np>brel7HzVpzU|JJ>pLCCsX6Ph6Ns^N3lCAhTxy)}3tp{9I`V%dw@p*F!rb?V%2q-D^GJSby?MH0WhpvZZB-NSpvHcD%mJ}AkN>}|WWRHNO9y9+ZoDgewM35&66WlU52%;hBYXw9)aQRmIlND#gBdT=JZM3cLB!%sTU8 zW@l!dFM1=RSR8%bW@0dW(joq#;)3|mCW425dsi~C43n8JJowcvGlyl;qJ2MJ`_@tTe`jgmD#iA96i=`Hc_mK~r%imHW$o$va-YhrZ!h&f!` z(c>Z!$jS!6pKGIpPvbY&G_;%5d9lXcT;>1ViQakMdg0#IywX3l0WFHOK582;~-e#kCLK4As>`0`v+V{Tf2GAgMBVlHup}ApAg> z=KCRHD(RsU<}ApaK=V_`s!wMNTY>clnr(@dQa7QwBpk}oQB(s9M|KZt+I!!x#g z5_hYSXUHiQ`R0q2m&0BkfW0Ns{Mjmq1rg3NFx>?qeexN%E(7d2I3F4N8Gav#aW8d24Ygx@v1-J#uRv`k>1Udx% zM!L&Ybp-j4Grd5Gy4>fF&C)~t{5((w&HyHuxkPPGm-;;9uA99?jPHk^BT_KTD<|sR z617>(7a}Ec7h3~fA1JODkLqjeDcxBw%~^IpozBSIG`kyXCf%YrO7S`)O(Ad2Exs(X zLNz}1O3dy^Mr<4)oi<&LapOxoyiAQ7)cbuXuz&8b2f4b3bIZrs)IIvj^8vZj&r(+S z)oG+k7t#YvYl&j~TY|VGTymj9OEgo+*lu11X+^?pAd&N4NG5*qFLR9>f)qUkJv#;=-Rv;*(;}=j}??&ECW}9iED2 zSv8L_1fw|^g4`H_{z8!QTWSM2aN6N9%6fZ%Hq{(BumBN^?eFU)}f9jeNf!upY;J@=ryTFxb3q&vU{HbYKDd#0>~aZ$B- z0{M}2k}`Ocu-n5eMF!z|U$--iBtOY__9wKZFHB#Xp%+;2CvD$NZMRL89A?3;g&Lu8Zqf-Z1tw0za{db~}KzV^NU$OB&fYAEH-w zVpgY~tq@yi4<|7R3AA837it~C<(E7P@(Q2CjAYqLzxnzOD7xuM>9ML@>iv5)KGyp4 z6_q~dBc+=7*Ho$s6v%@6BZUv|;P^kax4O1b9cKk$sxa-b_njWn zu5lAKeK4GQn&y;xc?KTfJubLUg28MMUu>Yfe7>-Kf5+c8W`ifoK?l0rDcF3O-~*jz z<82kF9(K0LHcg-K3v3O64_=4dbPCX&H^jDl7$3$1vH`rM>M|`KSbqL~hQOWsfNccc zZ+Y7MgzT=n2;AL=863rkO0N1s$DWdmGd8Lcsj{h=F}+Fa_w;E*s2R+S-})DrxDDAF zxU-!dWn+PR`K&s4=cK&+(0YpmtY)`yLE$+aCF!0@zlu4a&3| zuz{xy%kiyZa{4~?H9$M556fvnF4bAo+ul$WCx)mb9GSm`-I3MCi%5Hom7l5^OHGjT z5rxkfX~QYvrR zQtdV96>C782tT52JSw@sEnIR{F%Dqgs7`Vr#WT=TpoEhPBNjr9oKK&7R+b@pDeeMn zli2h#;Oup1_xSKGG{_~s#T`cPErU*l26UiLl2EBD_#{@SmQWr>tP^l5Y)GDb5CM0G zZ?A1@=bjW0(B+TK6F9DMjqm`=6HIf#e0y>`gpb8aZg+W%23j!$OwQA0huD@WEG1fR zJs+Z5$E$8auH0Uca$gon=+aLv`pO-XYe2=EV}F;B)vRC%i#g2p$2<7~Z`f^gZS5kb zdFtAGak-Rn@4WuB;q5zl?%O-Dfx~hj?O@)p71MGgI+aO{ANuIufUtuad0L;-t^5K4 z+O0fi@J~>#{TNvOHL0ABfJ$}<8uj*IXu(gQE<1#ddZQ__X?S$LHVc={uwe9{0Sp*uEA*E4`tbe{!6J~Z9DONkmQQ9z_HMvlTj5&GY#F5%ym3uBZh43wZ%69xXJhP|=W)~`Mm zN#|(iRqt>sw-1Kh|G31X+R*QJH)t0fa4&a>Mmw+B;bz##-{M|&iT1lEcadS)h>yHC z*yWZ$Ij`B}wrU>?+#Gs{MC*#Z`~sdWcY%c!U9(FMji=uaT4hw2KwV)kNuJDOAZ(KS z;X4aYeB`9TF5|L+EwpNe0DAEjdySp@ljGJ()Rb!TC64Nu1nxDTQ*q2Xg@H5lawg%u zjs{HM>;_5-oE+AU| zf*71P?ve=WpFsYC5Q{GE@}B^l4#fQle@l=jTnrU@84AN!{nxA@Pn=!`gV84svADc; z+oB9!#Ji%4T5lG=|HLfQgNX^VtHTvDU$S`oSaI0&W}5N`C_M4VKYA3IE%TO?L{l1cgDe^DjIn}LHDn`__&#F^AQ^Nt6et+GymR#Uio+sYyScsjl= zze3g5Atakgv$5!MxW-IGx5xvwaIUYa9~60^AVA}ZKFRBn7xd(RgT?cAxGZV+KcDhU z2;PDOAi=jpU7>0eNrlKna+QG^(%=W{L+#k9&b!23RAcsN)}XaC!_+dd2nnFo_$2=x zxB50tNqgj*Pr7XqHUc?9%rr$WqblQV7^yxO75b@`=qOXBBtrjJ^?;u0+QFGYi?uEg{i^`m7!TJ+QG!p00l`WoI!cs35}}m~{r;^gz^gF_9PCy^nxVR&9t%)) zIk)J9Jmiad5a|lx2`7j?ukGqC)+>9#+CL;D_9p3!ZR&BF=o)Z#x_GS(Z(NtHczrYr zeBrkI-RS(pi<9>TI&0T^Utgno#ZM83*jx&0ZOj<7nYb^g;r_Ed`cTB=q)V+;D}n&GU1Km7vl$VDLjU~bh8 z>MrPvfxZ93R)-iqf`X446Y}Gwjt3N85P!_TH8*tc7QGk-0nv&+&WGq;F-(%iFQUCD zc`FaZTqGOxQNA_plWa&j7@wBFKkR-QsACuqdg2mXCEjp^b_DeuEL{&Al|l%Y#}DVhUm(-PY@jS(^7nqGLvjvg|D!ra}sL`nU{x*C3W1RDn>cY%!P6Irz?#hJStc` zBJo4&H>{#=#es>B;0Fv|e|3y_qIZMZvqB9*ijtCBN`xvwPBt(bQ@&8=Vh3xXo8_3C zbG`7l)q>n7vIzfGT|bd+x~n3|3N-x|U2`BvOYIXlN8{HY11b6QT_B%tPQ(FmQ^X;t zQqNcj$1qPU3CE8e zzIGV9o-l2?2#UR0PbZ*nagf2yn+UQ*PMGk5eB~^lSQm4be0Mi6=8O{%S6=Fs#tq`~+O&0yJS;{BT?VUr6SQ906ad`_eq{!q_amOr~-P4KR1b!m3~JeoSpj)%X&lsmp4W{YxF68h$XfEhe83SMOa>E zOLdx>Y-7PG#8&uVA4YTunx|EfjQRA&T+p4#Q-27u0%y&{9G+Ef2iPk|7?T3o^yXZu zm*&x8Bz-HGHg}P_X>`6e!a&Uwo(yM;Z|GXL1Lvv7Z3?n!m;aqsJ!q_274NKOd+++q z5zMe&{t@2OP5xxZT=50$Ys(pr*QU%XSOOUByUCZK281x;*{@Hq2OK+dH&C7mCHN9u zOi$br&)-(?QCMbeMv&SEcfZAX<^N($^OCusm6@@IJ=Mq3$B8I@HC-W_vNFsFt;a`H zmxAm;`2Fnk?M3v#-v))A`iKG9TYp7JptfCx->eM;5OnTfx&)vmKB(!mer-%63$-3k z{i&M;s}L|5;g(+4_q~oVC_Nj^>6&S!I6TKS$R^cz#yIIB%{bi072Y!oMcKZQoaHct z;hL*vf(!p4jFIk-`uTRT8&*1WxdRfteD-W}7##{rkDgSR{vX#2^h+8-?lm^)+FL98 z)qXX~VF+U+^;J7h^B2gcPL-Nqh4o!yF6O3myH8!ApRSEBWNKF0!;N3jqipd46bK1s zzBY>71+3~IauF^F^N2s9j%|66j-jYOQeON@+x;%BF^u%4^8JH`cu(R>n7ly8=!cLs2lxwz+@M zqIL&<1a>8Nf5>3-L4jn80AsWL0}?(b=S+HT-M5vBybTP^Id4Z=aV<2AQ_hx*@=T~d z6VQzE&mdADAM;lG9Ms>tS0!plB_0YDK?)Y7{Ka}dAIzx3|I?_>*r8cQh)x{`g+|CuGc)K!+5xAZ`C zUP6|cv(!j%zWulD0ss69APrxMO7I{2jvO;xX;NfqiyX-9!Jj<#Z~I!g1{cL~|I$Y} zkRRos(!?AyC&lrg(*AriJjLG?lxtv6toWoScv&=E0CAOK&9V?KT8jUK_xOH{H}oqKn<%@*$>zVzy`)ew(jN8O3(F2w?4>W@B(-EHScn0 zo#y(3TE~Pm*Zwrkr6mD`!#URE(k=re-RJuK|1y;iYF(1W-~{RkYVOEkAOLp+H9d44 zDFihw0Fo@gxPVrdKOI`<{pF5L76THPm-D-<&{lFlxL+&Vkfo^PB~rtT=3XPvTRTdO zm{*l!8jgTkB0&AYgL%$fl1+ff0k!Y4z<5;`OtCai)_@nhCRDF8+V5qS}Q`(ZsZ zes@Wrl}|drT-cS-(7e)85KAf>^Qk_+liMMulE{#3WTMX=WFo#PQ_j4!zQ!zxymaTG&aoocCmiY5 zXbNcb@WSwkY!w(WOc2&k`MwJCq6JS?LY1o_+>&;zl{Y?d&V0e(XihO&&?#SnF85B@ z_AX6LT8fUMe(7sgNLYC7?AIhP8e-2!3r! znwWSyh=1)H2CJgxR1^${4L>I>W*@k{Eof^p2#(vFlL;mE6WqU9hn5!5nhkSbx9bJJ zHi_rd_4O<{{Q0!!7DsoHs`oamx3ai36Q-$d*9m@YqOxTj_09?XEH?&$R}zmilj|v3 zW7#)-S=A65w1PT@{gz&T^A9Xqg%3`4x=x-v3s0oz^ z!@{JCQg)=z>|bsWlUQF9mi~jCm+H`X-%J&>O&&FS{890h3eBLPF5Ig$Uq?tjHX9n`TNob&oz-Lcoxym9L3Qw(~j_;oe zBe%Ib$%eV%pXr~kuRjll+aHXj+IJpayLxYIPO>YI=5_GbvzDF<6K+uM zV3eNwnt7fpZmQ2apPXPD=;Xsv$N9D}*yKKKlyr7gbvBI*KrAl-Ix&XD$|5uXoveWK z3ZQ%03ANnjDFc&=r*%xB@@)sdr?t|i?Ew1767uajt+~CSrQg%WSNjU!v)65hoTqg{ ze_(C1Ec)Td4y zQ}P^C)h_H@HT1H&EtwQp)+T(mpLga2A5+>S0=oCo%Xl`Hp8r5HC)Z1S(h@?mFUgbh z^v-5LSI&O2P~5~WF@Q_-NRwD8F|cwh3ITCSo9YxsaQ)@-o8bT>+IgnZb6n6-J#9$v zt5cYm-);aB{SM@(;BQ|&Z#xp>8s%q{Z(mK#)WoFh=kFo@Jfwp1z=VdF+5`Co*palq z9}-m}O>S)_a++DTXx_NgW`XCbdr*m8r+Ks0S$-+sc9 zL}(rPC9H&oOz5c+iB(bG_-|^I;!;AQJpox;IP{pJCLOtr!WM~ywzyAOB11UTSa!!v z;-sk0NjWLcAlY%I5f^*7(xzkNI3N_YIpHUcxB?0)B|NMH*`&d%+-O>ofyC4xMb zIRini|Fm*VXpTfyk=wbauw^8%s@y24`dt#J_{p-366ZhNd2*99%I{E1a79D2Dr_H& zTz6qp6lQ+hG4^hf?H1_caY{dJQWzv$J>PqAUiPL>lIss#>|IB7jGkN% zN1L`AQ5SNpNMH@W(o*Um+WhXC9__lZDB)U1ZVj<-ncr?Ta$LC)YhBQ;Jd%#~Leif| zUfH(eEu%1_1x+cOIoA-@T3PN;1vyUJ#WEVP!~Tp@>QHA+ZowX?DXywcVUBI+D8E2C z(i&ImBtQ3xIxj9)Ms7wXOj8WVOsLO_J1Z`bmQYhVHFB1pv6EO45%*7E5);2yn4y$V z6BHk%C<%>olAm&eZq4@NpfFKtC|eh2Kc+bJ8aXP+P@1oFBHO2~a%xbgD2mrpmK*z{ zzq~l*nZgLI-$8zivThLzwJu%{U2aTTLRDKyf~>H-l+uu_kh(YlH-SNn!at$5^QpiM zu8_Klr({E%;J6I>s31lOEpUt#y8&om&4;b6reo9^i@aiZU$|@~db=zIa*>xnl298d z4?$rVBY#$$pp;M>B%h=(f|XDkFR-96^olwoPEb~=c@7VaRS?4uttvxsOkn^Q2r2_< zLmUgcY|@N_LSN~{n#0dD6sxD+fR>G{g*7FO8vL+;6kNgl3=R*VjZqFYGk8MZa5XX8 zQ=fL|XWHZU>-y6-PhUqC$!xxmZc~5nsVCpG`Gd#>9g_ab zzJEM&TmHAVuAzB;$*YrJtHY+#GkcG6qE~tiw!(9X8J4djY3ga z$$It&xGctcDNXyDgK-UsA6Yc}=S)Ea zLBi$FaHq=)uk&eg=c`ww99OWQ3(tze{RDZrJH|v$3md}ufV&M3ZFisx9qrHlW}Yue z+1q_oD1iW;OX8p!R+H~1Fh*oq{eZ>EZP|K?%l6Y?8gFbSQZk4-VOE+})9F*GEIdo( zZHKGxqfKEe%U3f7uUuxfcYEM+q^<-R?5-uJ<2?2)`_Fmiapz4hd~*pIrk+VJ6OEgY zmgy+WDt7LP`}0w=de0hFRhJtLXTZa4BA#oxD&C-Dn-0&z=t$C4n|x2}t5o&!O(QI0 zXWRO3Epx^^hN~Toufh&ezziLyasTO}wD&;o(8`iWdMA<8G%mbBUvipN(`D&Vr&cGU z`jR^{jpF;!)+kX`ZRw;kUS74iKMQ` z=wc=9TCM5dG2X49be2=2$37-GqKe=0V30~g+`aswj z0KfRa+T+@g*+bHx-S`6imLyXSbFf(1^rkdgl{@gRv?lJ5c^eDShmvX1R~o_>jban#x*oZ4DPk2X6Mz}xH4 zj++dsqh^?qM$o7&xDj9Gd zJku2rFlNY=y!4QBMa)fGb&Vq13{Ic%0RYJ_1- zFxkM(x0r!zd$t zKXW_tmwos2IE4xsdu4cy)G}I|OpIOms&w1bdpeBZd#uy%RmQH?ESsD=uA&FEWj2oe z#{%?b$oZsNtQVYG7^LdsZ!l9)>FwTi`-3%zO*<^BR!tfKoPMA=n$`@0o`vjEEuDAq z){fsEE1m)%^H1%nGZEk~dOq;5bwffvZ1IhwY~cSq1C8H;an&Ar7TCbJ>WsM$Y^U4v zB=~Pq;jd%`fuw3CdH)7>cnP?frUg;{gm<@2@-QExnlilxNo1Y)0 zhnxjEQLZv$&I3Hi_BaXt8&tU`e}uPx?*q*MBDliwN8%VE=s{hafqaMtfFO62D42A2 zDBEY03+Q%aZ$BojKoxyLE&s(GM;Go5pLknn>3-8GnT1yh=|L zQPt>B*{T0iV_s(kz?up;A7*sauF7GZG?89-?N*bgRSv+Q0``afY(TqE`FfO{z*cku)#Wo5z+=Bna*QS+?$nA1KAvcHEhl#Ckwz?q4}OBwgzjRA^~ z!N;n!SeK1rEr82>M4xpTsS5LoxMrrKr%g!P{+! zoIxbxUAa+KBK=0Wm!;`d$ADXGjkcM3-R&ri@zS~HG_0rkAid`*vl7Cn;&UT4{;J~X zdfKg(!w1!%Y{RGkIDLLaSqtR$VghUM!SE@B{ z66@dBZvLCZVds)dl49#UXuhA-^8xOcJFREswnvGs`vpMsBKOZ@ylqEDmvvaJ#o=QP zSIxuG)>pC5n>$_!bBL;~v$i2rSnfX>m=h)(%LObRmp`QQ)fN_)%K$yMP7sE%i|zjv-t^u1JRj)jeYABkviLsu zWB!cC9I!&YM7`TGJrVvqnG@l;gy1}yQ4kx?WEUqQJu@W!g8HfR^v0c!3ShfG(GrY&gfRHc9mS1Nq3lCXtaVC zcj4HuinkOqg2W#bGNKp}@5`)fJ!*_C>%B-xiO#f(f0S}w^A)@1%yLbc;{9Sma7csX z7zfKd@SSMoZJOk~IB(16PQA{;$w(!)Exsfc0PMzjpD0tUBMi#cl8KZ*smkqUBldFBZgG zS2{IgCD}aaC}D$4zTAEEsH5o|tk~GZyX^cf3ghiRCsiWgnEqc$1NP2>YK^yUzHt zk(-*Q18w6r>8&{~M?6jOsG1xHMbZ*f^guQmM}B1=%}$PUaMjDywQv)t<+CMcdy1 zr=XXkNrUBwm0bUMxnjpTQ(Q+i(M*=(01jY%)Kj6ATk36_Ey5YIemk>Rx~82`a>g~%*0*DZjsiT#AcCJIpdI6 zRK^qx$8IsCD+rHmw-mD=@aLxP&Sn8`Vx?Eroy{D<_;kCRJEI}^-;ttZX$zr6j(Mh; zCTjnGtG5aND9W-BROD@TmC06GdAYJH2ag%cd#;oa!~8;{LwY)z=Zm6Y!CPJZINAI|_(f>lR$T zK~UyA^ruR_IQ(~N)VCIg90dQ8{+Fp;@jtR;P`W!*zM0v4M$;5vx6Vyd02KL~ar_@J zR;+q$y5NzWY88Q@mYx-->E8#K#f0a2dGKqhQU|#+n!4Rsu3h;EDh4(P6 zzkpAZYbM0mQ@-;~S$O4DAw<=2&r$J~Z@T{Ix~}H*ueI_lxC+Qw)Ie3fKb4x+34`!Y zKeAM4z&MxC+V*<&tasddBQQU|ZdOgdw%9Sr&h3H!vgQy`X4s;Jtzy1wX6dlZAH1B# zX1&1m28v+WeVycefcF#+Hi5ch!ayeH(r)w5|K|krm3i z-eH?OK9LU)Z+Ph!QWgVE)g(`GUmj+>O#%j#P#u@2AIqCK?s2CThR2c^>-POp2~$yq zgX1wo+)pC##Z!Y%PH-)`l)LePckzvi(cjfa{@3)vH< zp-g9l90)Oy{WqzWmBQ(bzXxaj?lm6~Fb73Ez`UcS9!Obs)tAt3!yUTB?*HFmkWs2$ z+&~+MYd25XNu7c_*BlL$JgM-wrw8Kg!{3wZ-l|{1^>E%68@`&VdaK=?^%PLrZ?Y-A zF0^H6Y~L2=Z>0T>xfC~cAq_?T_b0c8TQ!4s74ey?r`^?;JZSkhL>d01mR>3*6 z?Obv?V$_DcvKzJ?;d~JC8_Jm#&}i2`#UEi?!UI!f+pJ!Pwz8)oB{+KP_swHpoE<`h z(H;hxN3#p=d+FisH#}Ck4a?@)r;h2EAMm03AZW=VSY+ID3(}a3ImWW%7OXTLx`i$A z!Oqv4u|V?P738G%#rZm+@MzuRqTm-40U_Hpr&%w-S!Zgutdl1QJo#DDW2AZ>t?Rp@U z^)Cv)J@AX9;*Y$a$hV0Ay0>I9a0x2eAHI1z-rVvz86Wpi$&2~e!AB@$rG4$76BPav zia#l-uj>JsQ`n|vTH5t!IpS9LB&sodA5PE3pDJYsx+p|HSB*DN;*~g`=kf$)veS&F zq4_7e?fO2YdY_X@VGxhu>xPL+gOgL}F0Jhv$wwN(DZ>9LuxpltcOKrRWnUu+Zrig- z#yN}Y)l6J+_;ik*F8f`8{&PP8YVeffUF(F_;*w+}XX$$sxzjw};>xqP&79Wa%CVZe zrn$9c`{`%YZy^L+p}Hp`NHV$zSp!-L7qBBs!LMvSNL=Cm56mK$IPlx9@Q>%Vb1L`> zs+kNOszt1$H%80rgmvnr@Gas-O+!F*)pf!$bs?wlAuFV18p1YVgQk!Z^w@R6T6N0n z`B?A$+lF79!`>lx#P-u~douacBV9WjB#(w?)$rIE&f)u$O22%rR8-u_aV6D zjMrIC_)c&@{bCRuwCZ?KSGVF3!NBsakBl}XEBPM1I!trl0?6ni2%TL88L;8V7Db7M zXm=v55y!a^NHJ*e%MHEe%JORCs;TE}r_>bE=(0bRAr;J|lgJu#!U0 zUyXD3KN|Mb-{141bz)0PF$?)3kCG40&yWg3N+Q`q-0^bQZ(4xDF4xA<{!CK)+XQ4>e?m`vEeWKkt=^}hDl_4kqPm{W>+-ZD?OKdH5UEOz$< z)r!^CQ;uZCKaZPy#s7BEog2R*aR^~yQ#I5p``7*7VDmG70x!V_RZfCHTaTOZ%DfZG zky_+q-Smh(L*jF@ky?g?(y9oqY&R0E;D_gsj2CYe{L7gA-bw)3%7Iy9OPXb6(TUl} zZvgGop1{s$TRS8-`;B^QQ{6ga2r{s=y(9uA-S z&Hz{0s{)#&zQdyC4R;m)O06@)+wMxPv#$4wel(lFfm%y|-#xCKcvv#-IWLr{o$pN2 zPCM>eew{aD&OZ^*pSGcWFL=!Rg=+RnxZXofvum-kVnTz)kBE?s(2vNm>&h(|ir4p} z)3XHMISU%hzY8kPcVy*Nv}}*n6)2TvbVj z^Nu9X=hw?%)2Fxi5z32nKjTas`?sk!PeM-2h^Rt@#bG59mllb6>5$o@l%Y4`xp2N$ zV#DJBtYH@xyt#g0d$6bCj;iRn3fU0=prVw_$l(4T&wljhNP$9m4NfB!-7Sbp29FIY17 zLkpaxq?;74k=f~k1k5{&N z&W&0l3sp}V>5I2e{qj+pmhLcL@+Y1cam^Vf zt~O9JPT3SXSjXMs?Z4kYy_f_7t#^8<9xlS35LUc87C~+IMibLlP$#(XM%!#-+ewoF zb(Y+LO%QvAF1&F{FV+DQ4yOA0H_*2a#C-iSc0m+llO0&8jNDL0rc4{FIn$Q;1tz-}{|OlqS)@v{jArNaM+Y){`z>J>ABuUe$p^*tkx$ zbe4MFGzo~B8aI?6RAev^=6zo{yFQ*g-`gq?xu<=StA~)6`-9HaZFp8Pi|49ql`hm+ zi|cwP6=Sm9<-os%vNeVcb&d=k^46o|tFkbjB5GOt5^6kmPw24dC8k%97w(SLD5!(n zJ(BVbe$RCj;{y9-;Z@1!Qyd%ouB^XWM#yIu@V8IxoVRA}5LNvYY-kxIjvPDZpX}x2 z*23E>$j@ADC&OK{n$TR-`P+9}N{4#G^t8$m{7{ZjQbH7LL0^k*$Wh;AUwWVF+Ozyj zUEE_Ty&*ROuP>}Ld|)oM+7TG(vF$Gi#`*_saIJohHxq$I)Jn0IJ?M`*OE#&_&zP!ncH)Hzc*UgL&>9 zuLt>PgFmz)_(=RQW6!u!$Vwx_WMPq(sHGp>ad1fhLMVA^$QDa!o$a!OQL-s@BPYisCa zdLgHW8F%ty+CIef)Z#7l=1-)>BL&s?@hwlIi*}ESh&D;9y0q2uJr=5Q;3ZB?9FR=m z)xe6eq|*3AcAe#g{A`B?Qm(dh@)?p+x>lZA#V#%}!+@Dg)e<7wePbSnIBR&f)46b& z3!hjYGP*5c%SEM?{joRsrQob(^D+ve{VXK-)9#vi3b$;y%9d1O1$SZy4Zva4e>w*s zwTSW}fS>_gwA!`$wtjcs=2sIrlAT&8a1ZUwA-A%JV)Jp=(KBf>EvE{sWr#KNYr-XHg@C2x^%=&m)Y;@W&dT>wnH_fcUu1oAaAr;LZfx7m z#@^T)Zjy~{8yoYDZQHhOn;YBC8=E)ZuWsFYt8P`FIZvPIb82ep%pcSJOt(s>CT30b zd-8Pdi>P2xJgnTTGKv0_=r<642Y4dS z2KLTpIzBu9Yp`oNDAv|>-q<8+KK|azJhV$EomYo7PxQNJtT4jgFhwP4`;<9+IB%E@ zDm*%7q2{dA|ozL^eoTMSEX3NDyTy1+l zWk>u&5;L(BOy%j**~-WdSn#O*WOcPv8|zfl0WqPV6E*e*N*XAks7`?gqO5Dj-6PIIfOyH7j zaEz0jV&IPJvSIMTg@I{Jv!ck1-*upSV<+y6f6TX^X_k3ce#t(ge#|}1XOv}Dc^B!d zyBK$bd(~M^K2^b`NcIU?PLkFh&T%B}Y4S)bm4^TE)7hpn`0TNy3$N;;siR&^$5K{V z5UtLFY}z)8fj*|x#C zuztIgq2l6A=CJc7Ejw&ROT+VDx@6%R;K;P$qThVBBBMZ}5-15EThno0%xWL1+wT!i zy*^9J{n13i6Wgw!y_xV=d%+p5)nTQL^HId`5#8MD zW*cqmIwLFc zP-Ek)>K*nr%4AA)VGn!72z`hC=HK++(hF!R*RP^gx0(T5hUOp^LyqllD}2D$QoUz< z-P-J?_IPK6`|NJ7ju3w_l84UlGPr47tM#?-2pnsmPa=2Qbm4FJxdu3ok)#S<${TLA z9^Yi>e?F({1D}_n&WC%DN+6IU1sBhMFKwHCY$m5b&<*Q_pI0%pd~H6v81_B;NNMXj zD%R$kY8dKHb%m{4s_w9nJ)P={ePBnOPK3EX==HS^`oBIrcj)VUBoBfucRWA4Lf^%F zftXU+@_O6WK0dqmS+YDY?+cnPobJ3;??Sub@UH{|pADFStz&(SH&lC5Zt#1{X1j3Y zonsDS%zudX38rHl-QJr7p2`Qeq=-~QpTiFZ^~KHzJioSS$xb)Zw(=mX7#<_^npW&g zXPGbM|8BP)2fPjY@V3^N;$9*yEmorVF+o2q`aquNXFZ(PQLeeaTc?%XggFA)=XKfi z9-oTLc(+=gzXF?0f*9zm)0i~vU=>F`58K8CB=lBGh6Ex4e)nxZzZ<+`8HM_%jp&3v z?d9v6dg+q$yS}&TA3eM7I#l)@--x|4XqQ#ES$OG%t__vzRIcgFwN;;Jo7vevVwu^M zF+s7>kw5Dn+5tBWF?^hrqpZs88Q80fhMN{zS74U#`r5EY`hTcz77?q0Z_j75aX zyP>6)_DeldxWBmCkO`(R zSch+ZwL(K_s4yxhle#^oyeNkuUoSj6E$vfYoU~|U>ZhQ}e1go61Q4+E%O~fL^5XXP z=$7h|?3Q+=RXfARG__u&074{Qut%wtxY`2hnNFmJTMzY7z!U26)Ph&EUf?oo|QX-9B?ShTAu!rkf|Ky$jc_2&H2+G=@H!>_&5&8 z^3J3eUDw;t9pRR94YlX`%LCof-$kSCNEUxY9nJgwKVkvj-@sljSK^BL1X!u6UDp>3 z{J<~)4%4Ukts2t9F>FWn9)*$&5#d!kE|XIAoutl&fp?$tnOL6f0Htu` zJvNmX?GBtlR~qX2-EzfBpK3rCKEmA})3Uvj=o4RG$-pkK3-(d2mUEzZ_hlQ!j_AU0 zgDC_6m6`!pcn9K&-Jd^Iw{=1NY*${>OZ+ZZ?(Ny|c~w@Xs~^?EN$(c!3UZHLe0rr3Bf@(=4~^!+am)nk@HI4tI@N>Am=zAofE8^EtPz??YFNC z=qQFzwfiVLK5H2!HE!E6>67&+rmr?AZv8nS4F{JAI$U zuP#1mfyyt(wpY7D4Ggt|E0gTP#?%u1l(~DH`?ObHTseT$LGpIBYzrFsp-%a5N1n zf@EEWrn1^{iJQ(pva|TIn|gB{xMwjIUDPp<&)-bKTfeJ2;mKQv#2M_Af2%X9mcdw% zh>=dfHW_0yGC~$9NhKLW$ge>sK7wWegv^L%SD=4Bf<`6y4*nL}qad+Ii{*lq%!GiD z1p|BY?G+%YMTWTm|Awssler7j<{4pY#`zp+agLawac~QNz}8-Un+0;Kkj>A*zhR>Q zNfokW21Mcms7``!^>3kNid-wS*~R1h3gkP0py`nlwhll@jd*qu+V}xf10bYI9Q!{| zCBe5`Ah#U3^bEZG_5Z>jpnm{DO2o4Z&_5r(VQ<`0FKQ8!aR*mE3W?Uomjy{FGRzsc z|Eq7V0Es!;5Y`TCEksppu&Sg89kq;tIvRB_x%1{rGA=i(6i$Mrx5=4;LaDP@^vnhu z^MZ0@coQSrAG+Cc%hvNFje=@T!8(B-=R`E&-Fd3;`F5nY%}}?^s#PV+>28Us+6Vw6 zKen4%*xK?%xH$DD-QsnRwDt#U^Fa->pusy5YoH2jy7_h!+y(S z3Z9iG-Q}9(DE|6t#?9-aRMJbahh$CxPn`grJOnv%0J&rLeZlMXLe%eux`+ED^%kjc zi)Fyn8H-@e1vxSns<{+~!syLJ&_{y0_gLqC4c7}ih0w1F4l?y`!|ByV&?kaoMg~s} z0i7HGIWhpbWA=5&=_UBj{JT^=V*zX?T>y*`2k7JkNrAqHpegIxc#VBcY?k<5&bCQ` zw|*`$&IvTstKWC#FpjgB;2`tmMl$O}1+cXhJurL*p|?>DNbCC$7Dd6=ftb(h5N5?0 zu3!P!y+XZxW1Ft+U1-%;za(${B0(^^fwWTMk9~=+=K@2M*r3-L-;_^gEWGFpZ){Eg zBbe6(S?|a$jIY3LLCm|s$|;rH^Q0O*2HIQ1lp8qP=lLvsF5cYI0@wk9p2)yly)nN) zt2b74mQ}>*Rq+^=GLvdau4p4#9wnscBU~PhgXo?pYvuP~Nlb%W zK=!|7g&5=!+V=xg-v`8v7-S3D_sOz_P4*p*0NtbI&L}dI?_2bJ;Kb#!Bfda)dj4(Q z9>@%4L1sk1K^tKA`5ziF!00oCHkcX^rba!GwEieG{39vMRH`Ev$%AFag;`m8CcxUMjEres%DHfUkCRZz)g~LpwMN%9J z`pvFWqbz-Ise+BRxQO;&lKdjP@jWutQd5thv+&11B5%c@Y~Z~UAlIxQod_UI|G~eC z7ROa0Zlx|s1NKb6;E`MTv-57I{1@!aXDn0e!fK;-^tC{mWCkLU^u_7At`div ze|z|Ff>^@^*8V=n?rY*gWS61C$rIKdU-BRouZWPdg1;^c*ixAis#5a%1L_(hQg^Iu z8I778EO2cg`Z9|w5J^oeo`}q@>}4Tn*-Fg55%YOt5ctB}?^U{qv|tM@u7USDPGxkx z4%_pgZ`Lme&q4V4-|Pv1cA$lNPyu_N1;cNAFbX85ng~nBkQOMA*~bFz-A|~9uPw>N zqyBkD=l6KUdNCBLZjd4?)`$@of)f@vlAsfeLO`=dIFO7747$g1iNr9nGxfXA$^_2% zM-7J*b9W3#q!XD$_|o^qJyuLaoCV+H(=sxxfypKYryB=GbuuX=Sf}6vegQYqpEuK= z;jMnTo4@fj0Iz$7q_I;RRWWG!{rkg)je@2PPQnB&4YsCZ;F=KJ8O!JnCS=ec4Hz!~WyI2~0WOzrX?>Id)i_bip+gUHP zA9dH!q|U)V=uVDYwjaV9VU20hDcLzP+Dl0G5|a9%J$vT{))D=U`#JQj)uN(BKhZF5 z(HSGQstaz4Esn-1gjUYv+4*x33(%Igs`n5BYV{2GVLu4B#LcvxTO0-zsL(x-6$p|j zBgU0XZsk?Z{5w8>rmp?_o9>_V7jLS6)4FyZ<2BU50+P_QE^%m2gL`cNOvZ5_+TM3*%g)4)XS?@oHA39wEArjhC+OgBgu#F|mM`ms*dn#t-zb~mz) z=;i%~m8ecoyHVS{-+W=4lNr}PF0i&DTTEMSn>z_R0$g{pR>_~40zsV zU(|GRUQK)szuom&gA(_L)V)2!2!t2ivApvn_m$k1S>yKjmDHEK{CWTJh|rU^J*j%F z^`f^TB@nPZrhCxvLeLz%J;S!5`3d6_*fmUi9MiD;g8pvN99OeLx1#mV{mHl9uXn)I zVEsw!lLY8pzI(V3`Q+Ii71+yoF@1!c*|Tc^z7u{TP3&sDs6Ik|h58J3ALLxit*E^# zeL}AH8LTjNCtMkJybyKA01u&`L0x>0Z?#=wiH|~7Nxd_P&9-lp-haMjA3KH+vbXlF z+Kb@Df0z&A*k1%HOjD0|v(w@wtymOsF_`8_8yUo=o*!ta#3*douG_CYw)UzFnE3SL>QQjv%F zgKjL@J&ZrXe|r_QYHCk$hL!D^eipZ?Yz%Lsx`w8`16Z^s4~fIw4T-iHFR>z?OZF6Q zaJK1)uq$4?Z^~Cj?*_5rjF@ktp0^}X1VhQib?mhXIPpT!_pl4{xEN&drvk~-<_Mc(`X;*b!Sck_Zj5*0kJV&#K+3RC2?6m1Z#_fk69Q?H{HyBgKRED8m zI=%W<=$A*E#FM?mY?~ zB%{Mr@+zh(rYVIbq;oB{As!TTtLUgQ^aSJSC=2ZQiB3*aI>tI)peC%&98((D>O=pmKtg6smr^5ei`D*LWuvzZyP#k&Y9y$y56j0lV7TBAW5 zmr6o9+m`(chdrc@aGgJs^;YYMqUoEXwzOC)48Y_)fsU?C-3>d}THf%U^(-I}+2*AQ zRfGhv`w^sW<#Am^v=|V?|BKHercom7@Dax|Q{6zW-VSYM)pdn!(8IHsU#Zh{rs+6* z8R-59RyU_>{-x7tA!sg0*1Qq{EHbS4NbHjFGGuB=iI4+gKEmCkb&cy%3bg3e>!EQ! zPCWA51bw7;DR>$6SlD5G2VE{&hKSw(o)s&0KBhj5NNakldSO?cRb4tmPg}NImwSmV zEv~hrcStu#Nx`nEoMLcSI9DpHOT5#(y2C@>m~TmuF`Jkja>)_=Sf0OBX+=yB{_1Tt zG1O+aXA#7TiCBPr2)b}{2icAu69lv^x+4pi9Mhd=I_1Rl^d6QBFovOZBR)o4yG=Wc zHm>33UU|iJwo3( zJ@)5^WZC(cMUR9_scFj|KL^Ek7v2^e>T*>}%cN=0qZ- z;2mdI3Gou9W6a{~MPZ|9UIHBFfpZ)FW^F@;$Kvo^@+s3Fu8R~4(h9F6>LuWLb4s01 zq}sH2Sp1EW2=@sM^JDfmSL(uu(`|svG`NJ!v?0r#SNUl%{3kO{OfjJniNSfAXeYEx znl)q{=&Jk;8)fP3V`@Q^ed^0-timy8B+$4NtFJw3N=7KvW7beteOw~a_NH;~DO7}fjT_hLOM^A47tZFK05mV+3Z zprim*f00QicGs)=G5u-p2TaZhi{vjtz50JyVNP|C3{x?mPV2$V;oQAywAzV|F~Mtl zWSBm#Ps=ZF2HAdly3V{n)K)=-&x1=+vbWoGr(ss`rQ+!>x&y3+b4Uf7WG@!F(|TK7 z*}aQ+!>0KmSxmD_2JLw1vXZL5TG7up_V53)W>KdX;E5P8toJwZ`#V^AeG&KPOCCWi zB_CQdMhSjVRsSVa+)nA2kBBO>nHHS+DFSz1a+G#AJXCIH{*$XF1&@w%@Lv0Z52Voj zfLC~nDk0*gW}_gaPI^w(lEfhlC8EHlD?wXr$vwvX)!_YEE~&kcyv3&jwf@@P%pF|?1ko?B_X-;ne9|_ z!0SItAeN_Hp1}h2i z4ZRE>zHR&J#m_7F&D@#;4|4{|58J3)>k7Caq_zh0(l^ghZe@D0nb5ZavCH~?4KZ(; z2S?8x_2;g;0!J`{-bMYai`*`*l%=I+30Nj!SH^C5bkQ*s)qF%`E@G=3yrD0oGmPnd zj}55vaxXoxv6qUIJW_Z4#^|dHQ}2`D>OobF0T*1sf+# zPL3;jJG`YgPh`NB6AqqZ0Hj%?A@;O6@T++i@#WW>zt2IDgc_=<^1&(8R4QktQnU|= zte62NF~|dUY11{qU0W_-pO3)4ry;Qw^}NY3%CXI%=}T{IQ~CNr&m%jLPr@?k`M_V- zBe9aPwL-5p-9pxvU4!T5GFyko?QAbs0WXtn$bGF%?uw%;vLhv+H1h4?RRaYZN|c5L z{>KPz?y^-5Qd-SGqxeCj#Mj|TY#MXNqGdR{dr5|;YHOqI8j++DaZmds8LuuXp49b} z$nG2T;rvPqZzEH+3k2g^QHBtD~_)wBI2j7dlOXD=ejOoS66~0mTbZfZ!%!CDuEfG& z$V=j0zRdGt?P&Y5y~z*_uVKQF`&p#0jsc=z!sD*xzu9bHY`a#ej-tWLQ)K5}BP>;~ zgf#g@+{<37L95#UKM`7Ee*2?T)NbRf3)1h>r<7{gFD@3ig>DVWW3JdeTkJw*K)BjEfS-`njV*X+#mbOJm zZdwuV_CuA7RNs42cMM+lr~ zYM8vLbfpdVE((6+FYfkK@HD-yTI}FHoqhg>6y-jIU*W9|{rc7Rb6OB6>G}ky^Cr*JX`+JN#(K)A1{ZS-GG*KP zm}Xq7HsYDIJyz|?K;2kZ-o`9}ehNk*+UVGTGA-8GSPWgVvb9~$#FFF}0)UrZ?GI#E zEtBVAwr%@%*bT#ZN&{&DN^oCqa=>@fpetJgv5Ld)8-!-rl=uCYkxc>hg7rhpWA?F%$SMEuUk0DRa z55~^Xj#vMUe{-J`&hM137B97C5zaY}lutI54F%upJ5#5xYrb^ZryRLCXc_LV<>c~B zw4_^UF)i<-rnE+Ix7a@wyoL**?w!;g!_zvZTywv;=`*A?5Q zO2lJ(w-Z8h0zPCYME1+|LJEXsDjC#~-_nr&yx(GPy~^Hymj>px%VB0SGHsQ=u6ld` z24#5m)hxfPQr7o0aDbMg-G^SfhLgX%bdc|LVmKnl*|Lx`k9zd5a=TwSJX^#W7?8cU z9kyuMv(}9m(HI0P>iz9Dq+Vt90r%HzN9~z#+xdr3(sKq1fA_qY9;S>37aM2!-?*_U z%?efQGz)GX*oqOOOBxJ)dvXkt)2(a=uQ*zmruXxiDis3E(^gaD9nojfo+1E;G4m|#}@y%e2 zfZGCEAUd1MXGgFg=O^poPG_xQd-^pH;j50H`QHdYn(|qr_!)mbz6a<_u&(iTHFRaJ zyfgU&U__&C4>xh=vFSRD-TSvs&)-mAN-(wHyy>2|9h2zg4m#xS`}*F2sbZ{OC+>;Z z_;`Z7L3KqVQ7)KF-*4o9cYXl{s5@`JdhKco06jQ5L_sImM_^xSdffzSK26#etDdiR zX~-Ch%OWf~ABIn>R|S^c3jd_0Eb!6_m-2*vroR3|N&oX0SBl$ZQ|7|!DA^0nntZ&V%2QbiTDRlXh zZD{)kZ?^y=|95$BQ<+3=haCGX0qMP&TWI&mR-Nov_hEWK_~7i zHMymur33d02n1Rs-#tDdaiDjKbc#%tZy9XunzHX*m__O*@Fe)MNcO|j>(eSAM2ZpF zENs)e8yFgl_YPX1*E}tb?{gCE9_pk0RU@*X>s6k&JE2t&OT~Mxf&g@}%3zm+DTS2x zYX_?@mh!5EoQA2hmohE}Ds11d`z!xmz+wHFhZS2++4PGjMP4G%=@+B!nG`_YR__d2 z<8@%rh!IKX#gZd=#F`-ZHY7kvIp3ZcE2<=n+5qiOFvapej02V=+aQX0a~|VocvBml z>vRq355`o8$)i zx~Zm4#4?WUIiJxb$RLE8poB#EF89oluV3W2PBb6j#oP@3r$RBkPK6Q%!Lvrpgyt+V zR34ehel^b@$V2a7 zmdFaR2v?;V$KwnX_N9g!uo$x<-^q)avSm=*u`&(Ss_$eWcG5|ksPhe+7##Wnz6FPg z-j9+*071nh31=9wVv<(LSv5!{FTIksLaIrfT{X(G;jEI!*@Rsk@od<#K7Aoz(Xfd+ zZqc-Xlbn0sjxsAG6;PZ+}Y@Q%K2rg8;U#tNNJ_N3B+us^} za+0wmYrZ`>eRLEbGI*ijidE-W1Go+%*24OAl7XC6Aoa)h|8zKQ*q~sGCoQtZZH@F# zppSL#hxDqV$hORfk6eb`!c4Da&EiIy2Pz2w?uFHRrlWN<)`5@q5Us z0bXx(E&0z-LK6uK65iqHIenK*LW$>?3yHuSeJYes^f%aDDwdG92Biy(2h*Nfy;7zL zBlm@nk8$rJ?~9+jQPk zmJwue4CRieSgM6pp35|sEgnB=I&xNC|MrBzeEm6^N(^lRs-79jvX#sg9oZaxZ)UTq z12-;Nukx`ho5)3~T$EuebX;5cMdiXVQz9mIuP8m@DC5Og-4|#jQw%UKLP|a$YsC;y zz;}qLp%ndj5@2tjBl=)&;00Bb=qQ~P=qMLQq}(w#>I~_f(e?+q!j(#XDk!lC%lP`_ zr^0+uu!QkM_`;BcR17VS0`XXa&O*!fJOZ~#Y<(%p_QY?)GY0=qf5`2b4z{UmglCq7 zS&Y7L*yCq!G1`XkxrX9OI+vt|DK`x2j5;<;ioA0hGA^R{VETwm-wpCD0J>9SO5g{< zBpq5>@kyUTJ!6l5)uC{2&|QilJ%vHXa_AH)>D=VHq3j}ug-C{m3=Jsj8iyh*IK`<4 zHpYZX#NHL`DGa*H@C7$Y527VL2fBe-u!;TXPYEwUaZFPWCdkI3i@T$}0W<8T))nQg z!KzS*VBf=(d?;6sNw-D8R~X0N`x9u5WtZooHOMRZQ0;~ceD8h+dGVocPLT7Wbs!nT z-m@CLj(W!WXi~b!zcg%F5#b-wt;1%$K!=v^2-ripeV6qLA?U{5CJ)h$i+J}z5zHMN z*kj%!K$Vb(b3{48qiC z;9*>ykAZwb9vqiyzqE~>Zi39TQ^vO^zY@lWQUh16Vw5(KqGH@~K~yzmu`I2U)N0Sd zMgyOFA@CzP(;xk24k#wI@#Imq3&W`k*y!h63-ZcC!#nE5=@9oK0+bl{LJN z=PIf_&zS6j@D1(r+jw{Aw%nu0s601@eRb>rs=%-4+~8X&ZoHSsxP5szb!>L1^Yp-f ziyHqB51bunvvrx2NROj#O`q-Je1xBY4p`quN2Z0R9S^-MnXpHL%o98h!9x=miA6P# z$3n^qCS$*HNgd(_@u-O7VuYuM99SIOv<0G{r4P^szYi?>m87wv?@AvkTGHes$|=GR zy`$7?8$u?|jGB=Qz_o#KS0>V-`Xp&X;%2AJ3;=|?g|u&em6y7aZm1p5{nbmViKkf} zbH*s(B6C(Dh#U7Ox6Ow;gJ2y5RVpkGr%_}W!YIq;@k6*AxmBVqm?kAJo+cHUWI9+@ z*77Fr5gV0lODNo+bWLD*8s#5#tl0?Rf<6!~)l~jdZVoFgpHIn9*?`5!T7^RwJgz}BA=0#9 zVK!K$PM2({Wm3r+if%R(2jR#du~>Dh>Rwo7ts?G*3Ew$WZmS}J#9qlW$~{*elZsds zjA6uHj~9pN;t8A7q^Sjr^^us6z^r6cx}k<$e=~C9Z2p+^wL9R;La(kqlP_^5{$;?UNa$T{mLHe?)`BdHon=ib zXOqfg1`o|qR4gZubJw<+lN{n5-=eQ44(lDC@tLy;?92Ag?=249N^|{PU};@T*OQ{< z4sZwP8ymePyD+`Jx}LV?3D70hIRowie`R4PNn~zqZH3N{tcRp~zInWn+4$J`SRN7X z5c9E|oO$~Wk zFlJY_xrt2;y_qv^$vNJDrbnnPYIg=7?WI^T+L|*G)x5a!?a?0b6KwG4Hk|3Et58{~ z>L@gvd8ezWEmpP%oBm^GPpAeb;*UXN_q45Eb%dYFUN?W-kZLe)OuG0&?qv!+0Xt0`l<#see1j0vzd+sDB&!&Q^rDzY+B76NZ%dyuqbqpb--L z3t{rjF;#RtkMPdabtZn^v1pzlN*Wzf)(>|^hFJx2ZfHg~5J*vogPxcZf zcv)ly`Mc-(N`#02L86V#iZ)M;sm-qRj+Dj!QMjiz>C7*)bK5-arZ(R!FSqm@pJ>xN z)Sz8!z`L_Y(G+ZTk|BKd!8m66jxtD(k18QGDk)O|8cTSSTi~YKP-|jZOIVc6MufXp z5Y<~j%Z*j-O$#N8|5#EjR@Dqb6{OsaZ@JL@p5wTTU4?E)i7!OCP|g;*MNQ z7YSb?2)3HqmHO6Z(+4E0xDl4q2a+@$aq`$h;xrvwe_0_7G#>p8`Zlwe+J*b>->>6K z=DFq~k|1>FiwWuBV?y=;lk@FCtAX$_(M_|w!|R0lt(&nNydKLLxE|k9INr&2h2Tm- z{JY?pLIBp*7h3Xq%!_qHIUCLuDhKq*+glKEFXmRF3{-DCMG;MJI3+Hp=76q@NN-@d zce9ss=k)yDnQ!W7bwM->7v7b38;LXIcowBQ=PKljL{K#9g~mG^3a_=an+G`=507X7 ze3`@A(m0W2d{)1pQz82dZ!yyHZw3D1O=GtL@eMv6BC5ox*nZ@+xLLW)B(tf!+&&{Y z;-&V!ZR`1GOqU&K&8gIz&lAs^!y`|esHmuId}wGWOjs*rT(L#Esk}-~dHIo2fu(X( zdA>M+7Q2o2_+p}M31`Y_p;Tdi0;iySxPZDmuDqNUPrwMFTwEpLt3y@3N_X}#NNk&erGcnAqjCh!B2o#4nbcF_~4*ks3o|&waKvaGeX9m@gC7bF< zxY~^>zl;~<&t{N$IS5NqXzH0jZ5TPKhQ<)|5OiJ^mnuO74RRQ=a4Z*69hO+-1NAUf zcmne$&R#XipiTm*vKPUe8cu$Vp1xN(7vjDg85+D81qWf=787cW*k3-?-WzqS5hKDu z_dPHAoV@y<(c>P!MG8r|;LUL8QwwT@PHj(ZBiRsCM^V*C$f`YAg7PZCPC-vWPpG5f zhK0! z{Fs_LwIFwz0P@fg17q?=4pc&bko$Hlr86E|`tG+t=R~ZWS+v(J_Yv$73{|R8s(!TA z&I%lB$aBixeER_d=Vv`JGHZhIZhP7(b#QMUanyUpN68s=~^p8n&xmggio< z7OLV;s%0A!N(o&j#kB>bcOBMngD_0mBB&^ItVA2BlhTV;+2c|@jZ&v1nz#rLr3@xd z#)wvb{W};xhAK@Qt?s~O_&eoo6u`_hz~D~MB0BM5d|(-^%gXK1CPGAyEIv-p4KF>N z+;9^XJnBmFCp$9)XGiu$cG5G&3%eL&JP3z1GojC3mT`o8j^KFEAv2-hUY1~lo5rC| zJJLSb#lyaFKBFMZNt8E+JUNw2uFt{SZ?puNEC)ArnpqCYFk8=H{fPYbG-mX;huI{r z6U8E10wd9nx)ef7g*K&6zl{KOjwCv?9tCyLux5#raeTLxI%PkflmHvkQ9E(MUV&&t z?34i8#9sSn;C?ETJMjV zxMh+b?ke7x%F#jo2M@O%2)JPO&W$>ntWAo#6f4SmC1d zjnFhtaQ7)6((SJZbhP5P1L8vna5Rx>-ol9iunXIt0*)>-j zc|X=M7ZMBad)?~e5kRHnim-=0>AG05gJH&pQ8C0IRD8edW34$}Ech9f$VX>g9<7`b zMQ3>r*C}z0$i|J6kCUfHkd`752yYIcDnDaFJmBn6;*UtjjiZmF|YzOaJHh2)s%axTd9}=Gl#@<$XU@2h9 zCX=K|Df_>bN~uVeWSLW)2zSgf;tc=e>dcVw+}p%hgWm^O=pi^-Fb>Xpr6Y$m`eF&W zdLVZ}Ulxfq!pvWlJc)pS?&Fy>Q!yJ%9QU}~WTG{dO_)=;5`Nx^>R2}<||nDc)y9Ly~`u@`^EeJ8?@ zyPv_a&8-o}+7#s^HS`MT26g>M=mcHNIrjr0=3jyOk-Z0j!zru>Sn%vu-WRw#0j{Z| zF^<(lt%(r9h+hB~(&Qcta|C&>dNjyB7ubafT|K73yICm6JU7_n4oq#2%{MiC_^M?S zxs3oC%aI_}4BrMHajqHK8riTq#0FV}SgWoIr+(FYIhNor=?)l0gH8=;UDkrEzbHwZ zh4t0>iOtO)W{|o5FF(2SG7i1A_05oWo8|DDB72{VnhTDu!lv$r(~6EidMV!3&U#j3 zz{Sm1d#f?TFn-PL!>`{09#h9uS)N@Di+k23Sk1$`Q`7Y7p42{<>s9>sE+132 z%kXDbMf5$e=}H^$Nr0MXgJvQ#&*V)n*p{!CTbddVo0fDz6TtR|1px0e#bx5<6-g(R zH4R8RAhF-9)q7~Nh*)OxsjbEzouYRY^6y7NRbExlyWK7@(&fB$$)35MJ>&3eEz60h zy{5UWX+({0?DXlSdqY$1dhV_IW8CiKj=15m=I}!`<|yMeFn{>vDtoo_mpQ3U3%SwcC(V_+sP?VptQYR)%p-wPIhO4Oe5sg^_)AUA)h0AMg@CQ_ z=&!gY2>dIh?ZFNkx{jXdKZ1>qHPP2G+*_OqPu1rP__wzYJ>k_uE_ax}1RW+cQ?zG@ z`HC*q&3!JA1r$(kZ`j?<`8Ur#%AK@#I~`mBi}iTEt8ouFm>~;PX+=H@}qc0RTZgCzvGA zcAAB+X?seaoGgC*V5KJ)UY>f(7x@spAcZ2bZ@ ze?sdhBsoH`RF{!*a;@>>gY-PVJMUgA{R6N*t-L+Sz6`W+!QTgDiEn+(tJhtXW;{Kr z;0L@uLf@Pt7Hx~>=xL$*m71-7c)3wQc#cl|` zJDNzGXRI`wh9AEF^KJpo%|TXcoN2w^ze}BN*Y53=yl%8Jb`<^dAu}GE==Phb+55uZ z)_9j>*IjRU_uT%8;RAf?u(?9Ftys$N&UrQ2L~z$j68lVU`aEZoZ>_JncJ0Y)+XbAJ zo^O|IiLNhu2~M>f=>Rfb)>=t1*0-+zoR_j>MGd=F*AA!MI&PftxzatCJ(MjyX(l&z zQJFu~>gkd7V+CWrH3>ZYVe_l7*zV-1IUIi4Xt{2i2D^Ip?s70ui@ws%^MrTyvFPz> z*LatEe<^N&^SqJ^dQtQ~%*WZ;Q>XOeP zNfA`2ePgV+(zd2g2|lKuOObOR!pjR?ww{rwHmgf!zHgRy3#Y_ma=l#ZmyS=EU47fv=O{u)ymt5wZC49~2ZaA1+>Hg@k>N&#Z$UBQk;f$DMWf>jm?JYu zd;)e4esV*Tw{b3lA2{A}N0RErs=CEyH6re}nk^1sRSZGxGXUxRnEU>1p@E?@%7>R@W01rbtA|%%ztxOcwKS7&mS@l zSi4-ZPAWvxA?^8VHgn0f6rMop<0;a&fG#Jd_c(cks`eAnOs{Xxl~^Hr`%>{*Uh zo{UeH5|8BFKdYXe@0)H^c#XhoqTv?pQbO~KW~vZ8h}NaPUVcPY6-(wD?3hx~!Fzv$ z+QjHQWY~#Qx7W~KIaMsx*;S|JS(LvNJ4U;57d>tLdSIGhnt{u!K8`_CqbXMo-4q)+ z(Xr|WvT=@P8Fqxb8#IoW%G|Ds2h#{LS0Q|~WHCsC9Rbz$mQcqF*_ldg+$E34nQJkQ zmQW67+cT`(|u^i`gF%T7}I@lPy6VjHL)=a zqa$BIKjGstl(;xc9Bh&HHa4;y9igYEvSKq*^66P(dZvwW9bAYnpHjqiML(mBkH?Hg zy+C-$QhFkHr4AlsGnWInYFf<9CX6h6#G|i9xx0~%pK+#d>NezgJDFj6VZ(Mg{7Ti>hG{NyFaI9x1Q#l%32c|DJhaY z@rDx;sHyl@!tT{?1xIluNzBGHtOvLgGbtFkyIKz*@(;ZH(({8FbED10Xu^*aG5U+B z5sF6PI4+BDdb=>iK5pZ1iKPIPqwY&G3x z3TiPuz(KN&z%-ZO6VyXTT6_r9S!=9Y%}1pJ0%{AU{JbjSL4g257gFn44$7WxdjD9L3P+jVs#@vMc(jf^dZ$8#pGhZV=vcT>#4MoIo!QIRhI|^ zQ0`5HnotPZHwvi`oD{`*ULPh;<0pK+1;^CTGvPf_;beik+Y_S)HpJiU%)gfz^BGuk zd2X%{gnqk#dx1g;hG6@nlKF_}B4lCav-+FVPZ$8igjb@hKl3XNfFS<_g9nnvN7%=Y zQm#mecYQl2$C z4Q3!zE0PxD^y4Y+atKh!))wRBb4ku0`zDFJBk(Vv_5V}LN?-n$V$8!c4fCbbdl#UC>Z-asoXTASsv}DdtgJGe643igZf+V_)HldGp)k z@}lPCGAALY0IOR!K#o+Y`t+vk05-D4;*M&}DYE7CzC^x6t5sHxWG3EhE?K)~K8GB> zJAV~@l&l`cBGvm!_Gi8@&eJy1L3$Ve@&&NX^s1NLlXdxmUy{E}Vq(zA1LWx(iNtCY zuh4jF({H1r1AKXZ?4YK!kGu^k<_M23=t5|d@V85xjyZ!%0zZzK2VeRHr6_ zeHQH)*IkcJs^$H-0}yWCNuRLIu-|{vB0L)MNEwp7)wCagX>R;#T;s>fwb zsDj^;p5)(pYC3&}peU$Ak_J-GOC2xof(}P1gvym>NaQ# zH8#K9*&6&yhbVS{xmU8`^QxW!t_Ccfwx-d&C9=2lrsw|!jzDq0j9ZJ;uUHEUw-yO% zfjR+1?#)QJHzVP8B8>Yqc2GB{8&Fd-+t7jAh92CrF+hC-Ed=GZA&h%D2CBQ%U6{fw zM0ai#!q6&wfO(l!Naj|7avRWt`#=V&r`6MVmw7^V;GU3y>N)is+J+121q_)bNI@HL z3FDX15=5XSXoX1bEg8*iKn%A5J<$fp7+25|bmH1Sg|?&ZkTQ@4LT4I8gE8J7?LjB* zR~f}^KnjhfF__MLETg!OWi+=0U1%arM9S`H2_m@-=*hh9t0R7_`fB8mHdwxdter!j?jfd+Fg&=Bqg+K$bdp?$#dfa4f4PsnKQ2^q~j zA%nRmWN^Ezc3BYFF1uYe1c4xK5x0W?0T99#NNFY+Vz46{uZ-IBB zccHh&v(3B4yV2X^J@0Muh4>PDY2G8gQNFRBW?!*yD&{dUPb20T>7C-8=XHCR;`gBU zL>r}dqvwG4yl=jHlzXhJ-d*gT*<*DN_r!V< z4X-C3pMI>7g-<-uwZ^s5GZU}5#&FL9*9o)AQ|jLD8Eqc+M0onT)?gpxV9l#}-Fcpi z{zT6<{{Vl!e*)HA&{nT!9o8G}--Y!C_#6F){muSU{&U_fUiS;)3)CO$Ux5?}tiSv- z{R{l7k!rKI$-fQDCRjq2dC`|RGpmec=0(>O9G9)edUKso zXY4h+hK|4Io8xd)`kJN2B=a!-K4UC02jD2JHjW`>vyo|@b4_;*HD((-jmxfb&kE0K z-)zq|&j!x{&tXrqSH!-jIF1?KLEc&3>0YO|fsf*8ANXQ$gji3e`G)%neUq@a!@N@5i$L`tejrV1Gb3MzkkE%Q^-f~}nFB~~wk*~s6 z=hMAIeaTo`z4sE1(ok;==Gx{>@{Ymw)fu{R%nUVS&C#4MSGZ+td%P>xHOMv6SnKw> zm$_HD*CGcjGS|6ZVqf=q#I?GdG*N+#x8pjjmwVcy}`L!E}6z87{Zsb!~BNH*;JkTv4tt(`s5>H7=(y%C*#0 z?^=nH&|v6hitC{3i0icLyz7$dk}=ktX-+fenx*bcMcS13<&(1ue}Ane~rL*t|5HYtp#eq3nJ9RZ&Azr z9q>zzS(prW z3sZ%uP$HH>WCaAN5N6Kx7-_!@zqiv^L0|qa+aI}$K_o4E;uRQEf>KVd6+y5&da58DSRp~ zmtTYn@=Nj_xX4!S2ytxXju6jQ3q2xktH27@|y6o)B`CCzU6KBIPM%rtmZ68RZ#am@-G1D-2iW zDGP)V%JWLO@E^(>$`;`vWvlX*@UXI5*(3a1*{kdo9#a~XMq#q@uJVEKIL;NDh3VEB zYmM-X^{n-*Fk1~%!-P5NSaqy07w1lwglE;u)G91uNLW~cv!D>cf#^3(a3T5)7u+<8 zMhPCA?ZgURhIj=ZV%?sCpQh3g!mn|r@qn-eQRrAJO4(%e3W?ezsg&F3GXw*$T)I zw!VYp+lJZhBX`;Ew>?0LY!BMTk$Y|9ZR5%Pwqo0Vl2JG_$wpol$Vfz5Y)%pn51 z^{>!LpRHHuy8aS|?C*uzF$U2qj8G$`#;<#g3HU8FOv7)iHZ~jEj9o@!osM}HAuZ;p z%c{#VtVSryp>IN3(^!s_1Mv4;;~Xp7KGL{|bXc;!sdfzJna@f#!*nm!G(q2K_{}6U z!`NjGGIRCWMvEz$)QmDy%>v#s%x})pE6jQNRxIIyxztF(zioMS%)7@th;0frPnhS; zOD=H9cm?1$9P@27hZ-h(9&;(?+=x`$^-acRY~^Zvo_xHD^g3+mDSesl#Wt?eSLy4G z5%?Sx`Z4_^_QM6d+ZX#`lQG(uX4s9xti5<`z!Dmb1NvTlztOC()z@Nwg&H|V4)%(d z{njt*myMbFR;*)O9qXytSZjo_LO+8guG8mZ7-%dos*Fbcf)Q&Z8k3DuRvXeT(+?p% zD=~+cvq{&@k>*fyjG2V}5O0n*gUyNN6zuQW_*A)9!VAVJa}DdSww^MbW{v4)J!Z@_ zS7HebMx)t;y}Si`>a&_;7KY&!5BI_d=n4JC%zN`jeq^?(Ji5R!$J!b<2x zqDX&8B?HMIC?Z)T3x<+fVxXpXkyWV0SCdy^Dp^O?!F19<8sL|R`2PYk$ZKRXJT1zi z40FUlF%ahR)yB_?bHrz1o-|mR0MAL&q-pS5>6g+k;U#IN^fdfVdPbT9FZ11yR!NJc zN_d6udbCDzNH4&v(pqUPY?4k$XW@1EZTW53A-^NP13Tq?@;-P=J|UlgUGm@Lzrk+h zRiy#;D1TO7hbE3_Kd{DHW8skXLF)?pGO5FxW)$QtTXi@j7 zdj(N#R2v0J-LLK!Wc8qWP*B)=MZv0mtezFrc7xju7Q#^C3&?OT@nJX;usDQ$g-%*d z&3bKg4QLBAzqUeKS2@EGr5(_kwH95}lk@`oj&ZDUH0bd)TlMMsEPY<}QY}Zz*G6j- zv;|dWhwltix>q$nko~lp8TB9n5>+#wMtYf}5 zjz7)hsz9w&PtvMbPgF%{yI6axXYqa*qz~1{>*cJyj)s~U`V@U3K9h;pa&4M6Q#)6= zU#EJowi@%Z-`lj!6%ASy){%>J3-GB&*IdB7YqTP)HAh?Eh|)(^m+SMiby&jkstA3I zwn00LwBxkpm7vYlF6v?0+$w_Qjppqer#ESSJ*ncnzNKQR0ad4Tr@m4@t-JL#`g!fJ zu}Pm*nNYLV2+^wadLvDbGBULdI8&W!OkzEy&(r7Otg)gxw{m#ZIem-1rE&(M&@5w= zF&ulZP|L@fOg*VGp)#TR687mP#5dtajJ6Hikz*{^=XM<$tX#%M-1$ znJf!y;BlOc7ySGCfBQ?ul=Ll|VK29@aeyPFB*&4w*jcvIQS6vu-&1nf@sj;g$pCwO zNniUcPSv#7=?F(EU=)to_C1b}#ctI_0l%VYT4PWZLBy`mboO<-cYv4 znYh?la;~hnB*&RjGJ3Jo+1ELsWQAjE*$ih6t6xv6T<2`jLCdWU&_-64E_Sop^-RrK z9gZys)0*_G#Rs+X70dLzlD>6W&WO@rd%1H$ZBoq!=ghLSC8V^xBxgyeBNU?7F@BD&HpOA z*ay5`XCu~&^E2(dzO2%Uv!YG<*2+_uf^)FyaJ^V-ayH`gVt?rsn5Ri!rZs6!eQimO zeGir(J7#E2C4IGWcG;Wk3(E)8?R6w$kEc4OI%cqOv9Gk(JJ#Es_BA*rYw>rvBLqk8 zyd$%0hNBpNZ?Tt`9$f5PG8(D3J0_L%#k=*6W#uc%ca^PmY;|sP?$Se?hn)v-EKXG> zYNF;wKoGB`Y8l#iZA`^6Z6P1UdaXgr&}G(>cpbqs9L0(lElLk?UUZ()YH;M8&U4z( z%4u4#R_<)n!P$cS)2Piu`azYk+Clu)qD|MfXxlMwxE`Y?=*jrhd$f6r&ueQc*J-(x zrI_ommQ;~kz5<`giETb;KjH{rd|9>=`+i3GJvPFyCTCSewoK{xsoaxwWU&FY- zInz0}?hKCWf+eBl_BI~iTu|kRDJyi2!)qoR_tJ7l%o1Xsg{`YcUW~x}myl|*b27W@ zIO#04JIm7a8Pzd*h(4-fE#nI0iTRby`Xa2A&6K^2E3`{^o!4Kgv})V+ot395PiZ3= z?_huAR$42(&JB7N_O26oYb;94dE|{ldLdqQcs~X6Q@x^W#$u;^I!a}Y-C3Jdn`B?g zM!GJ`z7(bM5cV3A=M|32j!llScx5>X9i#Afv13&AR>!LHP~;B0N>*SFw_|^4x&4yk zjHAM_sQP5}$uh5Fr+r?Tw=Sz@Tj@N5<3jBv`}n#T3IVp#BmQ+hB1X`LbO%P<+Z`lvQmIIap(B5*;au7l+hb)JngXOU0Foar;SdKtP z%Q4F_2(vU>nxT{E5j_wt`a~ae7GDrwfC%x|;;$i6{Ehe7%AV=yc^@Jf(FR2&gO1-7taEH`K>H~RFx|9xgO8umMkS`682EbiPg;D_p zN|jOtcPlkY4HPPMN*&yz*cAs9DVn0eP{mMi-lVt`7YtWCiU;mhe2Nc7C@(0>;Xb8a z`2#!<@Mgf9@Myq}fE_R~;H`kS;O7Cm19rotfVTtQhQ|Wl33vx4|NH&lzu*7;`~Bbl zAMgL#PcJnR#$B(ji_p@YR34v zMO&&amM2%WREy<{=BHNWmu#vspAW@5%by>CRNEG9!IZ|b^6Iei@am)zM4UB;sz)w7 zQ$2ohPHk-MfVpPvwA!j#vwT_Yw%X>}bG0pXVqI9xs_G=XMpoxm=hlWU&Z(Y))Hz5y zZsD@(+`0DZ^6HVbX36kclU;M|Wf@CCSZql`b;h#?mxL_It2Gx-dv?p>Q%ee$3|~CD z>_lBt`K0QCvZ3?-AA8>))kb%oIWq`>6@QcvAD0kHT$gejKFU&;LntAX5I#a&LNK9N z$OL1oU&dHSBh{AXx1`a`NJv6Z*JT|JbqRG{>JaL>lo0ATEF}(c2&II2S>jUS5SCDv zQtDE|diTBeOPZeUIX(N&?m694?it}bbMM?A@AKYy-p7|wIh4xj9bnh^H|%VzrY|Fw z&U>O2Xk_eKumQ%xkGuDpO7nKy4b7OezZb98Jm|+vh)0# z*rCeBv~YF8%=Cu~5}nKdzZxBaem>yGwH*fs8U?|}S(o$a$KS>fisu0HzR{-LB4Xax5p*bvW$-u1uRH{}FB z8n?<@N(Y?pg2h)r76Ua9}tT2~Wr8 z5|e@9L|e2!G0O~aa<4M{t^(>l^GF=KI+-ttnOs_&ETZKV{d#I}BhXB*!YF4bgL4k)Tsfgq{dn z(N<*wN_haCil9SQi=zAj-ydv<8IaACYMw#JRN#{tiFQQo7{fEs8K?uf=n$lJnA1eG z0%mCh@EnEf2Y~$@O^)_QMLN)aEYnfV3C?d2a4Dti+dF-)rPAiFJ!~Fp1+HmX! zpvxF*gSjkHs^hQ2r?lg}1BqLFTC^cnqa9BihL-w@nEuf7zTPlFOzL?3mq8_;@* zy4BYdn(L+F+sLeG?Qv9&l6YzSBLsW6h&#GUwHBEXFWcF_Uea5r%yo{@0I zGvhhzTBx2+Lr0$#)`KoBzpuT|3w^EtobM+(0cpj^6HxBQz5rI);YR`WRdCd6`C5Lw zorSCMT4b?!d9*t2RT#i~UR;RF@!WV3@|L(M>In?@p6GQX?uDn37sM0caekcNiEqcZ zVWlv|$`TLax8q}A!Dq~XawJWkBBy6`4H1m0SM4o$##&k2FYs*m|BbxYj} zN8^I}K-&#YYt}w%pUkc)%Ym`JXUb4tqVG1p+IOGn7tX}*Yqi`nxc`&*TzoF-iPdQt ziR@TB))+30Ib&S!S!E$nnK&K0qjd>2y+gety`#|QiQa?o06!F8irwWhV)x=xvDv^d z?|{06y;-p4#37+8#j)bvncitwIoo2Bv4`;^O_1B-kAi8T+kxR=8jN_ZH%+VON)pA1 zvQTZ}Om74Cy0^KvgO`{AW&l=$nnWEF<)(TUdY5AX-jird82P+tG(^KHAaHVEILsv4 zdRL*hXJ9V!daHYx=((t)cf5Bq{xZHByTz3R61|>qb?y!l z*C#iT7n7TlJID^Cu9DqIS0$ZDS0!nrtCGKtz9oXZk^CFUcgUN`L&?8Qibz)_{mEO& z+hiblC;4y4Q1ag<|0Agai+w{T^n{)we-k>WCkOPY`s3v15Q`=6A{I;j4ti54IgD5= z`FZ_W{aJDZz1x%gUGzRr@}9n0{|@>4=-Z#jKhW3d&y!!!e@6cq@{jZv^cToSdb8e4 z{xRaUo|bx5?+2<9-jlg`eC6 zcDqAvVP5+K^oD(M2N>;JJy0RQniTbQlCUxGj$GW&D5_Vt(mGj z_Qhj=NPPp$7YYsQ5Vr(cB<{zH;;Xjx^(PY$G%0i zBUPHZj8ti=1F6!~6{Jd2=40PKwoO@%?Ht>st^%w62g-r=B2qNkk50MKPIT%fdTl)A zH6$5yln?Dcq*z0$!9a0__Zi+tiHLJk65`yHA8~FffH*f5G`wvnq+~;pp_tOpU$;;( zv`dicGknxgMfIbdfz*KE6NXyqKchW?)aML!hI(oc?FOWN8}V}LF5>0X?;u`I4I^Go zecsS*ps5jq$Ka*z8yG`?`hr0=Xw(F7^d9QVhL|Bv{i&hPaGUyyVZiV?>d%0k|1R}) z!+l`n-vmbfCF(B?Uj|100yFY;!&eP|M*X$nYlcN?)35}Ld>0t`N0Q$Ao{zq#BIyIb z$ZL{*2EA=RDHpw8G3n>u`p8=!g~*O1qQtGAaPI2~e7uFft12JX!4g=(s);(HkuVYM z5N$gM%0I4D5lQ~hP_|MFxnaf(pMy#roVy)LRmvb2R~jIv$%pWpx?bj&h@|Vqen#Gb zYqW9(u64;T6ll?J4jn7?H;Io=)Uo&e? zP19~^liHfL71oDy!{y=Ha8uYDmcxVLsqpjg%kb+66-kYpisVHKB4;C|P^S~>+|ee( z8Bo3iN?XGwD1HCkl3`i96JCm(V@K6-->f>}KNlQhOVw#^UfNb?)TfMBUGS}_4mGMS zkz_DE!ue##3sk3z=KexOq+Q4f@I zbyV`Qque|n@nr{UTyrq)X042?(`vLjt7^;i7Op*ipb%91G8dcOw;eCaJI~k_AVp zwg_Xc)*goG@NMlC)O--m2|v>op}&vd>LkpM7H)^~1dR3s(D)n;|i^;|P(Cz(O*jO&Q2jJ)aD=;@3sz>IBbi#>*(lVJbT;p08V9&=9(LIupg z*`9knTF>L2*>I$%t*0%V+mqgNrl$rUm-%|8NSRU|DNmGV(2IGfAN8%=xTW^96Rz88DfrKj>%Pi(t8X5$t$YN$ zbVMChD->B7R>qt+nCHs2nsqau8CGhYg^E>qt`4ZxN)=jxeA#IAK^}-!9j-344{ety zMcf)(iSm(16jnAJ`YJ+#NT!lul}m;nf=W(FP9c*1L&y9N9rHhQ%>O@h%+%>)r!Z@o zA%1}%%;o>yj-(^{z#VYjwO0jZX@~Q!v)H;E)OW8t&F;=%j@Lm~2TSZnj-u`c>sgN} zDBCmK>8{tXge7=3=&TBRgcr`bp)$|*6xO&5X^NNtqxBYt=NoL8QO94 zS*VPizRm@AZH4Z6dXqk|m&{26$@Pu?%nX61-jh%+I ze>%90>fC${_1=UudNVZN{S@xE!j6O*L!2c?&axR@gS5oo_SMl*Ti|LbldGO^Z>gu$ zv-Wno*ZoShd%W&5u3cxkrO0jYWV&Rw1D**>@}6T@*|psRj+h3e;i;mYyZJ(uT)XO! zTIv{9JM7Or8EAfNhqMxyg*y~`Tdm98>u?Tc$1&!0xa#TZn?!emM|M23XLuR*0IqSu zf@7FBU4JE)+OmT$+>4<)OAb9Cp9?k04el)^7v^M0DY6;mW=pOoLn*N&SYWB1Y(?pNKVu3fv;dC!x{9ysr!UZQ@= zQef6O3G+E@uX5dYcS4VGADwr*8@xN+9(#to;B4%UcK16U2t&?&J0Y+03EQE|>%8kI zLbi9^ch1Wb^0GYbb$CpkE=z(Qx|yk1X@{q_JIyidFawqn zGk6j(gV1O7?A6kD$47%5EJe;XPiA*3f18Y=9&c*Jh2>&iUdjpe)$}a)UBw zI|Pq;p}e%v?6f6EA)Kd`BX*RYac>C@73`)qxN=p-{s>`H?YDJ0(~+;a%56q^MA;5J zRttg|YDF;L762v%c~?evRBct-0Tq%u63PyxE6*8P9bo(E39H>^1TLKg@skJcvJNp; zT%AxURbgnlS#4IPz%RDcQDx3fxKBINZRX%0S~qA&!NK5QsK&BO&(KflQF;&7iQLdb zOHObqI2Bs6*LN@5r(nG)^umgVFyLhXQg(U`w_uO~GB+q2vQzC1nmBcB`64H`Aj`y>&#Lc2Cj=&SLgJ$$?d{ z6!|F1d8?iKbTxP?il$hj!5x;q2+d^(rj>ySN=p2{h;S&o9|g12`!(26{u2sUHrj?x|~^VBL{ z@Z)xSyAq)lkJY_s_d;|w28b!M6UrmEj-H?ur3-*310Nq&29+oFVc%)N1E?yrME?5>-H*c_G+mo(%mXZ>KnD+CA(x# zm&?T8?ryaXxHr+!on=3|$~dzjHaB*cDj9SK@?#4;4cwF6X`wbH)4k|kgJ(pw zQwP2S&oaw%x50kgk_&4+(ftOlzOp3XnRY`yVShxYxesj*+5YZjPl6tB9(o9m-rC{j ztd6V9jYE3J`8agXea80CPFTm?cSDt-IHE2r28Y?pAad!Dcu}#T=(a?W#aw1zt(-1_!-@{?gzvv-QVk86Q^}Q)EyCd zIL0}X42k$q@`sZ@Oynn*C6^Izr#wt~NEARD1OJ!y=?)V4I7<2i#7JL++9*n@!wUST zh&kdZQIBJ#^H_mz#0vapaNP83IBsgjanl7HHyMfl4slZpj+-1J$9n?6Xi;fRUF z5fhIiCILrGB953O95MNE#1zC4lZ+!K1xHLOj+itYF@qkC|k#(*Ak0kC`07di(EUz5VyF-ad-L%lC48O2aZ$59NG^cIStlG0ENmGo06hDu6@7^)%Zy(oH0`ehV7CH)GDo{}n2 z^px~56g?$Xq39{;;}AXVB~?R=Q;{?e(aq(gzr;H5KM^EZN)G-cX1SpKyF30(&ARi5 zts{~;UtgJo-&E(TE93CF#WujXjVmK8tb3iSY!l>`+1lU&%cGt`pGjB>T@jofW!_0kNp z!>lrIt{z_ZUh?pH{8_%#y29HnC-`xGhF{=k%u8Gjmk)KunQ^X`S-&)MY390@TVmd@ z>FgQfeeN}X!n(ptU)$vEJYzWl_nBcv#B#Ao>=FfWP#hG>#3k`1rGFL0Ca9!M-upx8`ueiBOo|aTT zuO-#`ke^`>`Gu}dG1EG0ofUJ$Oi1~{tXR^~&#ZG^>k69T3s8qy@9N|TZkr$H^w1M4 z?#re)=&up)i%b4Czf(E^bMbCJx}YC-{SRSYV1E3MAdA)WEB`8T9Ze_T3{Bs8af zCtQz9dHy>vPfP8MmpqmeP&<#eOA40>bCxF+T$;JI$&8?ctjHa;H?}ukFX9WB1J=NH zUib2+m=S9wZ)eNE;_E&uC-XbZ_;qiWfotM!U-B^H{4z7jIspl_%o`~0>C9*AEFE0A zbp_6i!P!0T86c;EpJA5S8{8xI7JG-i%ie=F$6@@d))f|JlXn2pR?SQNgz*uV;HCtf z*e+V7Y0-99VcztP*MQNa`1#i6&`4tc5eLCA;K-x=*DAX<1qY6i8C4lqNMx z4!9G-g;#tcE-@pS^J&#JG>pvGJu9@ z^Ace4j&P5i6&?zcu*|)fkUVkz0v_#G+o;98~laR z8-KCXA--%$mDa(gr@1*X_qtb@7qSud0C^kSabb&_ z6t?-z{!Z+ZdHx$1hxhysz#nd*bAUk3&xtP)T2UTKoe=B&E8-)t(Wbu=%1!#WAT|1p z7@3+s4hVO0xh<(z>$noGo-=_T(VUliW-SxW@CV3C!A}irHmhS+Ev0B3y08K((Hpjg zZ)FSlR=$)!$2SX=u*S?VPxMTMiWaF%6YBV(phKog9k#O>o2WBZ-IL!&rn{=V@ z(z;M=j$C3)*?cNb@o9XP(8!f@yFwYHN^3E!j|2P=Tg*M@o?9ygBg^r7otZ)#*rrS{ z3!Oajw{d2Id%?Zr3;1fjf$!iYev=#I?z5FJ{y9ERsNqMMA!f9_(Ny^3H5kgm`U|)k z=NHh*i#@iMv%;*kUz!0_E?7=*k(N~PCI0Kxuj#%<5W27HzD|(3Z|J@O&z5iMz6sBk zZ|S~;|9Z8H2omUR>4^1aVb+_CS?>oi>pg{8@6Te^n~PcR&tuk`hgt6#%z8hBS#LgO zy>DaITYy>bf5NP{2(#W_#H_a-v)%^Gde39l+lX23XE5t+!mPI$v)&7s^|oNvYr?Ge zB4)j^4o~T5`TllVu>#! z7E3(FD*rRA@^4_3e-o?x-^VKd7FPLxfLJW?w^-}n#ajR0VXc1;YyE$Zwf=pq^}p6} zI*ItlQ-up&Q?75P8Miu@8*LL^`J$hCS8AlK}D;{&g_Q19J^T&;K4d-Q+gMgPpNQctAj<1u6r0JFNl zkB_9IYa1=aX1jO$$`fCn@2s!FG3#^qJU+=c;2ZHR*cN=tU3$}?rO}jWne|RFh3#Xe zVeb>~lJ|vo*Oz9Ua?JbeKIyaGi&?$}-zsCUG%}}sqi}7nvDLD8dDS>>(U<^lzPN6A z#jG$}wychO?T=d97&BA%>4uiAdM_$reQDk1D?iQfr!9Bd38v9F&R1SsXBI85x`r?A zn7Z1VK3!qW=O?Wue#7^axz+OO(?g7zzjv{LscSWgRLiZFdkwmlxXXBLqkUIwwJn&c zM5+D$mFMEL__SfgGS5XVizchMcey}3sGkyEyUvKImO9>iX;N$uo1wHvbciG3C~xGV zOr03D)Lm>amtM?5^W&4)rYlcO!@dfZhWYV$pP|{YEczB$*|uP9vNW<0_BK<<4zk17 zHdqte)v(VBY=V7sv4VZl(kYa?j4eiXPN-_>Y#(cXaixl>6q;-e?6cOkc7c6qYZZ!Y z9Z=51mI&?alFg3C1fyxt)lb2Qg!WzA0-S>p8KqLw(^G0W?V=JUW<15jb+{jvuLYmKYp>Iwe7PxjQR5F zc@tmBr(3t36&KfStHQ2r^K!Fk>3orG&$NAUgg<${sAUUT-Zo+zzql^EV4GUoS`DV* zR%449jZrFV&`FhI!R1X`^kSAMUE6qfd@Z-QsI<{|;&Oqs?;lA)^^kOk-rbg4mU(1rDK6cU=A}bv?aK3p4JKgQW3tabvpx|A#2qG`-x60XnkmOO<9jMP zoCUT4W|6t&eQwfUnYwrY$lvw8HtAb80KMRU-~pw+4rF8B5W>H2-M7i;m`Y@0Cf)jk zIl~kK4o>+_8JE3BKFX)~qP}t8MDwKY-F&mJ!M6i8eAPaNDZ6-JT)w<#S+p!NHGCQ1|1lF_0+ua)k=bGi zrjozM&$2mInSa%=C>#e*Y3s_dzGgbv3^vo8$D8?wOs9~+7)>vQT)wi)%HQP=nH4L| zukgkEhEUXE;A@yQNOcWyzLJ@=XvUpS@0};ua<;@=9yPQjzF|J zO}9<7jWV^jm>ZFg-Llk)Ct5n0O7N>Z@vO@zmR=~a?AsPZMU29^aU&xxo5~S3#dXo) z+Y=r2Q(}QwV9OJ;e5oSi>lgcd(~Xokg!AWot>TPW;4Ba)#5cTII17o@3(TTPR88+$W~#_ zJD<3A$UNpNE&G=J_Lr>wf3f#1Ky7SSg55#_o{R}0#35LGf@S>-twzWoBpG8NWXwnA z@pyoxR!eG0ErtRV z-S(K^UYlVN^iR5drfsvmqHR0u32wAK4jUbttYla)39t2<4=i!c;kuy+7RhvVwAtDw z!le;Gn=vA3Gq%xf)87c15HM1_XgdtWhmt~~kmAFYkm?)ykT(L$ae_j=JD9VoAf@gNP)X6+~*#4PnvM|+=qQ$GE(nYFuyd% zhB6|CNJWHNoG0ciJ)6UDv#8+4;cq zn6+Y49?=-AxJCvmY6aD*;H$Q{_QCev_9RTX{ImS-LVqt7F65v4ZT><#U^!NK52 zlPWkKoB|f`*wt;04=0CZzQfvTXBDIW{ikiEmPCT2wdTU$ZhQCDt~OzCp1l?f1esun zzSk!6jMB5gUQ;r?`SG#idV8onWIA-mx<;HW?)a<6R3;t%u&=!%oaf4{;yb3D4aDxX z`?QfRrE6%Ls~?Pdq&wqUW39w3GM9ZQqgOlwu5P#DL#;cW?yTFa>oXl%(%cztmAjB$ zx1`yogWYs8o!359#W#8Aut`=s-_EoL+VHE3u2=2L?ksvUSOI3yj`qgj{owQV{veoB zeVy&Q-hQCj=x}m-CP*iNo~zsI+be==O%1`Bpwr`N>$Ie`)qvGO6!(|hUm{=`!Q&z* z?*rZkAnpA-?Dy}m-@n8D9ean3^nsr9cJ*F#|1EyzFOQl%e=QPKv-8n5IC5$>J>Zvj z&APt^q^*3k>@Nk}ee*ux=0BSAS0fznb$=BSU_7mxhUz=h>lsAip9DYp6hi+&#Y&`vqDvucQ$dF;+sTGiYCHL zG!fQ*qpW_Xa{OAgr?hFVMr*{ajK>D<3D+4-rBroUe^dO2(Z-1;qN(9^&L)K?+!XPf z{LTL9Kx`l>APT4gdjEBQGvqP?WdSPC;$QMF1m^svx+S&_P4V8{I-?QytoRVBx{2d4 zu{F3xHW9u=GjVOVe#e*W6E@BHWIphG?-TDUeTOg3m*&&?J*}r&1+AH_r~G|^hpiHS zxD~T9mHlj)m*(q?z5&lf$-RCdDXYW#QZQ@|i5pN^78rsDIen-#XYjaxHYNKM?EPZ5{Vdno?>GM4HZ2OI#3BT^zeIs6HYX? zEimaH2;2zV@(=jKfvrGQ;7%aRe-zjWybK(-a$EVV{(!z>1BAaPQ0Pze%lul;fM?%t z1LbsrG!DR&K!bn9zup8SdbNv1U$SSmi7<8gqRZ*>(vQbjtpJTEJ+s&PTh-SRyia|3 z-bdc&K5c7tWiQZYXKPVwg=fP1#J5ml@-5Xi`i@!~nOIgsHQE|&Yp9iJ?PeO7h%ed~ zO;rOO)VDgn9&F;Yk{%n7&NR?yr?1m!YMQI;Wp4T=O!qvGeJ?yFM&X(GXs~rE5ZgNA zZ*ILCi1(WU-au_22-*|5ub@f7DReub>?&^cSs{Rw_KIcC2UpPPH{1CYX zy}$nnd=oba-^Be_==Xhy^PKY>`4;EroS!4Z@Lk)VLJwCX(8JZYp@*wc=;7)+?6+CS zIP`P%-=LqXzk+_Q)}WuO??XRVKY)I&HlUxYA3{G@ThPzdkD#BcC%h-T=g7}^FL*DI z7rd9eUm!o{9r2ElUqqwPC~^cI%SHY%njam99K+cb1@o)|<-o76xX~A*F9M|-q77(t zba`|I8WU{H ztc8As^{j;^$9QAB=vQNym}WF3#vc=>7YTiHS)p$(8}!X(hrYQe=$p&&!9RTP4=BS%*+Bn*{lW=t zW__ZgU*~u8{}A=_|0Dm8&{lpwzaI_q2lxYM8~h2UC$6A_C(2J$px-)CeWDuu(-ZY4>d_>fRZv{b5`b}ccL@+IxCaaF5Zo=e zTL``ccXwOd0xa(C&f@Ow?t1y_R?WkF-90@Ir)thfPfr|nGB)1r3T-)U`61mc**z&M z@;z1K#&{5Hb*FzepRZSIDkLkpR4S!;Vpdif;73N9Q|!KR3*~|7=bkvbh~uuiO&VgC zIvd$%O)d?s>xdxU7^2vGu~~mujg6_(Y}NfCO2zOu^sSdUgpG^%9oYwNXmnaU3+*A> zxQ?AGq&`5ct)z%qrtbH!=iJOMhbLtp^`|(=BaY*SdM6s}4kEi4`&MdOS?1+wlYX!I zxnnl2LiEIPV*BLs6!JMx`-Ju>)A|hPMZUwF6+NwMmE$BIk{jBn*~+m4u?oB}Z2A~o z$Eh0vrQ@TgtB=KO@NGj=RcD#j)Fx*pnf!=+PLnYH_X=#*_k@PxFZb5?L*UA($Puji9afUvt48su8Ma}zX>*y&*6rQyYW{{A#P)x&@C{Rn2Y;`mNQLt) zlbJ_re^aENm@F%+t@DACXixF@SzWj?Zz4p+7?Ee}BWQWU=>jhuV5E^2GKRPE#XMrk z_})8fPimQW?avtwa>qoO%w{u{PL>i}LB46BPOGgnLyk|OdaxW;gMP}fcC!Hzp@DVc zGoV3#Q`@u~icxc}&A5qrBIRJ_`$MLeSwTbdYsqVgQSH2=Yq_Z5q?N$GEET2XK%25| z26UcP+q}9J8pdVb?8)L*YWfWam_l3@Jal|?n+2|sZHb)0Dh*8m4-dk_9+=-hYEPgx z;vKS-A8qB!FTP8AKw5I-Lovx-t=%ZF2FWvtvEs}?+zqZjq_#KC|1?nbYHY~k?Y9U> z51dpx%(z5-g!`+;RuSFruQ(rF7Zz2YuHRc_9%u!rBlF9?w5SU^SYfz7qWoQJMBe(P z?gW;zN;oHX)O!Ek>~5}LyB|wQ#-KfX4g-0aY)7b8t19QhOw-9ae2&U;=S!{DU7cmw zA8jslYH|F@Wiq>%j_U1svq(Y?aV^1<22`0~;+&wb8%VYxs9oH=8y4~2`9HD5Iw*@! z%57_Zw6=G^Hb}%G*LFD)L{|>F9j?Has_PKvKY09zXqSH_9yPb~>{>u6H&**Vh?JMS z1y2dXL(jNPUHB^>vrKmW;5~epyr5J*{L&KYI7RataVvN9kR2-ulvgH=(h?1#sy>8k z@$>#`pR0=?EK5csr6~T!dK@CHH)|;M#^ua@ETt?gx}6Uoxii^CR`$id=;78dEixtl4;{vxwVd5&>ycFyWXz}HW@6-{Bd740k)XL?THhVsPV zmdPJo;7HqqJ!ExG?S_TvSlpy4&EOWyA5h@L(?l%&{WG&nn5ko9lkU($Q%qA#to%8* z8!=z++SWOR=($ppu*ih7@5medm+kk+7Y^|;pAnyM>86lXG4T49Hl}*)EaXVTbmb_L|HJIPGcd zVVkiUi5kNb`z!h@DEFLBoKB=AR(qR5jMkn2h0p&l{8cIv2YJsM6%VY}g71u%9GbVF zlUp>bJ?o-}L+CE9>6O3Vk9=Y!r%z(b3bUa=;Q*Lu5>5Ic{JrU^GS<#?1BlFcV2%Z3 ziUc~8qBwZcZ37(jVSg~-cA*wVcdW0+xCHfGgU>K;t~}|&W`5W022rjQ*@X~f47)JO zEsJ*veC2mn;@(Co30G64K?b2|Hd4O7+V8co=V{MmPM0U$`n^iPF3kP&KVhEUGj-W7 zPW*<0zrW!`-6E+sI_vX2ZJ-pD$StaM;D}d8dekx#1S#+WehD-YWi~pA^+hJ0DbL!d zPdqNtU*w9^F}KOt+7`6_ncSwUt~Och+|sf}a`$Vmt>s@|>YP)3kkCJ$?Fq+-Ol^DE zyFM9SZc@S9K;8c2p=236>v`!U#x0e`e+&BR4aW37`ap99_1$QkMZLABMi%Z?>T~7? z)CUE1OuPca)H))`lvL6Kq^g?94Oi9koWfbY$cMx4YbNJ1FKAh(0HcE@2Yy{W8}}G< z19dgN9)FvPk}7dsoNV%w)u~LCIEkzNFD75s!(jD`hu~6{3uoO9v&!}KqnP2mG~)Uj zkbn3L`|Cg+7cfI~B4mOy2VJdFU_eNk^+J#rPGr1>E$sUKayOvB5zJK=fM)Ifs`GiN zI_Rfa=S)VnC=>sK9^ANm+`q@dLQX^U97f`)F+J!`f*X^Y(eS%y@j(*`haB_;qKf>e zXa!9c!QJ%S-rq4dl#`=Slf#@@@OVGuZn;}yg7KiJpLjwQR3)zs3n{!oAa4tvQ_r~rD)=QP+${JIbK-jZT_2zufdCOu zi^(vvO(Xxhe$o2yMUVdhv5fjwIW3FcRwF*6 zYn%3t#^q#O9LduWereW@iXJAzsm$U5ozYyUhS90AGcjtebe-aX|#{NtDpq&cO0 z3r${eiZDj`a#rXBFW>#BfyBy5hvXE&2cTlD=QY6L}|Y zu%Fpy+SX4Fpl>_X(f$?_awul6=NOiY)?v?Kt}j%rpS8O=lMQaiZcw{TZ!>$+_#a z3=tQQm5g1Q*iMu|Y!}t$;xq2|T78Wci?yeoUTN*!fL_3;khZq+)ntc>a1Pcfm@e{P z4yzX>Zi%;SPzk^~mMFJrmbXa?=DZZ@VYRfpO1O@EF~->b?j-Zx;+`SA;CwrOM2n5t z6L>Q=ZK6BP8SdoWb5D@nWkK`Bs>n{FiCJf!t4tN=IP)8ueN6pb*oATTDv=g#12^iX zcEUaTWhAK=oGw*9yuco!y72`R*h8^BPm&~*>e*Rz!tq>o9V@XPxgSo0W;+6ly7#ff zQJ=7ku)2Z~Wpl*%9AmxQ5zv;}8bwN6GO8zsZXfTq_;vBw*rhxW7x52;joCM}Irp7K$UmE?IHB!7t77P44qQ+@12*q{4*wk!1 z9_n7$rDarSH+mp~6acm+a!FwO(x^K7xaFUfzgTs<`^AD|mWTQZcD%>VEZkAwN371~ zWJUlUYjN~!is&Z!M?^AYiO9*U1#zHU9s~rSTc{x=JMe6Y+wLK}@%r;>7^Wcy)VBe| zYqno@@5yu`U^?#4K{k1Up-=E$s}*U;nBXvT&a)z`s`0M|j5aA@%xT#@{5|P0PTk)x z|A4e zXS#_A)&)(Hq+CjC#mRnc(Dx}__y0r$?N=VU^gUk`UPvUXbTlI)umV^5;YZk&p{l$k zyBEnK7K9_sy+*VzmU_HJ>oYs4R7P59P#1xe29b<^a9bY(e+g(ZUQBYyg)TsxI_NY3 z`6)fV8se=m+a9G~A^y~Tv&jLjIQ(pl7C(-oT8fhtoa0onnGL2wE5ou$s%{p{qg7!( z3`lEkI*i-(%dC`Fk)pn;v_oIvCsw}f7u%)`QvJ*ZfRlwq6N+`I9Hh#wSH%Rzu_xXR zI`NQe7VIfprJUqRS~mBJ-v@;y=$U`IZf8OkmUf^=NZ2YpcKJFwnkGy5=)?Ts zZq5sKJ`IQvEVkI;&$a(*gBCMG>4|a3_Tam%?P(j~Rz?+J8tQCAh2<7M_fL;AMhf&M zJ2|5sOYD9uL@FZ{)A_X*Z7neE{ti1QwwL{)B4W&9Kg%<6us6zA&sV=~DI;kty8auG zra~Roc#lWEcyA}hXO{l-YH^MB6lq-lsMQk(UO~fc?{VE~c?1&RgLcnXcCO5Sp_2FC zC;l6KxEXck4>BsikP3)9GB_`%>;41d`66y$kqhw<8p3%Kk7rX!msqKZz|6?9iUnKa z<$RUNp2IdNh7{R{9dvU?P)=w(xKYdVLy7p8lmSJflWpbWk7`PfB1@RJB6*Hq?j@0h zz#qasA0aQA7o9>LA9uqSlMA$++k@k;f-u7=;B^g=jk8i^f6IJE9InWlLicQ=6%VSn?-pCb@9rJo2kk7+`h=dzEYL*!zNNm^_?Y*zeYp*3=Tx*x*gQ%!`}F>P&&`8|`_0F#BfR=>?jX z;+ZsGN9xS|_-4M*i;v-!zU)idDm2jQCZ74N?(Dzpo81IA6YFKPbV&!PkZLfc&1+`1)gE31=D{<7N2Yc(JpV0L#)A`}*M96iG^Lsmemb)yKDkq(;IQN8@Z zSIG)gN*sq|{szLDm7C48lDG5FaHEJy7}QRvuv*sH`ltRCQ7fvn&iOsxb+649G;K;6 zTT+p)k>RMG%XLvCr}c#J*i3l6%YK%me~KHcMA5n>8{{qe-AO2_31k=dW#7#9!8V^) z4yZRWY)@g?lW@;^kk}S{m>3z+YHCpPahqALQ7eN6G>|_q7p9w(qn&P;&bH zsS<|muBoL#P#uK%IkT`OQW>pK*YA-PpM{}Qo1z&uXr0 z*!Sgq*QKabPR3q{mg!(Qn_mW!826mk(_YJZ1Hh@%@%P_`n>Te@j_Wwm&? zZupu>HMGV*sFXD@SkN-#HYE8}ZmWEyg=se-KpU$@S3I39D<@olGt54cmtw6dr#+rf zxu~Hn@&>*-!BaIfqGSuP%kP1?ZOH2iLXEfYFYlqFG;@ikMY8iO61O`~c056w=uoj8 z4RQXVkMn{LTv4$l{E{*I^+*AXGmHFC&NYWSFQ!}0B*XqCqc>61D8#?s#k)qDn>Kyk zyp*3a9}3jGAwW0r6HUiziqjAI0Y}v6PK4tt^EYv73G+e$!c}!skYc+9NNG@uG(&7) zC9m)_1vZheH?cf=+~!whsQHzswy{j`?;(>WLG ztJI~~HHhc=JP&Q|ZywZIqxP}10qa~W520aj9-P;<S-)$C=iPs`gqf1?)F2+5yzm8-pfH=;KN< zU-_X5RP3(8&$Y=Q+OmX#z%s4{@hCEK619O7&LO+SZV6F=KUZT1hMQTwI%i%Bm15jB zVc^L!^-D6d;?q{6mFpVu@+Vnid0nAQdD;h9irlj*Bqh`6;hx}%PATgIr<%+`&6-sr zc_Ne1Sx<2LcbF%vRo%;=``O*=gs5nW&)6EumBrf?qUr|i=hd;@EqkOjKip>4r|ne~ znooP``{@c=HNq6&4vHS7{YnzA=$biE&4)}e;?m{^qf76UV;>Q#B)BeDF_z$$^?CUl z*u*$0HGKx|s%;zp9JHe7N8q;~dYB=@U>7xSraA1d{ktp66mjY<24#iq1QEHUpQjxL zaSP7B#dONOWs6v3KIDfd!k&`9#qbf=+D{tT8!L7JyNzfL5jxAp)5{yj5l~zt?DSbq zP_T(G2V8xNg3*ANB*zt(v`#>i?hPk9DZe8FLJowjsi5(N22oS5NNF?A{caFl`Lc;! z+Xq#hXpQyTf+c-e4cjTPJ>9;l&!SOF1;UiBm5~hh6v07@H+fMlp-pL8 zJT1uhih#hYD9kH4vd7NDLXxvOo?FHiE99DYZ>Em#SG&DjI=tkfC|2b7uKk)uH>n)% zlNvzj`gSaQdx$87KX`EGs^CWSu32?jaV)J?MCeO)sDlpXlb~zSZ_y5ljW$O^0L*TK zq8KrQq{6Lh-Wr!w;pi24-p6@{@3tUWBKS7F5Yq{N?^r zXkuD*#;AmWrR{!}8J-_3M?=QtQa$Z0#CfhKLWcph8W~(nS;(g*6D>yiHT}il%q4+# zi?u{l{MjOKM6fB6k#Wq7p9T$B)o|zml4JzEHiXF~Q2t-ib}}2Q6oMHJw=_Xm`m#c~ zZfd+-($a3&;@fP~@8B_N>`V36T-%7ms`fA(j4*Nbj)Vky-NXyzf5U%i{F#caUH&oQ z+^eOh{E_=NUP_C#=hIxjs1LEJ(=Wf~*pCAEv52r@Mv2MPTvlz|x|n~vcB_9R{!I16 zT@rThe?wB#w;PfyQxkBSyf#6J+rt@TKUHI~R867~UdT*NmMD zlzDD4qE%43XSl3mCj7ibnk7{Gg&cN=k%tSdY@#DbbIZV+x0U8)zW*DfW_itO9g4|K zX+x&ds2pT+FOTqWGzJ1?Z%depmBo40Ug{6&$WSVo=`dK88&k6-Osg7sGsKaHFabH} zxMZ>_7(Xt^is}ow$+L%zn6?kV?%M-Zr^`mn>j?4O;{^Eq%@I$zO*}8KQjxzqj>`K_ zI>hada(FAR;<7%ZF1rXh$VLwx_-K+X9n?oINaWO-F2xdDgnu(|1>sk3 zk4&AmS1`BFD&c<%9^+Th!QVV6eQ+p`fiU{2LiP|IlrS`G3E{MviqK^FH;gucvLFiwD%Q_r zRpyl%4Yb=`_H7fQp4PQ0a5|wSVIYAE;#x5sLK0dC{V%G@{o}Jdg4NNmiX*zN5UOl0 zZg(A7AOGOaY2M~)zuO6{5ze0D;jgRKK%EllN^Hc z?~|Y2XdD;(AkV)yp}3JI_UOZFe!8i7(0O&sl}L06K<*?GzxeBlgSGNf_UMO~gJyJ; zQJ3a+)CqjJq4;L8-?(d18S}Soz)+6dJK*%`v3MlSLz7%ZILCA*sx0O_^e-&~wDh*ly86E=&iQ{)mG4v_=>#_d} z&xEY6u8rP|YoC(WFz`W@!a;is?=PwJ(#}b(pmbOx24oi*zH!($dC})<)muWkapdU1 zO3LIHxW`J!dE(s&g;28%Jp(WDjYpn7o_E*>d<3|Bl2PMC6B0?j2|wj%T-FgM=1AxA zK;>v~FWsQWCklO{zj8FPQKAXgXZ6#lo^|93mSC?5Lz1rpA)f@ln{F`WQ%f4@tcQ|M za$=mggGI2n2$4@>7_1yE_lb<3ZU{fMX!#_XJ#>ST1bdGRp9q^z;``ZN^RuHn){$y# zNxnayt~eu|Pe0oc8zt^+csUSWFzsYlqu?ZcK9Qz5%KioZzWSMnkJ53~V^B(>Q<6JN zutOojD+PYd%Vp!(f;?5t8~;bKjYFkdTSZK!>J6Mcge`=nv|y(B zgewGBCTnrR4D^KU=JOqo6<4NEYE1AEG(-pl%8wk#z;4phJJv(7D+lj-`_8*LBG}KY zPt6|*t$}@_EEQ0Pg6i!eIih z08{#f^33m+O)lRw7Auyl+Af6Y%w69l5Z$cjIbSULGfzfv9mX_@G+*qxU!osQvWGX4 z%4Y_9p`Zh&%U7Do3eA(Ps{BVQI+x z#}AW>v7PqJWy#K>myU<`GZhBJLh(3B85tT0`XE^bLZUd%Q%RaSOa>VS)pWUB5l>TZ zYQ)?Sc2nT+W9m9J+44n8#{yuY`oUx4#uLn!eY21sbI}1% z3;?!H1Pg{$Ks#%K009En9*oogVWcOHN3K`2_kp>9Ei-RnT*m9(tzW59Lms=Aw7W@x zb(a_Ae71oOy|kM?mxPZHZR8!|nSBXu20dB}qa&xJD_}yvr@FUiq=>v1A6DAI;!>iOmEe=!VK_8N-5k_d^B%**& z0jy~dDdpSfr3t5396G}m;}x@P@AYZ5AhLyH(jv*;>AT45Y-LBo`A7^%A55cww);nWtCZ64qp@sNuBU32`mM&Dw zl80N?-Qz0kOxS7MFj2shSrXEDkyywAa_D@4s`w(!_m$YcmEm!>pFLQKwe z@-llci%5UOI}K8qF(hqp)=_!7I0DAm9#%^UCF=c}82fj4Wr1SH1Znj*sGd$Ie!WUXNM0JyY zH*oqs2Ky#%2p$vMI0ViY23llC6`^WoVRXp7o`z%6ea9{Kh0KNj-W7~qxM|g=A|EdQjJJORV4VlEk zclqspcuJ$G$_kx{4D|={A*rxi!K(~1yjtH@_Ig~>oO=>@WbyGhvtMgsAS1%|abV%) zHK(+8P%EC!IPCosE3y^5qGiD{@QO(ZKald_I^(g0K1z6K$J;xyyoB!=A3CY0O({e4 z5hZAMNC=E;6;-;DX^VD>Nv()0MiQgFlFanPk2&)azP99i7}6g;6K#xrB;;8W<&2~_ z$J`y?E|!qwYmb>d%6_}pwO}(QsHbv>NQd2D80xSLw{`gyLG*y{tVR8Mw8@j@Gc$f$ zB5T=}3dfgVfdsV%MjHLj{Kr}MB%zHpg_dLFvtX9AZuX+ki(}2RRLpn_uIy?V^L_`N!8vkP9V#Q5*w^-nXugB6)<^6^lm}+rViPj6Bp%`9U zH!tm!{um1=nvBBUnA>u2Cq2QQ3ZYc_TFspj-&;5v9m#T$PzD*;8U7oL_c2qk#uM}| za?5`&8HGImk*~In~l3&NV_K89um!-IPB@H_?}Rzqp__V zD7XvhK>JhZoyxQx@($8ov==*wkxr~_90pm&b+;XM9gf9MD=Qm!d^FvvEvL$NO1HG}Lf3mMb@A&Sy&M72oP?#b_kkcQ5(XDv}d1rpL` z4<4CIk1ZoZU)_;_X^U9o7}7sx5=PS$yUSytkVo#>9Hy4a^TidsPyQ)1jKFz3haohn z0>#9*S?cM1_d^Em&RfUH0kf|dDFH#I{Sk0T-x#QZdi=Dx06Rim^5KXu`(6yUHCL4bKrg-RC=IXT`AvAlw=O7X|jns~EL;j7@Ra9j?dlGaGKNF<7Q}T+{>g zd|<#IR*$51$;nu$%`i+WosRe}g2FMZF*$>ZugX`N20!iTX%XgVan*K9_%gC?Y@IBGdgd4fP7~CRnFx`-WehnEjfi! zh+AIw%XM*V894UJ5Bm;lLByG0Hbs?X?`voXNekr$+Ldn}KBd4oYB5v9D~=wr!!Glk zTyc-Ckyi;#*ux&z$FVYx#K5TQF{*V-z}A~1x&X}f-BYcxVTpmBf^^y=OP}1Wfa|0O zQinao+9AJd@c_+kh9hnImtE~x5AmPAScaUN-Oqy*>#kiHs0+&f>Ox_>{)}zDiks?N z7y(k)4n`~&qJ>7v@CUUp>cC5ZQfeWsmi&md=EZ%&zaxLq;{lH%JA?~ZqJXuB5%>Dc z@3>oOKCQ5MGQq4hGt+|Ybr$#OH8qJ{pW%-WVj0`RlsuH3q zgFysH7;$~gt;2p6G?cb)#U%3`@R35f$Pq^24u&>zSPWxz!vg0IMao83FX{)8NB9Jf z&%$s?to9q;lCMWPSn}RUM7Ohf2P|XM zXqk0b*7T%@(g<%V=? z$oo{s58<6H*##~mF@=@o2Dq_KX?qzFj-N_mx|f~9AL8$6B|O`zl9zrHo1QZC>tJQA zS#C({AeM#tajo-y?I0H0e&W}#C#~N(R3>FyL<4h_QwiU?5}KuAib=9$S?ZHZN&iAF z_l1)cvILj5GuDnKKB}6-)89P9T(Hf#&d#~VXw_@lyh>gl-6QN|YCdM1o{GmPo1*Jp ze(OuH4O#T<8F7>yE^t3WbV+b5YG$#n+vrtQ@Kg<+bqH_FoF@Nz3=h!0)?vw)jV^9rY6II_iV8A`5j%M)lQ zcAbDK1&HC5;n9b2%gu&z@V`NvL4Bg)E#6)4el-6g4B6P7v};k!{w%~TFZIED)fW1S z_e!StWvw_4d5bUhbx_;G@LL0mixxeq?6j}{D^bCp8o1cUeA@Yxca8Higls7nUT2mj zGSqrJCJo+1f_qHi=5RpyrOYG!D_(~pig3b>CS^T_7vIzabpyxdkEOIIyIdAVYM(S4 zWR@ViEtXiKFeaVru6AwB?Q;JPwse!tsYCdDUr1CZxNo$pVF0dIf_2$PrXd~-a|-q= zTJk(f`NNnZp@P>0XbLiS>Y3|ZdtLl> zgVGS$A*6P*;u8Lm=BivA80?LFZ53Ou;0DX$3?zyOE^76$-rZj%+b-nrv!33Ozr!C`P|hJ&@(xNg$F0L@Hq|?xE}K zw0P#9@cBxBzp;=+ljL}wo`w1%ox*C%UA5C4v+Dykt+}i)4SM z2|3v|`CgK+e2s$16tUW0{ylD%_(ronV8wtAh5qhC{&FXHGG@}Q*Ki>gzKzH>g6JUrEy*ES=Wuvn$U?dl|A>hoWub$-Ykj7AUqSS< zPW%eWilfb{X>O(&Qez)q!XroUT!21%SrToyi;^~C8e*D{*Q?+I-GgF+*V@STPSojC zD1hwl+LENqtlkCRa|?@)aSsnqsUH+b?!182V@O#X`Ko}$?rr+eEA@~1DwR-qMqwI> zSURp=;eq`DP=?c<%~bqvl~eO`Eh{yu@XhvwVZ{KDe+wAL3Ml?~>H z7A{AcOz4Y1mnDl##U%hEzvYxDK>UVTX<1#;TBEHvE!whRy%;HDo~ktf&pF4g?P(G1|oaM&wrzITP%Bz zdYK8bX<&+w(SpF<)a|l@WGln9;g9ix8Wf=)XB*{vl3}=P7R{A?aAXDdX6kluY}peD zcx?G?86@}ddO^qKOoyHm7<^p#6%yy^_GN^87Bot;ahVSkuUge$-kn8R2CNmAMey40 zE>};do|sJv7D?hI$7UU&Mi*7MfOE~klY0B+>zfaEh`Khu<2 zJ__;mY>kvjTy`Kh;};b_G8Qpq{>55stF^d-U@Gk`t!lBG%(0N4*YL{ic0yqk&O$D2 z>DUZcvOe7IQeOki6WlI;9JxQ^*p}o3tsard(2~X#=;Hp(-ZXjbrzBkum}yJ@%9?S- z-y+Nd&6mS4q9R#96ZKYkM*|IdHs#p0<2ydNvp4sEZ zWLzXJz?4_murAIrv;PFyETG~@0%I5*0ylGZz z#oyhTttkF1CU#n9udpZR$MTWeyfIIb8=T^s?qR(-7a(7cUhw;uv^PFM)m;8}SHvea zKC6f^67EBR6hbL(!|Z5+-xg7G{dFK6`m4i#>|PcgTFPXt5~b$_ht_1pxhjI{*WfI} zDMw9NyP_6ZdHTI-_^iQq#eXk5JHvCMiHK%<4g-MTFT!GHdZOd&N<#oGIh$M0hFtPH zb-MJ(wQLkQw6&@qYsCh``Z1zO!|MNDM7}R{RVtEElIa(ELykvWA}$A=OE=6~&;s@s zJm#dYxJzgmtsRpDqt!I^_@>gML@Q6$Jpub9=bqVWz+hDhGC&@U26Dp}htnA9SE*;s_Qfl|>y z*CfeEtu2kYVpEWLUyjS`ug8}7r>PUIsh_|sp%Hz_VU7nxmgFkd_|~46T}t$3#;aGT zIW#LDr+}MvC{&UY?;0v2|2oYQX#tffG$X51;Rd%{&6iy71R% z(jS?m{_?(9g1+=(6BR+;oKLeuEo*IX=N`D2m=`o)!> zorao*Ogr8jA!rGnP?IGbnMbmjfcwyP=FPm!m~4{*t>^QY7gMcC2%PS~2;LOg-3v8ihY}E3|f>IeWHagkQ;60E9d9r5J|IV`0zuvg^x1@ z^8nWoK0RVH;S%w7&G;{mvxB}nV)>6uau-)Vr3Jikj!V_;CwNa;iZ`S;lAdhX6|oUY zPZ3dBDvX$o&~i<3nug#*4ad0jaFd&c;-LK{@(KItjvkMzT+r?FwZ(*)kV=)XE z^!Vcs3icY|?EF<=bj5f3JmDZO*UC&XinKf`li@{L&4;)VTV7lcZFc?;qDS;S3niln z@H;vGFiWs7ra8qaG#9u&wjPed)Rv0+rxN7Z*4QrD^mm12iGLe4%?Yf0Aof4BE&HYO z^%(I=AFO(^43#eU+!q?T^k8-8L;Dc)96p36In#Q{(~0^MvmbxK!n%XMsw%TX`sYm_X z45jNaF}67gyXygYz-@aj=F7wz{mKDi>48A!f)j?v*XKX062uQalxIBs*9q2_ddBPg zmoA_`BH&sJ^e+n{0Hi03-4MC*yexN?@{%!pzHAQMC$2t*>qVF03@V$S9+@PeiLTUb z;vd1QNo*#ve6Vp&`y=c{y7xcJ0WN;3>d8*rJ7e+#jUe_3+dv!Y_e52?QsA#ShhyV} z+@M{Cve5DaE%z@<+53jO^dxnT2E(6&z)i|@Dg>>H+iZP)dz0?e41aT66?8$SzV9RS z?E5jZbOw@v<&noX8iylvlQs3t)~KGd*!R8}XQuWjGn}eO#Er|*(SBk^g6`DD zRX4ZaIfn*4ihmys4;hETipg(yFwpaj^VqqM7OW!2>0HN7J418D4E|_rHNWXK)3^H(g>u>I0bDQht#(VO>tBo2rv36wNoB6F+EcP> z8^}OpmcN2qM~-y1sQf?XSp`r0Iw-x-0cgU0dvF_#UL!#+P`H6wfx4Hh-N~@d1bqff-w}?u@n&_?W$MLpEFa zj_l87L)etf*IBusA2kz4F>|ic(xt&XbO}_h`f;p`n`Mp!nS*mAwgKkoZdu|2{gw=( zz*%ziYzhG@2_Kfg!+;jRBc@wcX!+ig8|Nx<$W9Z+!`7>M(FTlg znoC8?&8XWRiGh!3WjuTF(CrIaMOy3lj_JO`n2W1og^i8pNczmbd$D=prO{CnL*B#2 z0KP4})ZEYby$k^M2kLc>MKPc9>Atg~S4JQ9!D$dXJheoJ8@a`8N`&vwl3K??Y+KQK zilvHqXemG}kOSph?RJNk-+Jm4UYoeO6C14S$YpF!Av|1L1!w7o*}?aGpZT*w$5}^r zA86>9oa8`VxI%f-7zQ*kWzKfS`@RbHge@z|{d)ED{T<_8B)O`#*L$Q|(Z<(2x+uR{ zYM-B7MAOXGVA#4!mHcmgVxoFZVy!pg0U7j0mXemzWjRgJvp%sPE_jTYx;&I!g*tO} z^p=wX@EKs&`~78Jy-6rB3G{7TTqwZ8xRB1&@_X08WJ<_j_e`#k7e|k6(gkfxwaP+r zz3S+4(Vn+Nk%b{&>!I%^v&w@VeeZisCC-aqX57WN#MkHcQP{rnI{=^SZ~W`u=Yknt zeAr}P^Mnn-i}_Y!sRE`t;y=h=(u!^i;|#zxz)Ef6M7*D~z;_nUUO(UE^^0}QApb-mn~fDK11 zj}FE1@1^74;e7nbmB6tzHkB6bp?oB=?r-bK08O{D)2Wx>zRC^zNmo9>m5=0I;i(J! zL)$C8Z7T^OSBX5t=M|52#K1v&rVYuf2bEvnHTy?L*wDu8?3h-PK%Tb?+c>PWV-mv^czwH-;DB{8*5lPv<&#qAeG@y!j% zh?-2WzKu(mrxKD{z!5dH4Ucv2SJ82?4yNPni_Z*aGHsM`TYM(%{Kc^v$%c(8%pm&s zCJ*H6o8{gn<>VO5Xeg>ZGMnI-_{{(4az%(#i-xwZp}>|=3EM{*<}WI0%;QvI@x8b@?8pXw(u z1O4#*TS}1q{8M$1#4 zrD31?-dsEJ+9ZPI@uOfg4^%gh{`O97rlHGr&y(~{KEizO@A}T;Tfuj!G~<-b5xE)p z?Ygt-HQRhncwFZL8U1ml{DoHQsk0zvN7ohL^#PU(5kLAlA_J)W0DsgMt^3O0OJzQP zM0L*3zG9bO7ca6$PpFRR)vgLyHl!|$6`MC!*kvr=H-wN{O0C$O+P2Pu8Z*uq?@eCv zT|n_=XX!2Xpb+9i$yS?H+s4_qIiJ0PM+N$ z>#Y(;??aqt0&~N!N_OMEs?RR0WRGnjWITa^vBd2KJKk1ud119q`K*YaWz*cKRlnW$`J~1>L^6 zdL_QER{co>OC>((HQpXb(r4?Rx-eQHa(?gFy(s!9AtOd-e&WyDy$Fo&RDI8%RNzi| zUDLRBvl!lpkrTdS3rPkAnZTt?n9WFycmr~84@?eHp4zI$4*Jc6Dn9~HM-Sjfz1OwB zzGf5(^RSo%jVsaX%Z;-z`1o{PvuCFyKfV4;1DgTex=adp$o0x@?~nstCC$GLM~vf7 zWqbrzORnqxatBLi+5|gA{z#Hf7Z%P)^3~+#$N-Lqrq6=vZA{dzR~otR#ZIDj@Erv^ zzY#y0Es2{vpn8jK4DsxbBeGnV1u8mk0+RKbn3PxO03f0R`22D2oARg0SL?FA%-#Oh zvRxJ)<`2+oE7ie4WvCuTcJ8lRYwLc1-ulPncU_w{AEEtI!286=e1E5JL^k>6MY(O9 z)78xOkoHpi(9%^{zdbs4eJ$?5AZ>bD#qLGNnX8tb&(7p^C?+32(W{XQM~;PPs? zf|RWM*DSG@eZ++D#h4JcDl%Ma;9X0S=372{vNG%_FT`j`xEV>PnOZM9S`RxK8e{K> zCF3vhx#}3A#lhS~DTUK~yn82tdu8GmUXmAHsF#uepV@w)=suz79-(7naw!w?yXqLY zMJch$*NL1Xgq>KMGm!K+0nxzDBMX+G}#6w!-ifKO(q zPhG!|Vvo?WG5J|_OhR>xYRLlHtc}$1o!W6d_T6%tXHsLi0MQ_lHU|*vLxFo?&{x9T z`qiyI&E9-~(PsQ@A8y@|JF42eWr^rxZHRcn{4%&UV=QH#(WMrZo2_wC;!j$d$whV9 z7-?Ilnb3uUcGrt8-t~L3#3!oBHx8WbH+nsx#OI^P3?5n;c|KfD9gse zz>&5!VLSp9aAMieJOQfp7-R;(i3uKZ?N0(DHKH z#&!sywu)bti*KU_qa`(tFUsxNar{Ybvl~E5`6SHi210(7b#4>n|HO%(;^^d0G24G) zjZg95@QV4VyT?joyZk574t7_yXQ&*{|L(_W3 zH4HS3vB^4B065vjZ^Zk6?5tH!mWwG-&v!Xfl3j|2h}Tw2kJzkK7wGMh8k~y@?PeN4 za?5OIhb=|=)1dR)+sL|Beh&R)W*3V>#_1%GMGMv1mSHl8?DKTCfH&dhh1yA`?i^F8#{rqjYx z8XlpQxHHETvr6;I7R03q+v1GW|IzgpaBW1-zi25%TCBK3afcGzi#rr4?iSpGySuv< zr^Vf^IKkaLxVv-n```EOd)Ic(d^4LlXYx5`KbvHCc4oYDxVm+7glOMU?^WKGUr4=P zUwn7pdt*l-`&ZtEm5!CQq{&usRtJ*%#e2n%H7$frT#uJ6(9Or_tZ~)m?P@h(RYZuc ziMy#!KV3UV`;2D)Y^>r+92$Md@wUABwCW*5)kJpR+{Jt^W?PUOzml}F4cv2qxIFT- zR5|HCx4;eJ5bfJBnX6BZZz$PY3IlzC!l?n3K0d;+0VF<#!npy0K1w~0aQn~waIasU z9;qNCEcZ$J^mfme_aiGlFWy&;q+K%WcRT7}=pKRlO02&2S%qWn^E0@Keq+Qg30-u& zD@}olLShG_tHAxGYw&$i7Chov``#CjwZo#$!}vsbg!8_GEZD8icefl^*46K zolu53m$svQRVGUGk#iYjrEC1njoOcc1^s#q7bhkdw6#-uq-BTpV5h%_$$s z3H9G*6tvCgNyiuSPFyc6k#uGS=Jj^od z#)?zx(Py-m!wxBI`m&&WlMGcR;}}A{6^7%fIEKt|IEGKsk>6np#nXhR$w$SZ+z;ii z7U*WB^@wb8T0!{CO#iTCBEJ_vyG%hl~b4f@3&H+*1DcY5Wj}E?Ncd)=D<`2zBR{#LDwRhh7t*w8>gK(D3YT&FJ;cLXj ztkJby;^oCS(b3VD#6H2ppyTfXkW;tl$z^*#1P(2K3=I448}bYQnS48%Kb!eF`uxyy z{dvsu+;eZAbcseWE9`|0FwUc-gtcPvQdVuvwZe2=!?lzdR^1`D=X5f0G7%U1$}n(r ze~wA~QJ_QbZbwt2K=^bC%3~If=cmdnGTcw3SsZaw>u-aE^r@kjJceB9 zCF&yuh#*PtNt6R0e9ZMQ_}`(X(OUpp^GH3huEg_OK>f$HK(&03vYo(k&{LjJ-l_T5 z<>Jo+1UgAN0tmN@&8e7sn0{h2_n%Huufn7joHkROg%#rVC!2Gf#k3W; z+ADeq@dlB0!%iykBce%?ZpS}-cFtg@j-E>0m3ZW5j%$-9SE@~4L^ zf^NW&pir17kCk9hDWg!DsKg>86q6n5-=~uFgDb%Ya;|3aXo#+ctaaP=!7j>|Ban=E z)F52waQdP2BQbR_23{zG15?Nzeu002dmlK!h+xF_0l+cS8 zMboX#G#OcNP8lHx-Qh19x=3k#NStF@VQ(RqD&WYC}B ziX-re@|9w~P<&k2C4ZNY|5=uy%wR6iQ1*m;S|(VQQ*u2=uvMTg_G5J{VVi{2?-nDl z&)7Q6O@|+xgTdC%&nbC=)3zj1qu<`|!?2EHSC`tyx2@Z#(N41t?7}1s!?aH4rcsbHi0ao(*FUxT2QuUZAlEPUCj^A8f@0DfNNV>|RGP64Lt zG~C7gQnKfN(^&Fx>6`SF(-JTN z^ZuCQWW?eWK+Lh1{TfG_u0QYwC`e7H1~MBPiw4_Ph|E4^fEqvoNmk{Azjdr$DUy!M zGfi5wa%@5z8*UYUR@T`1J67C+Xcsg$;vmpU$S5Oo^QX|a&-@%KKs3=lp{6L2 zlMv*<=dl4?r4JA7Q&RxtB|5)DoxOl7+{F06t2d}QSP6xX6hI#;3SSQVKdktV(KahLYzi824#tdL49ji~%X|pSl`D$25PJG>s)#V@ z@BEcmj z@otmhfiN9o`28zQ)b~P+U|OlK?%$#{!eh$>LYu_y@Rfhp+%}E#?%*tolj(~3zmX0ioylIA zbj9@ZBM-Y?6UX0IW6%W=mFUCg{I9P3amb%f6SyeQB3KkF*x1A z9L*;cgyhMhCu8<~EGU#UdE|TW%u^ca!X?P{BIA4Qpo6ylupyuG5M2^f-dI7!+~S!7 zHfLV%l=0tehm22zyqSWM`;#paYF~&bnrTE*XN10GcgpA|*RaR4IwWzHaLuIDb1)U0 z9#-6NYDu3LtXZHfC*I|ESdcEKuD`2HtTp22fm zK;8a|x`P0%5JX%ViyHQ$V48ws}OTP4{bcgoOq;OUe%<7nDZ0F)g@ zo%iWp=r(`ch;G~VwCD0-sqDKSmMaMzb@JF+Z$>+dJRf{D>6{@&>xMNQV8as%3*8L8 z`1$gkBqVeP9q^7HOxja$S>T53gB;r*yW{ZinV&=`oM!XAd;e1Z67Gd-I`f9id-%1G z)ZOof26pHNAPkurErD#843NYx7ZSf^@(EvBB3^RH{Hk;`hXm@)+c6<>4~U{sO!&NO z;TY~E&YV~^jD3Xytvi;CN~j`2XF4l_J@Q8eZmu->XjbBMRyccBd~H^=V^;E&{aanh zSCkpVXaamJ`5|O_(_KY&(Q6B}y`OM51X`hbV68gNawZ1jQw>iSq~mT|Q^*PDeEixt zZw;RY(1qss-^jTzKU` zc=Wofwm=UJ0QI(*g`Hb>vaTGiO%!+ZE`Qu>iFQ`If0lsa3HtzU#G;HnKZU{aMEc;EDF)uFb;Tt`C*L?1{KDbqzuGf_>BO#tjrKDvvb1FwAM;5niw^2_m9%`>50wr(a0#$lyU20XO8>Q-V zc5oOPt+MoK)rjKud0)ub4Y4^5aZ$Ihn7439wy*``ze>krSj5u+$n{Oci5)7M6=pGS z#q*l=*uSEP$2SXOMGkCJPsy?4GWCt+tJY&wh!ak!C55}>cQlJTe{G6zbjWPhb;fWF z8{bx#5?`gF?_1NVnU}IE=a|Z{WLHvv4)fZs2QRUe=ZH`3p*ZwBSn5RwP}N zdQrk=)U0OB#H6XgO2Z9K&!1#)|3ZI~TPLtfY{&2y_~CW&&w*=oV*}QFV@&sQ$_R;J ztO1Obc1De3n7%p=ZRCZE#_(UxTA!C3OC`*QERSd{;ZNm2j;W0qA?nz}+=JYN;p&{* z`kN`tqH`DU!MDf}6Gq;FMbSc^kI&zC(>kJ+qWeClg|Iu z=X00IOD*YJ_N+$CyWb*9_40WA%$aWwea#I;)m!5Jv-(4aZ~Ve@*YHYw)tl#Q_EpMN z<5i5K)?=1-&v``xiJgF3{+Lek+rWk6N>M1Amv#k^?*hqt87Q;^ep^a(IPCSg(A#hi zd7o)tM9cZxbkngtxGpzH@(ol%! z2_B!~j4xMG;llX)xTN z5{`!$TmGq6H8MN2J&a*W$w|r4s6lQ*9$X!ItFio3qm$(Gm;k|O)MnQ1>_G)Led!?y zrXxbY%5!rNyJT?4Qb~{@V^$@gmA@Q|;J5cIN}h(_$WNj>b!fRc6u3B*VS&J`O5%SL zc>V#|NHTS+snyZ+PrdAUA$vi1`%W68zeVv#+a3|Sr?@%yA}xq-x2yd~=*F-y?z&~u zoZs3!s1aaayXjsbZ-JqI`>dD&-B;n0-7Vm6mx;d}6ksv#ckS z;<72{Oku2TtZgJ`IV`y)sMYBDtxx%G$WW6Ums~CJ!-N_bx@N0bkX>B3CM4yOM{@F+ zGe=;Uy1Hahj5A!`Ol48^jy-cA$8ct;&Kf>**sNxwdg+9RGjz=Kdhyy?(C3R{U*d%c zKb&H};*P}wK0mQgBycm`4d)FdCpx#+=|YDeO(=GM2lwLR3%QbkrWbde$qSzUS zo6o#Cg3>gTB|gd4eij2uHM5LKNp)Of@TbhUI*rmmTKpu((J%k0h5^QaBd}&6p03>} z@c}%KYrRJ zJ6rPX^yVsgO{-S_l8XP%l|BG!*_1VkYTn}9axQTdG~NDgS`f91%xj8M@oYi7Bze*^${Kc4lK`Hbn~F*3fu>wH z_*hLo!9hAW0WCoLs)+W5LG(}>gJ92w%UdsjTCmpY(0Ddm0 zJ(1~X2~4yeZ;h)fL|j-&r!?c+;*wS*(&O-KPvj{Q<2q&nFb}T~d6@d!9^9pWGOPUqg7DS{wXbW`w_#S&x!~+Q69DO+(gtb8bsZEe((@1mi~=T|F62=9rZ@Ie%R^%lxkB@bGGufOz^^+ckC`bb4^1fi~4 zyEDv}&wUNJ4Y=`tnWk~b@+zk0zsau@+K2$2e=KBp8W)RXW){Y(bPw_r#jeEi9|Z9S zII?GnkXgs)FppN6f|NeFl=K<6$|!r}gK1442OP1Bu*;0Z@%t+ml{zt$$Z5+clRk~m z@f3Z)rd^<4$mbo{UpUZO{G*I}SE_^Hse05yk}Lv2g(#>N-l&oMh%U4vh_F>2VAxTz zO7~~}VPk+GtG(Ex4FCLVxz{IIyWV1%tu*lNeA!VI)l-Vs^0=Pfx$UmC5oHagP4cXk zvz}87d%khL@xXSGbsF0x+!g|29Glua@Cvs4K;Ci8d zR}-gK3zzvtEh!}KpF{WN;slWt%TD;67c3Hkdy+ZX|rL9b0w(Bp)QR)%gt=*CM z?fDVaEyETr3_2DWIu1HIHY+-=Za*~RU$eSu#Iu;|l;{l>Z2vb_4Sw2?u+YArm(_UG z0}+G$+?PRkEIC-1eJV!z(44;!n%i7Pjcy8~=uVK#AG=<(uhm3t(`euthS%yWG)3^e z5V^5X?r6GQs@*dPKtk*nVT$~embF1W+|*G%-!{_jiyYPN;MPuuKSuH#zq{`aIN~1} zcq@%jF`MUG+VP5*&K0_f?EFk-Lpzq#D73ua`C%Bi?Z&7TV`P>6mr%Q_dBwydODwA^DcbkHZy-4UYE&EOI<|xDzayo%~LC+6#84| zY*4gz=A#;78YZ=@nQBtBz~zwn@%hU6v-!?>|M|RmrTLoq&+~ug@#lHw;pY42P3Kc9 z$|?xUwafX+pUV*{B+CaYO3Hy19P_gCWxO*SYk!_^OLOLtZah5V*H!KEnx^;;vTwe0 zD4$o{FN7XY+^{~mdDjZ+=2lEB;2z4}Vn5M$$ZV9`CE88+yvF&c3Xv7OIRW;%7_XW7 zi&s_~e>2&F7mpUd*z^OCXd9B3Mr^WebZypbylr4@L~RPJjcqWkRczR-ove|pBW=Jo z3^rCagf`kXZPw4$2sV<|gEl4BKpT!m*~T&#vxO6dwhfYol2f=lk2`Wt6;C8jLQe!w z8qeU4>GhTM4Z%Lae}V&o>w-&yYl16+8=XU)vz`AsNAyfLtT)W68qb?ZYe^e&t8*K3 z>-4MjUA~2GPZHZoPNKV-5P^t-V~ixj3ucw}XkDFMoI%d6Hy~tZWKfi26iCiq4m4^% z>cD8v=)&mKexh-@xVgB!xV5;$y~%yTy~lmXy~BOpe9*j2sW4~Z>XB^-oK6SLgE;Lu zT{xW@9UEO;oLwATobH_OoKRg*onl;KoD`fDoW>o;otT}OL6!EEj%qwye6HO0+-Tfr ze6c)=yc66Ld@MXwt!c7OJi0#Wv&k;l&0lo;D>2mnl#Tv6J32W!IyyT#CO9BCB7hJa zXKZF1Wo%{aXl-hpXzh6{HOx0mHOw`D8zw+QpjpsA&@yNo)B{>#A`V|UyKC(|E95(_ zJht7mJ+a+_#%yh#?N-{Ww|cfcw}m!KHV-xrw$Zeev;o`p+i+V_Th*J@Tgp~5*Z5XF zR}of2*9KQhR)K3AXR>EyBzsf*3W}4M_a^)x{@@%V#qg3@mA%7*!|lVp!^6XU{1f~= z{8Rk>^n>)hbV&NX=7Hw6=9%W9=JC?O($Swgq6?zStc$G6SvO|)N{@8)Yu*kYyV=Y; z9Jgcl$aeV-rgocl;`Z!z>~$GCJ3HU=ujjPq+~;EF&ga(WUgzZJ%I9Cs>FttT>s&LN zmfJQw7d=-!M?B}XcRF@Ej*JDz_HQ1&mGlSH2h|T4?vfw09+#hapIRSUA3dI)9^s!u z9wnX!o{OK%9`~Mc9#fvw9@HK=9~vKA9_}7cpJJXAp2i=>pP8R3AHwx-S6+R5S932H zE^(hCU#Z@debc*EHV?}hJC@9ppT?=pU$X8i;k14Ul%bJ(HAkf@whR#Nw~4O37fw*6Nw2^l_IS57{YoKTVMSyVtX2489UBGn!QlM-AIFKRGDljvUFTgVZ zAs{qxFn}fy7_c9R8wf21Rv2smWP@*o@bl4p68!um^YQ@ zkQbh3k*AsGo)?@)l?Ta7&TGhv&a24N&GXI+%%jNL$y3Rz%gdOAeE(bqjg}*g37Odn zufjzl3#4yItBu%aNO(57f3eS$PF`Xx4$D4&nqDyw* zEq3H*g5-kKf`WoPf&zkkfF`i!*JH{ z&*2u~OW|g+bK%k972&$!-r<4a6yZDJD&ckE8GS{4bCl59O2FydDC(Kv0Fw^r z{YHyg@ml#>(OQ*Sa?SLU?2}xg1fqDNM55fRtgM`@?5td!B%KVMc%9^O8CwNgSv8t_ z8Z@d{YDG##nh7cvN|utJGSbkem+8|YN&tU&|NK*R_)GaKgI+edgtw%%xV7Y|7``~9 zSfXg4n7XjI*sO4`5T_8QB&A4Cp+dn%&PMiBnplolK3gtZURO$2x~@LQr6lmsjW@9} zky#G6M0UF9u-4hV)v490)w5OKL&`(dL&w9>L&8JPL&?L!L)_z6D}4t~2a|60dahuS zV1{74V76dtXIy7i=v5NGz(h9gXym@>)zL2Y9`=6nZt`9-1T@btB~0{^vJtcC0@eTmY_EVowq8I1+YSJeZ3a*WxCS7x$pXM^3~W|xglyVu zZGdM00-GdYkgWs&WWxohUukycoR7us0k4ktxQ6VqHW<5p`8>bGJnCMxLGDM-bA{M_ zo!=f_{yf%Q?eDXU>!-Xsz8$@wJZfLL?w$_|#rbl-yS*L0TtBAP(w3QJFBx#=jF}vp zAl3CRC0JWDGHU0XCRB{xjiHXm48@Eoj4DiwkB?6q2WK z>u73A>h^1KYg3&hl>h9nwiqzyfOn5}zc}@`BfXYiCKR7$%;?diRQ+EMq}mk zybA#++06bH-@uu7_1Kv^7X}3UL2CA64gXv2=M><-x%8i|)H>NvF#wW2S(Xk^q&mPe zALn$S_-(k)6UUE$lLPzc^eq>b8&@kGiPuRO$XpNjk61ApthOf;gTlV-L1HO@){qmb zH4*rR^vxG$m&NY|E{^5H@JDlR{~j_mWclzin6eN02&<^gg!U}Iy&B;IY>9u&_0e}n z`-S|1*(X?>{~-xWJeFkl-zP4h@mTS36-k33e${|*=+s~gb^fGy7u0>~*9LR{kpM*e zd*>4pb19r1<6U8y;`^Zold$gh`r#QCwOo9X z=*vEZ6*^_?zek-NeI2s8sQcJaPBZdwiK_XJ<8Z^*_8?aCPU&OmRl`;ECDYZazSE74 zja~V;li;#YWci36?^aGH6)(24Q=h&8D3kEi|IAH_MdiSI;a&)I-@^!fc=_7C=%I2< z(H#pT1oMJbc^-KDH#~$1+squB@vngrTqM1Qs(d8x!IAwL=cR7<{f7;Nmk*Pr`;`@g z-H9?@b3Y0~_&2`nheZDl4_QUcaG9*nOsKH8JrI-k!fp4P+MyA?q7?Y#hWFJAM&OGZ z^4=r8$}#um=k7$mlFcW*X2Ib;(eJ5UsQaNXu^&j_*clZ7OlP0gO18X;!$Uuy!IHr6 ze=(oU)YOi}##dC`_HDdpGT<;hfA`FGI&w~ph_H=`8YxmClMZ3Vqo7QrWIOmBLo3NH zMvpZW?VK2w?$8zWHDjm&om`@lYPA2=r|WIu>BLm0bMNuZx9R-FXX3gccfU>$c-pXj zTiLKtch{!4?rLW=nB@GGcY-SH~I2GjFut=QCtUJO6Rw!vqY= zhvOP9+x-dxzf}LOkG_NMNP$&@|)j252mt%wKFkUq@@x__kM6{}rn3jAZPV+K#ZgiAbBs+-iom$F2 zZk*GPW+Yz#Etq<}okJ`xW}RCGwcy6^7D5@lAB>)A1=3ao>3csgjHrDMQHRgkb?#CT_VlOPDl}}jAS+Mui@m5*d?6aO9d1!O^-T=4BzCnu8(K8^R| z{fSGC04W9+jrY!#1$C$yi7(N!f~7@Q*rPI0pQZLw5}D@>+mUaEx@CaBC8^ztho%6S zPqi&}TM(F}%!iDyCzj124`3v8p%P@uzb7^z0&%vGZ-;AQZZHk+dx)~YJwrU^*|5Y; zh9xa&7R=7Wkk;LQYLp@*&>EIEqoGM&7auP^p5?LWA#SvP1tPIZ{N=`2-tC>yN6w=2 z6uIQp_SXE^la1h$jXsIIi0mtCMXiN!&Ac?Sc@15_W~A`_264~4oEI{;WuYEzGqo3n zvMIp`0@yRA9XkId3h}#p4*`1tdkQGALCMM9>B4MttQ&<)GqZy8x-u_1-5gwxWhK65 z-M5cs1{OoDBH?4|QIJiVlvnrK{?WmF1llq_uC?mT0erU-m|`v+!2aQJyZe#f+WW20 z0WpKs7Ev?gA`ivXZNLC$EQkGDuZCDXU?9v|C>dbVC{7Rw!W;f%BmWIIhges3Kwdm1 zrFe2yuAV#z;iv63LmgZzhkqgUfekac1P4v%HzZFw?|B0tqy2zLy}4Q_P6{`W&au8R zC}u28TxAuZ+^-_6l^v5QgFQ5Lnn9t0zau+F>5Y7%ze%FB&_? z%-V0c`aou0c{>XD@v>$26$r=h$Zx>;9U%=t4i@JFlD~L2vH^~0W82Sii7~UgF6G_K zKm0YLd#0!?*KX+p;E#GZR|ztyT_(#vN8$HAT>Dvce>5PAvoJaikh%x7Ny!xL_qVN%b3iGEVnU+>F}@{i7s-q`IdnRx*dKYM_sn{28V`1B9R*j^!D z1Vw|nMTyPJVWUC6S^N172&zA5Aes;?iW+;GTcbsv=G6$WH--+}O)lm%O?)uh(yae7 zR2hr8%Pk!99|*vt{0}_w=Gkdyf%Y^$Fn+>;Ve`|h{zLzbupgzM*$|5>Y8&2W?b{%V zi<*w?Vrkz4ZV^?Ohd{-8%1D- zXND<;W%EbEtL+HfR+_EmaU(1H$bft0h|c2V&XWrbL(mxoQ?<+On^LpjPAZdMhE%Rk z&JnhHh|1cTAEGdIzgMK;a{tr=DJ$zh1WA*>g4zOZ)f{anO(nPuI(L(RGCIyK+LPhO3mdmE} zqVFt6HKX+`Zq+|NF>4x6KdA1PIVF ze`5Z)_i-Qg+CS1?E>`M*_;UwEo-5@|OwfA#Bp-%{DQB1793B!J7H75<^tl6wNAdKv+nPg7+e^&Ls)-zGV90N&y z`x_JL^#2X4hzF~bh`J;kUI_Xxt+4*5od7GW|Gj+_SbzEfJu%0?M0$Idfap}XcE(*( zbctva*Y6Qa-9!c?-%xup+++4XQPYU5J3OE2*_ND2mwXWgO* zVwHASE%_y)_g!r-Z3SXem)b|SOi5T~+%&tvB6<-8W=6AeQ5oS%Y^;{l5@UU(>3AHN z1>fATYnllc zdWD!}mr0{uxK?7!NKI5~7<}OYjrRE7YqBH&iQ#_Q@>AX2@!sJ zr}k3?aG9bZ5<>83;+~)vzwX#!n_xd4o8<~_Tmnjz= z(4D$SE9a`^Bl@d@dpOJ-CJ#*!d%Q*(gU~Te#@2Ub17>;G2 z{;Nq)>bKh9Z!GOWUFgB4p{d_Sg1O#OBi{LQNU(-h06mK`cD zVhtR5x^-!?Ni)tvik3h?tP1R_apc+0x zEabzZmea~5B&rCEK!{*E#beDrRKs)#9ngU<2$Bl5dHyxU6gsk3RHG7VlM>Akf1j?4 zvQ4C@rj+Dg?ZgZL&Wfl8s>g_C5Sn570bLhrq|uaMkZDl~2jgC7_390DYNY=Fvnp>t z?$R1flzs%6mO)iGVbxi;NnLRrg+NW6uZEAuaG&!75y5KEsiTuK0tFz9%3;-`w@Gzw zWdE)fRL1i|5Wz-JB{4Z;DpVN|RvmShRL4#J?`j#U3`YdpLX~vnjDrGToMKbamWmW6 z2xDhhwby-89WBMb+I5w2qi961H?$WwIU}qf1XT<5hOa+A77-kxXr+OSVaRhy2aJ~r zG94(%>Zd?YA%#Y5CyQyMc#UXUV;Htv(E-tAf=owCR&~MIGGAu2cFO)&e2MnNwhGjfys1*1w?>fv#`8$_?yQextoCRjHE zq?cXORYfQj# zCLuX9YxXAIUJ0sPk2L8Qs~iAB3mv_sQRcYmmIx> zK&;ZyLqQ!P8AXaI8p^6hP$Sdw$7_>zuDSH`Z&SqKYqAkjGLu+;Mu)E+#|ZOxqfs~d zIa@zPG*b*ET9o&8zaaC^)0ERvzi&MfC`E#%>1M1#lONp6kE+KZt95F`U11e&hT5u! zTw4nA6J=ea8(fX&-SKGGRL?IHUg(F`8#c3NM=3>59kM{Vzt;@G^%n;@-_678jP!F|X7a~5Yc8|S4NsKR&mQdSfqdIfd!XZWA?s*L zx?mO;Thz?>8%Af%?ee9=%rmJbAzNgH>U}9U(`MHTJ7tLIv2^fEzxdPbYa?RW;r=Lwl z(y)6`3r{sWIo!`z{skRZ&%_p(=bS!jETXd@&)PhPG z(~x>wDz=|T7RNtl=B5*7Rve93%cyGmKAIZY23$_=Ou3S?i!;G)k8wVibn&$7Tvs(U z6-xXgG1ObAbRt-A_9Sw-HgYwkC@!EQvoq0>dHVD!VKGJ@Wg>5CCRtuagES?|wa(Yn zr7!Gf_l(_X=$ia=;!Keqw?s-n=Hj)n2mUxH#59Q< zm$!w#wi-HN+y<)rr~ZBW2ERt)OZ+A8n3>QbS_${smerfHubq16%1)nTnNaE!bL%wE zxnIXCNU1BqrT0?zBP#E+?yKQEgxa00ZWWv&TviH?$Fd@tp$Lk_0&JWXRiIv0VBWn( z=;xwrHiF%d(2!tKCdC6*mz%$})3rCKzwV0$W{L%Qr#8J=&u)ukkM)E)-A1Y@TU~mR z-&S~W6|L?g7amccDAuTCG3S`}1yNDJi&)Bg4jvCLRc0Jcp1bKyjKjYlGTo_cWK(^8 z-A;MhY}%4j>P|LYDW|SMo66Q?` zeR`$WZ}(D>XKcPZO&K=a*@p@{M@QSsdB&2BTeQi{Ck2Gh(0oCULiw3w$e|gPqh0TQ z{&tzN@A;2HYn~$<+Iw$?4bCp6qjy_*(+YaQRaYfA+;^(hTIm>W$1W4h$)XK62vzhI z)4YzgcGgt~OH^INo!on|*i}YaEJSrT&VOgs-7kjovO`-njz2x#aV@ZVHTDC%qC4i0 zDthXwh!1G&wmPpQK-&8@>yp~$73Ht5g}s|2dn#qbe8aIg-k`#hob7?XDI55_XWkB8 z`ch5bt41324+iDayf0wGURc!0uL)4_j43?tHQJ zq7oP#^|;Ra2DP+f!y2@9kzJ7Ac{rEob?*LG&gp^-q!Ys8V|D2jAn%h% za1DI+mFkDo+4gnb-b6Agc6S=CDVyb4XIvasb+A|&FkCBp&3uU5aY{;4 z`8w!Q?jUKvSRVF7Y7un|Gn)aS1c93a^iZ@H+pjRlh^&~VFyz>duliPg=a+XqpmaL$ z_{;-uVRrle613bpI5ejsGIOprP)w4-U9YdKxwzLvtk4SLa$_N8nChX8L#a2`dJ;ZVxCj* z97xCylDi!AoZQ$sc2@Ric2;hs<#VD;_mRXO!|zeGk0 zdETcRTsncyZT+z)7BWt)kG0IEeK#lA>_AR@&%xl2p*EU-;a6blT+Uu=%|hm9_!3>l z%5*@MqGC4(cG|I>tra)pC&ZF=Rqm!&*>7Ki3$AO}gv$^GE{MIs811D8mvfvmAZ`ok^=F-v**HYuDH|5{S z5@B!90PxVb|CKtNdlI|meKw}x+P8Owb$%YAh$D~aWEgbMIZ|5oDmbw=Wq6u8j4y<( zr@z0{yT9pB1j!{Hr3And3XuIw6U!Cx3L+u(5P9E}@HPq@xwAW|bzSzW9XJF_4uwy> zn0M9lVIm~^R+i13jotZmFR3;0*UG4WI$W68*jsAf>u*gCmGMP3pW>IHA@?b-*OkX)kN3w%=s(B{bMm@|Mp2q1@ihl43$;Mrq@YnXl2uEcGo@0)By^ zO82_D6L9~=6Wa$YX4)&m_*ZYrbB{zRIPM^@f8s^K!*`^a`{Xp87EGnJgA&8oviaRe z3mT^x9Ifq~qES>nBN(^S`r34c0NXL5K2g!dyDV^;M_zI zD$MjSBQRo%0Q~_vcZz*8r10}Bbap+JYNA%hJyEjVmc+eNO4qomvX9kb&<-cH8F&^G z3yqy#e1v~mdW5?>-d-=Lvuabw=DRoFpPK2ND@v{{;-)D>+n;5QlOJKWPcm~9TP*c$ z?O>9bt-EeSO!IJ=s_3s`E}U)uKJvYzb6~B<!42~)=lSLC+9Jr3=5=6n=pt6kRGjDsf-*rDKy-}qByX;vmr(%)g*z~mBlBvoO;Qqtva7MF8K5-`GoM3OU@wnz(9}?_b zf3{Jde~q7sp6dys{|vCgXoIE;YN@u^f*77zX{QD^oZ6&3%q0&Um#r|$WEx|2i986- z>*efYF|D1MnIKiFL+t;<9_-k81mznAD<{#lc0?l^-$Fr6gSdGtOnIjBlSaG?np2=x_O&n4EB zsOXgtuk$W7wrpP}%Kp-Jx%oD>x^V9@5$@yDXH(Ssa{9DlBu6YGOReiT-N9e=-rqjq zB+HjZsmE1W*IBIsD&P1p(fOx}@mR}-J2}zu75v(@<~`r*h1bIBHhwd#;v4CaZPa9I zxb+gSw!yAFFJ`gvlSqghygcQwft#-DWj5ZS>uYJI``$<_@P05ASdNZ-bH3m+)xONf zWIGe+V$n;)aw?MjGmT<&V^;}hi5W|RPJ;!ElJ+KA$Cafhg zr(){b<%7$#pCkn6)LuBr4;)MJd#*vr)uo$}XKyi>fi&mJCNSonX+%;6(PFB+4M;Yk zkx*{D&NeVQ2(|HDf{PhItZwhF?7U}ficicEBli=Wd2Iu^#HP%%v#|Hpt3W>6_VLeM zyZtiNNhwP%;@_&4NVGNQ;=!;2t2mb8{NP~tuV!8p zn26ujCYMphWwe(> z%F+=2M`Lyq*mcxj^*mwgt=U99_#Cp(r|~TMWOeK5$ticz_;3^wG{WZ4b0~f4T+B>R zoUyQUq?MXOp>9LK`>JqUy!Rz?F@m%gmXuL5%|#(z`~4-u>;30WqwtZRMj0rzwTt(W zeWa}M7DD;jr+|$lpEXi(o&wV4o_X~#GCobk1i(fYGJpvL=n1_!CakMHe>u+U8nOuF3j5fvq&OMtaLQR+c2XU6JujtBvcB^dK&Hdi^_H?#4@J)ZRNnYJ z)sXpQx^H`F{m%2zls0tC?6yPjNspn(GOedYXPTfJMfW&tZ(74XXCXj5ruATGc zqBw`Aj5c&6;yaYKE#<%{Rth~h7P$1efQ|h(++8E7>a4Vob<8&Z8(nV!R7cQ-i6$ht zJHg!@E-nFrdvJGmcL;EC3-0c6ad$56!QI{6ZTbJ*eYNk^+nVZ{K4K>dO8Pw(wqeEOS?5!)4&`IzJ7ewwyB*t*lcpo2LhH6prw z+n0&0NR?uiu4O(rT>P}>qKoGCg39~i$*#j26X^6`PoTk>iC;4R($>9%y|de*qGK-Q zs%-%KA76P3(W(&POl*yvoE=RJZ2nudGqgnfWG3WhC1xi6Z(WO+m6hXD_&*Oe7FOc_ zl>g{h0bImv%pAn59Gw4^0nD7l|F^>Y-z%Rsoc|{x$EP)bgM}Et%1z9{#!Sr4#r28A z!S)}#|BcGd%0|q^$^IYxr!9c(KYar@*ofIVKMOa2m;=D}srl3aSpIwdKS#^X&Hib@ zNzBf|_1`mqneB7*9G|xTQ_sr&IeGx#v)|ADKI>d8Z2z+z+y83+Y0LI`osFBDn2r7O z?*4=I*)J#irwxGnzc_5%oI1q+uLt;_@%;Az^6@c=Sy(%pI5LS@8#tT%GBL69-2Z+f?ir^Uu--~4_m7i4Op@s!+13J!84k&r zBI)G<-ULvt7fnzS$G_Uf1X;+^pa5oT9!7N`d?9-y4{(=<+6JU)sTLZ4*+YEzP*dt+gUm8%zIy3$bkOh)AlHW8XD7ibT4Cr>xj&*M*%G$r*)-UHT}04mJa)`wDou*Xe^zOJHzl;4Ezso0LA>T-zzq-1hXA=@9eQ-tlbnwvp@u2BK3&G3#dVVDt`lQx`pcu7W2g!FdYZ7x%*vLT$>@YNq! zf2v>a`=yhfPd0r|k%?joJB(~!b_SDpzQR?C|y%x86113f1A0 zN}Fo+?ttDYMIzxwcvtvpg5PZ+y9V9`>RyY(>(yos_qzT#kBLH!a2z9IJ$*#d@#O|P zG-SRXvyYRI9`wt*W&wY1M^AV@^S$`BSLA&ZpCo*4`ROV`)EFLaH9p8R4WY_;6o0ux zG?%legW-5h^n`iPo7Qvomc!K0Wjz6P4Sl@r zMBVOf*)=l~jiy-)qH}^IBY(oJD zPQ-v3A?Slws2OYhrQgE^g$(0ouCra>+()M_qNNjT`sb^Y&V}(xWW9GW)RdB5TuDRIpQ(#S zOsm;G;}=p~YE7&GZ9tt7j_T1RfHe_sAE9AP&EV2Zj()ZTgSYQ<(>pWc_f9hE?n!9Z z+L*w|E-`JoSkLhb&wly-$v&g)gKg~XWE|v0bK(sAA3tfsrKhhI1K8zYqLrsVHmf*3 znae)f0w0+`HbW=h>dq@u08Rt97E0;qd{Kz;$0w9>B?NkGm91s9dF>VT#uaVuV~2`l z;uwfTs_L7LrY1#8N^v%lrbY?6*p({f3ArS2EixE5#z`x*n)JF}5o)GQDk>&d%^*xn zP#^|_E_@lS-1tsIy~GlI@xHUsgh%n7vy$AyPr0JH$N)u+)Fj9Bey@Tt(<1|=lk`hp zqg2q+_F3Y&RiRg^PPjRXVS^#8bc=&fYX7Jv{oZ=G34H5_*2w4Y?S`^hRUWm(MA$W2 zzD$G z?t#ZzU1Pk!A1XyHE3ZzYwG-;J9rO^d1OR=FA{BiATxtpQePuK7yd5~Lwk+d99~ovAtQsBXrtErkAPZZzY>M=WbYG10Iw=OJ zLVN4tJtWh8GGs~E26kA=n$$@wT6#?Pn#4%(cLKR&j6F6@){*Hx8I-YL(09knHl^d9 z(3Ibr{qeta>+461Z5n?+rZT2N_{0^vi$Kp6iuC`?F3HS3#ogN{kZMYpWWby4QKC(R z=D{gB8+@U$*ZPh-fR^jcQyw5`2q(}|f?ka)*>5&wekGh)ILxsyZ!Pkf0R(VWff{t%^@mO;^1xBFzb&V^176ZlznZ`BefPR|FnN(06!&~#aJ;pt~4(8go@ZU=?<7r-MP**aTJYJvpBkX!Aq|Ym+2T+b#6GK zR!VP|g06hKPH;%6ij#&fqw6?X*7OkUp6MG6E>La)Ln~Enr=^scNmLS1B^+-pIU)H2IxA{>I_{?0RS;iV`%E%bT`l2nVT=bLl(jbh+ z5;RioY#8)7dNC*WE-|7coR(gC^ZRuBCzQ3;fr?SgX`svx>Ob>61(xgBuN^pTBXt6O z<)s(?l8sIdCR>?FmT*1BRUCz_nAm=_Rbo*#?$!3xdStWyJV@~zz!>d7S8OF*uh*s( zRdwi~3K_f&{AQy73qc+ZcDKyROF1WFli;k%IjQ5yN`zx%W@^>`TI} z3!s}%m{cDxhFAJ!5)%o8!)!82g!@eLrf|EEd*&r4*eYR9CA>q}J@pc8OB4(bJb?A1 zcn!KV13LlDU?&x*qEWIa`9vSl0Waix-T{|fTP)ywU@uS{1{s}@6rYq&!bRZcBN+`c z8WPGm)hX32$~oDp^rHBp^rFZmYOBvx3k;J%6O#b41F`}3mMvHgtke03-**^;cvG>3(6NHqIb2Ucg=^KbE#J!^si%CDAS6`&0e1f(ln#R8jxF@b_8j8xX7 z+F~kp1>1Nq$!M)G$td$m{t>X)sEp*=KOgzGyt8SD90&~v3>XX$4FCq1TW-KaASTcW zb`*9LCKFf)qyQp;xq+@=Lp|-U+ty%GurOEy$OdbMf`zh=zK^<(wvVz5QwIwIVu9(w zGGGL-GngH$EL_Lrijx<{9K@WuNy3hX3lk4>2jl_&0)H1~FyPA#W{y^nEg@A#qlMW6 zvI^7W0-2LGDKXFoP{h#1P{q*1P{O?jNc-%;%)%tOfBwo3k?o>6!YrZv+Gpco*(WWG z|0_B~&IR)W=q!v&lBiEr@MtJT8VAdvhv0Tdt~Uk)OiaKENc}4zLEMKf1LP8>?~w>4 z!GW2Y6~<^lksN^u$jTuDqJv>H1A=oXOJJnR*b-2Lr67gm{-XX0_^JQ>Z}%(ESD0wa z3k(Z(0J{PGP&yOSOg1FQ4E5r#>A=ZACYWsWXjB0*Z>hsi4|+_wMBNerLjxa5J085D z@V5WsL{QGm_efhd*#=zO3}D6VT#T!tNrhndz)PMjI{^{yZ9sM|#1-upCU{i&P8x_^ zT8mv$`#*h&_Ju9cEBcat>jxMWJOeB)Ss9 zI^G_8OHPlyvh5T}?^eC<)2+Ox8bY;vrqEHE9`mS3ZSO_pg;#eYT*+(;=s6XV2og+q zO;_3?X_n(+LCJTM^uVi7i9d` z;k*@PL#4eH$3yQrOO8S#d=%MGu%Ge94IB-thU7tf=9=*gH%#u zEGbin#5`d3P(}iehfRs3IK#0`I7j%Y+Z4{lmcksdM>471a#o`q@kT(@O*yNPj_4y% z)SNk|KbI;s^*f>VEECEV8gs2hThL74M@$pw6yE5KTHH%7#Mu}nxy8{aVIsh$&F>~V-gs7__v)B#W24m2RZ%A{kFKcuJ|~cPjsN=$!j}90Ods0csZx0&{z}@Tu)-Vx*@bC) z78ey62J5mG=s{H%UF2%NKEtfa@tZ z5@ZjZlnk^TvtkhsAQ%gtb(&})!vnt0dFH`mO zZE`9UZ)CMB%+XYASamv|*dx4iEYeV&JF+o}|GFW9lL5CGIxDf%jxU<_-T% zh7+HY+r(8px0#n_CPS9S#E-00UNiS1-eS+9vy5X4R}PON{rBMsu^2P6{Nf&si`4qM zb+#$)9=5M{4HLMNkC}ihhY4EwyU(J7S?;XrKGHADc24{^wCgPF1TBVQWR?N;3|80+ zJOwm@HS~I|aW?>k1r36tRxqf7cSLifE4W>iPNNssYOd{%#AfToDE8-`)^CNxYRFqc7LCw)-wMwz7j>dQIATm(Hu9d$SPHse;GhwD2i|L#~=joI<#r zXu%Dpptk8kO!1cb{^c-DhxnwHhKW_UCJyd~JasljHfgf+f6Pq-S-MxLBUNatv@(w} zM{01s6yIVsaK06ZgywojtJk+cyg9`95C0%!XvM?Bk50=%`6$4(Ghbt8(z=kf*i>_S zQ?4@Xz~)mb2Dq@fYB+JCOW}1WzV_E(blLBSQA?IwQL?jp*h!dIURCzuadutpAd)-d z)E79ZQqB9r zmgtg}dRP}F>=hqB#sp{M5Brf;f0*uk_(AVfq<$e;`TER>{H*ov@#sWw3iPoTx*QRAb7*8wbIYYPyT}q4scjd%dVmW&m?CDmK-1J`=>)+Sx zk&h)ru5?OTzS{mevnknYX}0BjchAN1u7otuK&U&qC0vtc;(O~`<3|3WbBG|--G|}3B%Z(+arq8y`kKQxW_wXp)c{=C0`Oh z+(oUzV;ZbI#H;(DnO!-%h??}xkXg*+1VdcrllSQWS9b0S^u8(fvOD$!Rm|0k6-1o_ z^8T3^Jk;64j;a?WGq3SQU`ohJKrue-;`UXy%%vwG4)sey!hZY+KcB*hWW+R#9*%Kl z7h>(!#uooDt1-V6zXgBRj?P#wXzYY*uF=j&qgH@v^e%ApvR;kloum>eJExFaFv)b= z$lY)A{q3hGlQ&#;&%*Q_j(7CQaPlSQK$p-sOXQn^SL?pk>l3s$^q>P&S4gK&P3O$- z=NzH~92_GE^xTi#HAxUTE1w~?y)3+mRFNTWk%_^yo1d_pv?6lBq2J%Ur&#vFf-wD9 zdbovA98+V5G2n?QgtW1#sflFZv?26w`V>Q>VS0+crhlbA$*=)N(J4Y6Ga4LP(Q436 ztk~-Z)!wSz!8N3_#s+-YJ7mlZT86N*J=W?lgL_0U@i`toNCbnxSF9$)ey)EAXd!uQ+O324ykDV1tKKWl_47SymqtWj`t zn=hgkhGS7=0xWShp??Zf86~pA zb-;z$Ww@E`-CBhpYGg!72KpM0q!?*WF%y|6c?m$-U)Zam&X7HW!LGj{nJJ`nybcPF zIVBb{wT3~e3`2>z3&j*-R0n-Al~ci1dj>@*&5wT-d{Suh%Nj0@n-g#nX(=ff1%eh5 zr#aCW&~^kFy?zlwO6rF+JzmYs)Dy+M5uK`p)Lk_aen6l9@=ea0T8`9Yu4WF@0o78J zc9Yhzbc|;O5FM?C*#gYffhAJ~l;kVcVYHyH){+B%LxGa0ge}mK{r&x@ETX-49-j55 z6{&33+m>EV8WmRikz6~mtL<~xL;_=xA!ZXfD;d^&1!;0;0|LG`ll4jQXZGyHI0)=^ zrFj5ynR<$)v!GraSyh=(+4_-I09@~7Mtk0`C~GOdRq|Ah-0rQhnBV4$ltB|5ly=6V zWx7|)Z7~d4nHi`I*oiz0@pnO@WhUV%2>ww%`9^=9y6jd<*W4 z&hZ%s@B26$ADRO$yN*njZyxnpW*tf&dtBw^Y=4xw7#zj+x5VVjteX-&B~#nV%npk&e2- zainLpdF&2rY2214DhYkI_Va4#MJ%>M zOH~&5nJY|FQgsy81w3RljV+6;g-k6q-^#?)L^L|(5_zv=?oE$VoJG18c4^OF7|U6C zD?hGNDt^E7FNeLynBcY`W}iwA`*yn9^AYnQ8R#2>^dY_UQ(WI|$!dk>dyCf9{xU=X z(z{;m>8PZQ&Ybu*w8ogsYYwJ{WuX16AkE7YN|-gjT$91UPx)X>`I}`{K};!zL2#nF z(WQzhmmu`d@QgBgJ6P$=+%GWEXYA0hm15+{U=|^`sZN4Qbhd__WuJ6x`r9p&RSRJg z38EYN#rnv#5aVs%kBhW^tg-<}du+o)n+B;&`z)-Hv>Xm>;CXEI)b(ZSfVc#&D?_U@ zj~`G`U)VB4Ts=`pgRHK8;!tUSm12g1vN$!6YhtZfCy$!!+gNMf3(WAJG7O2?U}6x; zBFot3z83OzG#}vKSX=u@*rnKU^YJ~|eK(5MP^)adj0@6Qb_7~^`*6sVa$E6?yE*H?BLDZ|mPG1t~tfqzg|(eEoGa?e^>KHX*_i*caAsrGGxTZO0$qx zK)uCTH}To5Mj5Z1rQ9!CzCmlybgJYBa4M!(OqXK7wGR=(uM2H*TlC#;=TI){)>lKi zNt!$sm=EVny&_%^%bQe^wfj8Cn{v$seIp=Ew)xehe0SDpYJq-Jpj%^8@;5s(#dbO; z&=&sww9o8#(YZEw8{a!zyoYXVWqE|VGcw^oJ7#fbI@#Sg`QY>J`^WCFrG;zkz{}~* zgU5FYJIZx$@94&U@#Vb%l)>u3F%X04-mTB^HvD7H>=&OwHJ|VNU+YpX@yx%OaTx?v zsLxEXqA7Lpakb;9h99aznTNtY0jx>aotV13PDWLf4dh)C5g%Fl$_i9{L1lv7Vw6v`LE?E0oY1w>G zB`v!!fDRTk7`ESDzF;Rl zndbRq-HPN+$o*N!m&)G!Ey5;VQ)dMhT=|fPR?r=bkQot9jPpP5PBqQ2h)1EDra9I_ z3rWn(ZR9bdP)Uq$2NNkcf&P0dN@w>u4VEJ4;=881l;+0L`7@5IKjH&|d-MDI+Rb#RZ zTdGWH&%(g68$IQ-VJbx|Z?vPCawXKzY~Q~sp?Cw?e)3vJaYeBXmOltZ!Pm!FYGyG^ zp_7%F9r~^|t{w-`rU$pJEQ%zKLI_i3b4!>rA>6Cc<_mq?@cS}Drr2X`roNp$85qes z>}GwXAdC5wNS6DtZG7>2^U3MwA9!Y5y^}u%uz}ZQ{Wuo7kM0VHGy_i(>NkAI z33`#P*P<`_-=I~TWt75_Zvs~r>>SoH&Nn60F4=xOR&$6UPDjzr_&ejq{)x0@>%n%I*(2#YcXWDR$1}* zlx7|aqqt4EvQL5;wBGnJ$pEpW1aj%aDnEFRuBEtHNt%j>H=>JxPs`kA){zKhtZ+1zl)3|#!Ae`k!Lx<4I$UCYMBR|jxX@kFcIxz5GBw?NkO~`SfNfI|Z*$yt1ll;`}^-0`vhC$Y*Eb;H_e= z$!Q=irl$+{seSd2D7(E!JpxTfm%*ux+R$cd<|>>hzs0&oBc{7gWliL8)0uIpi_zDDw=@Zv?Q+oI=!Az-sHB^onr@pF?+=o$?fb#L- zgy8JqE`nXvc__UhE-2k2{0YSN>8Arrp1n0WdvWD|!6i7ahR`9T$Slz~oc-K>gJ6Tg zgLPJ3P-A^}PC|qtPX~V&t=oM-bNh1pYuc78=r=m)&A?LR7Rx+Wrq|tiAvS-lErP9Q zuzfy*D-d4CZUs}tEJm7TWt>(C>Y)i&TRba?34#}+C-JLQsjMh8FtypK8Hm(GJFS_^ zCvj$8AOjSVCW>tAs@m8n`2sAIm7XND$j_JH^nrC@ro7^YJV9a~OMaxbbwE1xG574G7q~b=;;EuKJaZ=64?A?BQ=0KS{|z zsjn-i(cT)!O&Ka6s0NY-dgH7(Y_vEo%0Ad(a))aO5lWAE=BJ=VeT-hd-A%KguuS7WB;SRhLeU|5 zzRL{Bd@0{hbFq_V(E3w1_IgtQ)>B&mX}NSdl^xHQmaQZRlo^U-4$AO`jufHIyOr50 zz`B*6E5XvLh`CGY_ULD$!g_!Y;8xoG$g$Ezt0S;F7Jl*G>Kgz1poxpM{?$Xp(w?a% z)>@hF>Iyk|acX$8e~=Iq8~WbWWGg^#e(m^s8DwQ}f~D=RX-friZ|C~hhCdo@Rc*Yj zPtv-h%%m=H-X9>iO1d)QWU^ZS0O5sPEGxZ3U$yG&sRj8!`0y$(|7&1fIC8Kg;1+Oe zT(P|JJe7r(lZh5|Tv<-4X>*g}l-p(6z!%$ipjgN1Ea*&Sk5%lawZ-cx@K~t1j)UmM z80S;Y_e*I9f>#7k{of*EmDs_UCVf?Tp647 zCPNb>XT_wBwQ78cVKN`Y6pV1qnkD4Ur=6^^%TllBcG>!O$?_gDRASof0^g}RwT0^QQ=ghcWhKpiM1X}Vqg}P29 z-f_Pm07MrnrA26qDgkf9t+ip=5xv}ZGV!Y*>N*g@#;E_Pl2N=D?tRw;*}(hEGu-d; zK-|;V%5r>woHZo

Gh%qA_vzk8~{Ii>scB9X0wJ~KygMh!8qPfS!Q8mc7)A#jQ-{`f? zh|I5x(|VF-5-Hd!(1XIIO|Yf3fGnhFMW^m#bxBh}Z}YIdth%$i#dZPg*RPupiyOCyb?5QQC5EI&Jmm}`pu(Fi*vQM zVJwF!^KGV8POqB8>rTv0a;@LSWG`SjmC9s^wwyo6fFu7M#XDn=rK^Peo8-nc^(l|0 zMjQvlsy)K_ud=!|)G6_ioCuXhfVQ z%DdRg#wi(3h(UX8R&h>2y9Xok^}3u(vFYj7x3}9PjcH>I<&3_Zsc}5=p%v!GytCs2 zr#@j#N5yk^%&{XRR&jJnwp*xiLfR>MKO{Ih_WVO9=V_%sFo4;gsf}Nk^CC*+?h(uw zpk;#zo0T2SZjwNwNp@?~>{M;;UnU78;IQ^i@J_TAn5>9}x0jZ9kJkROXD7t#Nb+LB z#NZ>Q!3@;C_z3*|k(SqlPd8#KYebbyW?A@F<$m1WQ5G(%)Vw+VOyWN!`-=B6vB zWD$j&3s8+;lk`&VMr-N&?i|mz^;lEO%GuruO_l`XaDY1}3i@Gn<}?mJ@q@BKzjxl- z8k=s?0o%65x^z^?IkvIbdcv@I{`awK1o96yx`^;{NBrfbY#mF{vYEm?WehB3lk|%D zB{%aS<1zn>348#Xk7eWGwd&(JUj54MW~rD}rPKY^UriH&T(FeDlrXm_w8dN zW$e`t@Vx2Y#$HOu8xx{^>pK`+R+_%;Yb?#TH&%2uSa&d~T+l?cAj;RS88v>3Jik@L zy#Km0?1jk8*sq}`1DdKU(o)Z|s6Uv)NYK%P=ig)FUvjd#5m}f-t zX!4OQ>?q0a;I}{XceRkq4(K?I`+9hdapgyDj7VcOEGhcI?WVgVarT@O>nUfV zxBmK-><*&gCxK$*%*p1r@|-AXSCoNAB=91b;Je>1JDc);2?Fr`{w@K_8FZE&0X!ULvbq#FQjvn#s3s~O$OB$Dt-_GzjLfqKoKWx0N%B1ulZ*J{MD%F*a^9}}y zo*sFuT&cb8pLd4}o=s{E`ofd2i(R~558Xwqm4XsIo+m3TLG7N%H@aqB#94~YDYv?H zQ9}D2Nq=eg16$xUqecUlXtk(I|DZhZz1iGlc=JE-*$}+eJnF8W=xGiF0F*qs7?;ZU z02gPSwDQVE0$O+mxaH?htB8>0YE4PFKBB)>YZmNN;dyy8XYt+!GvGRz!E5St89?*j zv32rvzNekC;Y6e2gj*z?(Oeagd_k&wPNbCEO}Mp)27%^Sh-0#SI1mpOPJJk_jhLD` zzsn?tbjk z4_hf4X-;PmUE`%VC2S~rUJZ{zr{<0%2B|8RbEarhyyEwcf+4HzD3~TM>Vf;NnyTW= z=!!w+huQ>$L&3?XE~p#{^O7zBLrvlpvh`tS2SqmwaZc7=1>-hGR%v~*Hna~xEw+$v z)L!H|-toq2YX4k2;XfD_|Aa|=^f$agzOaIWf;)LR)O4FFS8aYD$#@zu*EVo8QT|n} zZr?eM-h)i!6|5;VHY%7cRSL_SFPOpRs82pnm1+du_;X%I+6^g^!|=ToE7Dt#Yn zd9uH7GEprqj1*kc$Yj^*TT2!aFP`j*p^t_NlCGTDE1E!fMmqo85M%0M^~5gR%##YS zZabD6?eAvc_;6mrK;KHT=>Z3Gu53xL0Iks7UFQ3^7aQpaR5T|Q>uNL*Yrw@O0`Ky~_653&YXHYDPKPH>CS z1o?v}e|wA3(@&eD^FxBN?w;?4jVgMGS72|0I%;|M;CXTNHLK1f-wShlNG`UjS+QHR zmWXD}MMZ@S^##(jMKp3g*Q=jlqs{>h3}zmpqE1<|cWwcfG>L$&mOMx9&W;%9 z6;qu43s^9xXq}+80?OwOkWaq)6$n4o;2Fg2H8C11-DKe;UB9b-k8#s|oUPnaWvC+c z_%NEJ(k090MLXrr(pyz?4Pm-x_IiBErpXH~-|!2rq+hq!uK9!JX=r(+4ASBtm_QxSHlf88( z-WdHW&g}U$?G=nGWzPeg%1L9#anqJeb034;{CAwn3G>Dpvu-}J>`$W*g#bd!R}(;5 zj^=DSqVv;fK2)8qvev5WGx1wluh~>6Zk@qBjbk=dkLrS2BB7UQT(SYXg#A>U>hLAw zmW8fSHd2r8SEuaXe-HU0O6lp#3s9UYv9lRog6bwRm&W=ET6I#D)haikAt$mEqjVJI z^xradm>;#5{8Saa5%tX$UbnbAjU}CaBU4?^FeHcuEj&`bJj}3(cFg_a9LsX_oOKU| z;Z9<&Q!VTb^%U$7iutj-K4w@Y(8aYoBr{nJUv`}~_Gd7s#-y2cx|WUA8k^~O_3K!h zU%a~r@v#6GZ9n;o!8TS==r3(B!C=&Jz%9~>X02hrlb~vQ)$U)Ki7FbM>qapA>?XV+ z>j9fW7foAHNeRzN1;@cG7WRUqX`Ql~wsyKv(ML+gC+$W0%or|c$->vn$ib&_E=@~M zd-|_g!~PY3V)B&fkkbN5lB)7zX(+*dkR@a)UdUQLE9hr2-3a`n73Q!mJ5?X2OEkj5 zV1uh&r6Aje*c`NV%N(RfBKLf0USgC>>I_tb+_+`bAoOxr4bd;^+)eU8&N>KsqnaCgWUeXjODL&qU0w~>KP!D^fp2F=y?k|&g z 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

fMIynUm~-fKz71k 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

bKhQ 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 literal 0 HcmV?d00001 diff --git a/models/bariatricData.m b/models/bariatricData.m new file mode 100644 index 0000000..79b0209 --- /dev/null +++ b/models/bariatricData.m @@ -0,0 +1,251 @@ +% +% time [min] +% + +% data.t = [0 15 30 45 60 90 120 180 240]; + +data.t2d_pre.t = [0 15 30 45 60 90 120 180 240]; +data.t2d_1wk.t = [0 15 30 45 60 90 120 180 240]; +data.t2d_3mo.t = [0 15 30 45 60 90 120 180 240]; +data.t2d_1y.t = [0 15 30 45 60 90 120 180 240]; +data.ngt_pre.t = [0 15 30 45 60 90 120 180 240]; +data.ngt_1wk.t = [0 15 30 45 60 90 120 180 240]; +data.ngt_3mo.t = [0 15 30 45 60 90 120 180 240]; +data.ngt_1y.t = [0 15 30 45 60 90 120 180 240]; + +% +% body weight +% + +data.t2d_pre.m_mean = 128.8; +data.t2d_pre.m_std = 13.9; +data.t2d_1wk.m_mean = 127; +data.t2d_1wk.m_std = 13.1; +data.t2d_3mo.m_mean = 112.1; +data.t2d_3mo.m_std = 15.0; +data.t2d_1y.m_mean = 100.8; +data.t2d_1y.m_std = 19.5; +data.ngt_pre.m_mean = 126.6; +data.ngt_pre.m_std = 15.4; +data.ngt_1wk.m_mean = 123.5; +data.ngt_1wk.m_std = 14.7; +data.ngt_3mo.m_mean = 105.5; +data.ngt_3mo.m_std = 13.0; +data.ngt_1y.m_mean = 94.7; +data.ngt_1y.m_std = 16.0; + +% +% glucose +% + +% t2d fasting [mmol/L] +data.t2d_pre.glucose_ss_mean = 8.8; +data.t2d_pre.glucose_ss_std = 2.3; + +data.t2d_1wk.glucose_ss_mean = 7.0; +data.t2d_1wk.glucose_ss_std = 1.2; + +data.t2d_3mo.glucose_ss_mean = 6.8; +data.t2d_3mo.glucose_ss_std = 1.6; + +data.t2d_1y.glucose_ss_mean = 6.2; +data.t2d_1y.glucose_ss_std = 1.6; + +% ngt fasting [mmol/L] +data.ngt_pre.glucose_ss_mean = 5.5; +data.ngt_pre.glucose_ss_std = 0.6; + +data.ngt_1wk.glucose_ss_mean = 5.0; +data.ngt_1wk.glucose_ss_std = 0.6; + +data.ngt_3mo.glucose_ss_mean = 4.9; +data.ngt_3mo.glucose_ss_std = 0.4; + +data.ngt_1y.glucose_ss_mean = 4.9; +data.ngt_1y.glucose_ss_std = 0.3; + +% t2d post-prandial [mM] +data.t2d_pre.glucose_mean = [8.77244 8.85589 9.99010 11.35133 12.11621 12.22632 11.39915 9.31906 7.86372]; +data.t2d_pre.glucose_max = [9.44681 9.59575 10.80851 12.14894 12.82979 13.08511 12.31915 10.27660 8.74468]; +data.t2d_pre.glucose_std = data.t2d_pre.glucose_max - data.t2d_pre.glucose_mean; +data.t2d_pre.glucose_diff = [0 diff(data.t2d_pre.glucose_mean)]./[1 diff(data.t2d_pre.t)]; + +data.t2d_1wk.glucose_mean = [6.81301 7.52126 9.08133 10.64139 11.09391 9.44337 8.13344 6.70645 6.10303]; +data.t2d_1wk.glucose_max = [7.31915 8.08511 9.63830 11.27660 11.74468 10.19149 8.89362 7.36170 6.61702]; +data.t2d_1wk.glucose_std = data.t2d_1wk.glucose_max - data.t2d_1wk.glucose_mean; +data.t2d_1wk.glucose_diff = [0 diff(data.t2d_1wk.glucose_mean)]./[1 diff(data.t2d_1wk.t)]; + +data.t2d_3mo.glucose_mean = [6.81301 7.46447 9.81966 11.18089 10.32723 7.96670 6.82716 5.99661 5.64872]; +data.t2d_3mo.glucose_max = [7.31915 8.08511 10.74468 12.04255 11.10638 8.74468 7.55319 6.57447 6.21277]; +data.t2d_3mo.glucose_std = data.t2d_3mo.glucose_max - data.t2d_3mo.glucose_mean; +data.t2d_3mo.glucose_diff = [0 diff(data.t2d_3mo.glucose_mean)]./[1 diff(data.t2d_3mo.t)]; + +data.t2d_1y.glucose_mean = [6.15993 7.46441 9.99005 11.09575 9.81607 7.31356 6.23081 5.34337 5.08072]; +data.t2d_1y.glucose_max = [6.72340 8.08511 10.76596 12.06383 10.61702 8.06383 6.87234 5.87234 5.53191]; +data.t2d_1y.glucose_std = data.t2d_1y.glucose_max - data.t2d_1y.glucose_mean; +data.t2d_1y.glucose_diff = [0 diff(data.t2d_1y.glucose_mean)]./[1 diff(data.t2d_1y.t)]; + +% ngt post-prandial [mM] +data.ngt_pre.glucose_mean = [5.48956 5.82918 6.53877 6.90695 6.44993 5.87725 5.58912 5.24061 4.86354]; +data.ngt_pre.glucose_max = [5.68950 6.20091 6.92542 7.37291 6.92542 6.15830 5.83866 5.49772 5.17808]; +data.ngt_pre.glucose_std = data.ngt_pre.glucose_max - data.ngt_pre.glucose_mean; +data.ngt_pre.glucose_diff = [0 diff(data.ngt_pre.glucose_mean)]./[1 diff(data.ngt_pre.t)]; + +data.ngt_1wk.glucose_mean = [4.92040 5.77227 6.88029 7.64674 7.61655 6.04798 5.19070 4.95606 4.83503]; +data.ngt_1wk.glucose_max = [5.43379 6.43531 7.33029 8.03349 7.99087 6.45662 5.34855 5.34855 5.11416]; +data.ngt_1wk.glucose_std = data.ngt_1wk.glucose_max - data.ngt_1wk.glucose_mean; +data.ngt_1wk.glucose_diff = [0 diff(data.ngt_1wk.glucose_mean)]./[1 diff(data.ngt_1wk.t)]; + +data.ngt_3mo.glucose_mean = [4.94885 6.25601 8.07541 8.35817 6.93362 4.39752 4.22316 4.64295 4.66440]; +data.ngt_3mo.glucose_max = [5.47641 6.56317 8.67276 8.90715 7.58600 4.79452 4.56012 4.87976 5.05023]; +data.ngt_3mo.glucose_std = data.ngt_3mo.glucose_max - data.ngt_3mo.glucose_mean; +data.ngt_3mo.glucose_diff = [0 diff(data.ngt_3mo.glucose_mean)]./[1 diff(data.ngt_3mo.t)]; + +data.ngt_1y.glucose_mean = [4.94885 6.25601 8.21763 8.61427 6.39292 4.11297 4.22332 4.55784 4.66440]; +data.ngt_1y.glucose_max = [5.54033 6.60578 8.67276 8.90715 6.94673 4.45358 4.53881 4.92237 4.92237]; +data.ngt_1y.glucose_std = data.ngt_1y.glucose_max - data.ngt_1y.glucose_mean; +data.ngt_1y.glucose_diff = [0 diff(data.ngt_1y.glucose_mean)]./[1 diff(data.ngt_1y.t)]; + +% +% insulin +% + +% t2d fasting [nmol/L] +data.t2d_pre.insulin_ss_mean = 125/1000; +data.t2d_pre.insulin_ss_std = 77/1000; + +data.t2d_1wk.insulin_ss_mean = 73/1000; +data.t2d_1wk.insulin_ss_std = 32/1000; + +data.t2d_3mo.insulin_ss_mean = 58/1000; +data.t2d_3mo.insulin_ss_std = 35/1000; + +data.t2d_1y.insulin_ss_mean = 47/1000; +data.t2d_1y.insulin_ss_std = 27/1000; + +% ngt fasting [nmol/L] +data.ngt_pre.insulin_ss_mean = 82/1000; +data.ngt_pre.insulin_ss_std = 28/1000; + +data.ngt_1wk.insulin_ss_mean = 49/1000; +data.ngt_1wk.insulin_ss_std = 14/1000; + +data.ngt_3mo.insulin_ss_mean = 43/1000; +data.ngt_3mo.insulin_ss_std = 14/1000; + +data.ngt_1y.insulin_ss_mean = 36/1000; +data.ngt_1y.insulin_ss_std = 16/1000; + +% t2d post-prandial [nM] +data.t2d_pre.insulin_mean = [0.13170 0.15222 0.29688 0.38983 0.39742 0.35831 0.27523 0.17372 0.11100]; +data.t2d_pre.insulin_max = [0.16265 0.19105 0.37952 0.49828 0.50861 0.41824 0.32272 0.20912 0.14200]; +data.t2d_pre.insulin_std = data.t2d_pre.insulin_max - data.t2d_pre.insulin_mean; +data.t2d_pre.insulin_rel = data.t2d_pre.insulin_mean - data.t2d_pre.insulin_mean(1); + +data.t2d_1wk.insulin_mean = [0.05411 0.14963 0.29947 0.53983 0.53191 0.26261 0.14850 0.08320 0.07738]; +data.t2d_1wk.insulin_max = [0.08778 0.18847 0.38210 0.68158 0.69707 0.31239 0.17040 0.10843 0.10069]; +data.t2d_1wk.insulin_std = data.t2d_1wk.insulin_max - data.t2d_1wk.insulin_mean; +data.t2d_1wk.insulin_rel = data.t2d_1wk.insulin_mean - data.t2d_1wk.insulin_mean(1); + +data.t2d_3mo.insulin_mean = [0.05153 0.17291 0.45206 0.72604 0.58363 0.23158 0.10712 0.05734 0.05152]; +data.t2d_3mo.insulin_max = [0.08778 0.19105 0.53184 0.86231 0.69707 0.28399 0.14716 0.08262 0.07229]; +data.t2d_3mo.insulin_std = data.t2d_3mo.insulin_max - data.t2d_3mo.insulin_mean; +data.t2d_3mo.insulin_rel = data.t2d_3mo.insulin_mean - data.t2d_3mo.insulin_mean(1); + +data.t2d_1y.insulin_mean = [0.04894 0.14446 0.37447 0.58897 0.42328 0.15141 0.07351 0.04182 0.03342]; +data.t2d_1y.insulin_max = [0.08778 0.18847 0.44148 0.68675 0.53959 0.18847 0.09811 0.06454 0.05680]; +data.t2d_1y.insulin_std = data.t2d_1y.insulin_max - data.t2d_1y.insulin_mean; +data.t2d_1y.insulin_rel = data.t2d_1y.insulin_mean - data.t2d_1y.insulin_mean(1); + +% ngt post-prandial [nM] +data.ngt_pre.insulin_mean = [0.04339 0.14100 0.41646 0.51149 0.41065 0.25279 0.14389 0.07045 0.04854] +data.ngt_pre.insulin_max = [0.09840 0.22032 0.49717 0.58856 0.47105 0.36513 0.18173 0.09899 0.07492]; +data.ngt_pre.insulin_std = data.ngt_pre.insulin_max - data.ngt_pre.insulin_mean; +data.ngt_pre.insulin_rel = data.ngt_pre.insulin_mean - data.ngt_pre.insulin_mean(1); + +data.ngt_1wk.insulin_mean = [0.05886 0.14358 0.42161 0.68674 0.64776 0.26827 0.07688 0.05756 0.04082]; +data.ngt_1wk.insulin_max = [0.09840 0.20623 0.49952 0.83270 0.76448 0.36278 0.09958 0.07551 0.05614]; +data.ngt_1wk.insulin_std = data.ngt_1wk.insulin_max - data.ngt_1wk.insulin_mean; +data.ngt_1wk.insulin_rel = data.ngt_1wk.insulin_mean - data.ngt_1wk.insulin_mean(1); + +data.ngt_3mo.insulin_mean = [0.05887 0.27760 0.93965 1.32333 1.01117 0.20897 0.07433 0.04210 0.03309]; +data.ngt_3mo.insulin_max = [0.10075 0.31656 1.14271 1.62612 1.29264 0.36043 0.09723 0.06143 0.04440]; +data.ngt_3mo.insulin_std = data.ngt_3mo.insulin_max - data.ngt_3mo.insulin_mean; +data.ngt_3mo.insulin_rel = data.ngt_3mo.insulin_mean - data.ngt_3mo.insulin_mean(1); + +data.ngt_1y.insulin_mean = [0.05371 0.25183 0.60202 0.89293 0.45703 0.06981 0.03308 0.02664 0.01761]; +data.ngt_1y.insulin_max = [0.09840 0.23910 0.67792 1.02049 0.53912 0.09048 0.06201 0.04030 0.03267]; +data.ngt_1y.insulin_std = data.ngt_1y.insulin_max - data.ngt_1y.insulin_mean; +data.ngt_1y.insulin_rel = data.ngt_1y.insulin_mean - data.ngt_1y.insulin_mean(1); + +% +% c-peptide +% + +% t2d fasting [nmol/L] +data.t2d_pre.cpeptide_ss_mean = 1483/1000; +data.t2d_pre.cpeptide_ss_std = 543/1000; + +data.t2d_1wk.cpeptide_ss_mean = 1175/1000; +data.t2d_1wk.cpeptide_ss_std = 595/1000; + +data.t2d_3mo.cpeptide_ss_mean = 1049/1000; +data.t2d_3mo.cpeptide_ss_std = 501/1000; + +data.t2d_1y.cpeptide_ss_mean = 796/1000; +data.t2d_1y.cpeptide_ss_std = 345/1000; + +% ngt fasting [nmol/L] +data.ngt_pre.cpeptide_ss_mean = 1098/1000; +data.ngt_pre.cpeptide_ss_std = 227/1000; + +data.ngt_1wk.cpeptide_ss_mean = 834/1000; +data.ngt_1wk.cpeptide_ss_std = 187/1000; + +data.ngt_3mo.cpeptide_ss_mean = 816/1000; +data.ngt_3mo.cpeptide_ss_std = 191/1000; + +data.ngt_1y.cpeptide_ss_mean = 602/1000; +data.ngt_1y.cpeptide_ss_std = 198/1000; + +% t2d post-prandial [nM] +data.t2d_pre.cpeptide_mean = [1.56164 1.59817 1.94521 2.23744 2.48402 2.72146 2.70320 2.27397 1.78995]; +data.t2d_pre.cpeptide_max = [1.73183 1.77682 2.21394 2.54165 2.75994 2.90467 2.93090 2.53652 2.02361]; +data.t2d_pre.cpeptide_std = data.t2d_pre.cpeptide_max - data.t2d_pre.cpeptide_mean; +data.t2d_pre.cpeptide_rel = data.t2d_pre.cpeptide_mean - data.t2d_pre.cpeptide_mean(1); + +data.t2d_1wk.cpeptide_mean = [1.12329 1.45205 2.01826 2.94977 3.36073 2.92237 2.42922 1.86301 1.58904]; +data.t2d_1wk.cpeptide_max = [1.38532 1.58535 2.38721 3.24378 3.88151 3.34236 2.75766 2.09883 1.76829]; +data.t2d_1wk.cpeptide_std = data.t2d_1wk.cpeptide_max - data.t2d_1wk.cpeptide_mean; +data.t2d_1wk.cpeptide_rel = data.t2d_1wk.cpeptide_mean - data.t2d_1wk.cpeptide_mean(1); + +data.t2d_3mo.cpeptide_mean = [1.04110 1.38813 2.37443 3.06849 3.44292 2.54795 2.08219 1.44292 1.26027]; +data.t2d_3mo.cpeptide_max = [1.36712 1.59445 2.69723 3.48086 3.89064 2.83172 2.34732 1.67026 1.44002]; +data.t2d_3mo.cpeptide_std = data.t2d_3mo.cpeptide_max - data.t2d_3mo.cpeptide_mean; +data.t2d_3mo.cpeptide_rel = data.t2d_3mo.cpeptide_mean - data.t2d_3mo.cpeptide_mean(1); + +data.t2d_1y.cpeptide_mean = [0.77626 1.29680 2.18265 2.85845 2.73973 1.98174 1.63470 1.11416 0.88584]; +data.t2d_1y.cpeptide_max = [1.00234 1.54885 2.35072 3.22554 3.02438 2.20255 1.85494 1.25992 0.97496]; +data.t2d_1y.cpeptide_std = data.t2d_1y.cpeptide_max - data.t2d_1y.cpeptide_mean; +data.t2d_1y.cpeptide_rel = data.t2d_1y.cpeptide_mean - data.t2d_1y.cpeptide_mean(1); + +% ngt post-prandial [nM] +data.ngt_pre.cpeptide_mean = [1.13338 1.44380 2.21150 2.68655 2.65853 2.22752 1.86966 1.43750 1.08765]; +data.ngt_pre.cpeptide_max = [1.18826 1.55354 2.37618 2.82374 2.83232 2.42874 2.09832 1.61126 1.17911]; +data.ngt_pre.cpeptide_std = data.ngt_pre.cpeptide_max - data.ngt_pre.cpeptide_mean; +data.ngt_pre.cpeptide_rel = data.ngt_pre.cpeptide_mean - data.ngt_pre.cpeptide_mean(1); + +data.ngt_1wk.cpeptide_mean = [0.84069 1.34317 2.39446 3.39996 3.52744 2.72141 1.80563 1.28200 1.03279]; +data.ngt_1wk.cpeptide_max = [0.94132 1.55353 2.69629 3.89386 4.00305 3.19703 2.08917 1.35517 1.09681]; +data.ngt_1wk.cpeptide_std = data.ngt_1wk.cpeptide_max - data.ngt_1wk.cpeptide_mean; +data.ngt_1wk.cpeptide_rel = data.ngt_1wk.cpeptide_mean - data.ngt_1wk.cpeptide_mean(1); + +data.ngt_3mo.cpeptide_mean = [0.84986 1.87369 3.55603 5.00970 4.76219 2.71229 1.60441 1.04421 0.88643]; +data.ngt_3mo.cpeptide_max = [0.94131 1.99256 3.93105 5.68653 5.39328 2.46532 1.88796 1.18141 0.95961]; +data.ngt_3mo.cpeptide_std = data.ngt_3mo.cpeptide_max - data.ngt_3mo.cpeptide_mean; +data.ngt_3mo.cpeptide_rel = data.ngt_3mo.cpeptide_mean - data.ngt_3mo.cpeptide_mean(1); + +data.ngt_1y.cpeptide_mean = [0.59376 1.44378 2.81516 4.03105 3.30792 1.52325 1.09224 0.69665 0.55716]; +data.ngt_1y.cpeptide_max = [0.80413 1.55354 3.08958 4.37860 3.72866 1.69704 1.22029 0.77898 0.61205]; +data.ngt_1y.cpeptide_std = data.ngt_1y.cpeptide_max - data.ngt_1y.cpeptide_mean; +data.ngt_1y.cpeptide_rel = data.ngt_1y.cpeptide_mean - data.ngt_1y.cpeptide_mean(1); \ No newline at end of file diff --git a/models/bariatricData.mat b/models/bariatricData.mat new file mode 100644 index 0000000000000000000000000000000000000000..5773e82c4b53a771b843b87a411e4b065da38a3a GIT binary patch literal 9770 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 BUpD{% literal 0 HcmV?d00001 diff --git a/models/bariatricData_basal.m b/models/bariatricData_basal.m new file mode 100644 index 0000000..0204d4d --- /dev/null +++ b/models/bariatricData_basal.m @@ -0,0 +1,251 @@ +% +% time [min] +% + +% data.t = [0 15 30 45 60 90 120 180 240]; + +data.t2d_pre.t = [-45 -30 -15 0 15 30 45 60 90 120 180 240]; +data.t2d_1wk.t = [-45 -30 -15 0 15 30 45 60 90 120 180 240]; +data.t2d_3mo.t = [-45 -30 -15 0 15 30 45 60 90 120 180 240]; +data.t2d_1y.t = [-45 -30 -15 0 15 30 45 60 90 120 180 240]; +data.ngt_pre.t = [-45 -30 -15 0 15 30 45 60 90 120 180 240]; +data.ngt_1wk.t = [-45 -30 -15 0 15 30 45 60 90 120 180 240]; +data.ngt_3mo.t = [-45 -30 -15 0 15 30 45 60 90 120 180 240]; +data.ngt_1y.t = [-45 -30 -15 0 15 30 45 60 90 120 180 240]; + +% +% body weight +% + +data.t2d_pre.m_mean = 128.8; +data.t2d_pre.m_std = 13.9; +data.t2d_1wk.m_mean = 127; +data.t2d_1wk.m_std = 13.1; +data.t2d_3mo.m_mean = 112.1; +data.t2d_3mo.m_std = 15.0; +data.t2d_1y.m_mean = 100.8; +data.t2d_1y.m_std = 19.5; +data.ngt_pre.m_mean = 126.6; +data.ngt_pre.m_std = 15.4; +data.ngt_1wk.m_mean = 123.5; +data.ngt_1wk.m_std = 14.7; +data.ngt_3mo.m_mean = 105.5; +data.ngt_3mo.m_std = 13.0; +data.ngt_1y.m_mean = 94.7; +data.ngt_1y.m_std = 16.0; + +% +% glucose +% + +% t2d fasting [mmol/L] +data.t2d_pre.glucose_ss_mean = 8.8; +data.t2d_pre.glucose_ss_std = 2.3; + +data.t2d_1wk.glucose_ss_mean = 7.0; +data.t2d_1wk.glucose_ss_std = 1.2; + +data.t2d_3mo.glucose_ss_mean = 6.8; +data.t2d_3mo.glucose_ss_std = 1.6; + +data.t2d_1y.glucose_ss_mean = 6.2; +data.t2d_1y.glucose_ss_std = 1.6; + +% ngt fasting [mmol/L] +data.ngt_pre.glucose_ss_mean = 5.5; +data.ngt_pre.glucose_ss_std = 0.6; + +data.ngt_1wk.glucose_ss_mean = 5.0; +data.ngt_1wk.glucose_ss_std = 0.6; + +data.ngt_3mo.glucose_ss_mean = 4.9; +data.ngt_3mo.glucose_ss_std = 0.4; + +data.ngt_1y.glucose_ss_mean = 4.9; +data.ngt_1y.glucose_ss_std = 0.3; + +% t2d post-prandial [mM] +data.t2d_pre.glucose_mean = [8.77244 8.77244 8.77244 8.77244 8.85589 9.99010 11.35133 12.11621 12.22632 11.39915 9.31906 7.86372]; +data.t2d_pre.glucose_max = [9.44681 9.44681 9.44681 9.44681 9.59575 10.80851 12.14894 12.82979 13.08511 12.31915 10.27660 8.74468]; +data.t2d_pre.glucose_std = data.t2d_pre.glucose_max - data.t2d_pre.glucose_mean; +data.t2d_pre.glucose_diff = [0 diff(data.t2d_pre.glucose_mean)]./[1 diff(data.t2d_pre.t)]; + +data.t2d_1wk.glucose_mean = [6.81301 6.81301 6.81301 6.81301 7.52126 9.08133 10.64139 11.09391 9.44337 8.13344 6.70645 6.10303]; +data.t2d_1wk.glucose_max = [7.31915 7.31915 7.31915 7.31915 8.08511 9.63830 11.27660 11.74468 10.19149 8.89362 7.36170 6.61702]; +data.t2d_1wk.glucose_std = data.t2d_1wk.glucose_max - data.t2d_1wk.glucose_mean; +data.t2d_1wk.glucose_diff = [0 diff(data.t2d_1wk.glucose_mean)]./[1 diff(data.t2d_1wk.t)]; + +data.t2d_3mo.glucose_mean = [6.81301 6.81301 6.81301 6.81301 7.46447 9.81966 11.18089 10.32723 7.96670 6.82716 5.99661 5.64872]; +data.t2d_3mo.glucose_max = [7.31915 7.31915 7.31915 7.31915 8.08511 10.74468 12.04255 11.10638 8.74468 7.55319 6.57447 6.21277]; +data.t2d_3mo.glucose_std = data.t2d_3mo.glucose_max - data.t2d_3mo.glucose_mean; +data.t2d_3mo.glucose_diff = [0 diff(data.t2d_3mo.glucose_mean)]./[1 diff(data.t2d_3mo.t)]; + +data.t2d_1y.glucose_mean = [6.15993 6.15993 6.15993 6.15993 7.46441 9.99005 11.09575 9.81607 7.31356 6.23081 5.34337 5.08072]; +data.t2d_1y.glucose_max = [6.72340 6.72340 6.72340 6.72340 8.08511 10.76596 12.06383 10.61702 8.06383 6.87234 5.87234 5.53191]; +data.t2d_1y.glucose_std = data.t2d_1y.glucose_max - data.t2d_1y.glucose_mean; +data.t2d_1y.glucose_diff = [0 diff(data.t2d_1y.glucose_mean)]./[1 diff(data.t2d_1y.t)]; + +% ngt post-prandial [mM] +data.ngt_pre.glucose_mean = [5.48956 5.48956 5.48956 5.48956 5.82918 6.53877 6.90695 6.44993 5.87725 5.58912 5.24061 4.86354]; +data.ngt_pre.glucose_max = [5.68950 5.68950 5.68950 5.68950 6.20091 6.92542 7.37291 6.92542 6.15830 5.83866 5.49772 5.17808]; +data.ngt_pre.glucose_std = data.ngt_pre.glucose_max - data.ngt_pre.glucose_mean; +data.ngt_pre.glucose_diff = [0 diff(data.ngt_pre.glucose_mean)]./[1 diff(data.ngt_pre.t)]; + +data.ngt_1wk.glucose_mean = [4.92040 4.92040 4.92040 4.92040 5.77227 6.88029 7.64674 7.61655 6.04798 5.19070 4.95606 4.83503]; +data.ngt_1wk.glucose_max = [5.43379 5.43379 5.43379 5.43379 6.43531 7.33029 8.03349 7.99087 6.45662 5.34855 5.34855 5.11416]; +data.ngt_1wk.glucose_std = data.ngt_1wk.glucose_max - data.ngt_1wk.glucose_mean; +data.ngt_1wk.glucose_diff = [0 diff(data.ngt_1wk.glucose_mean)]./[1 diff(data.ngt_1wk.t)]; + +data.ngt_3mo.glucose_mean = [4.94885 4.94885 4.94885 4.94885 6.25601 8.07541 8.35817 6.93362 4.39752 4.22316 4.64295 4.66440]; +data.ngt_3mo.glucose_max = [5.47641 5.47641 5.47641 5.47641 6.56317 8.67276 8.90715 7.58600 4.79452 4.56012 4.87976 5.05023]; +data.ngt_3mo.glucose_std = data.ngt_3mo.glucose_max - data.ngt_3mo.glucose_mean; +data.ngt_3mo.glucose_diff = [0 diff(data.ngt_3mo.glucose_mean)]./[1 diff(data.ngt_3mo.t)]; + +data.ngt_1y.glucose_mean = [4.94885 4.94885 4.94885 4.94885 6.25601 8.21763 8.61427 6.39292 4.11297 4.22332 4.55784 4.66440]; +data.ngt_1y.glucose_max = [5.54033 5.54033 5.54033 5.54033 6.60578 8.67276 8.90715 6.94673 4.45358 4.53881 4.92237 4.92237]; +data.ngt_1y.glucose_std = data.ngt_1y.glucose_max - data.ngt_1y.glucose_mean; +data.ngt_1y.glucose_diff = [0 diff(data.ngt_1y.glucose_mean)]./[1 diff(data.ngt_1y.t)]; + +% +% insulin +% + +% t2d fasting [nmol/L] +data.t2d_pre.insulin_ss_mean = 125/1000; +data.t2d_pre.insulin_ss_std = 77/1000; + +data.t2d_1wk.insulin_ss_mean = 73/1000; +data.t2d_1wk.insulin_ss_std = 32/1000; + +data.t2d_3mo.insulin_ss_mean = 58/1000; +data.t2d_3mo.insulin_ss_std = 35/1000; + +data.t2d_1y.insulin_ss_mean = 47/1000; +data.t2d_1y.insulin_ss_std = 27/1000; + +% ngt fasting [nmol/L] +data.ngt_pre.insulin_ss_mean = 82/1000; +data.ngt_pre.insulin_ss_std = 28/1000; + +data.ngt_1wk.insulin_ss_mean = 49/1000; +data.ngt_1wk.insulin_ss_std = 14/1000; + +data.ngt_3mo.insulin_ss_mean = 43/1000; +data.ngt_3mo.insulin_ss_std = 14/1000; + +data.ngt_1y.insulin_ss_mean = 36/1000; +data.ngt_1y.insulin_ss_std = 16/1000; + +% t2d post-prandial [nM] +data.t2d_pre.insulin_mean = [0.13170 0.13170 0.13170 0.13170 0.15222 0.29688 0.38983 0.39742 0.35831 0.27523 0.17372 0.11100]; +data.t2d_pre.insulin_max = [0.16265 0.16265 0.16265 0.16265 0.19105 0.37952 0.49828 0.50861 0.41824 0.32272 0.20912 0.14200]; +data.t2d_pre.insulin_std = data.t2d_pre.insulin_max - data.t2d_pre.insulin_mean; +data.t2d_pre.insulin_rel = data.t2d_pre.insulin_mean - data.t2d_pre.insulin_mean(1); + +data.t2d_1wk.insulin_mean = [0.05411 0.05411 0.05411 0.05411 0.14963 0.29947 0.53983 0.53191 0.26261 0.14850 0.08320 0.07738]; +data.t2d_1wk.insulin_max = [0.08778 0.08778 0.08778 0.08778 0.18847 0.38210 0.68158 0.69707 0.31239 0.17040 0.10843 0.10069]; +data.t2d_1wk.insulin_std = data.t2d_1wk.insulin_max - data.t2d_1wk.insulin_mean; +data.t2d_1wk.insulin_rel = data.t2d_1wk.insulin_mean - data.t2d_1wk.insulin_mean(1); + +data.t2d_3mo.insulin_mean = [0.05153 0.05153 0.05153 0.05153 0.17291 0.45206 0.72604 0.58363 0.23158 0.10712 0.05734 0.05152]; +data.t2d_3mo.insulin_max = [0.08778 0.08778 0.08778 0.08778 0.19105 0.53184 0.86231 0.69707 0.28399 0.14716 0.08262 0.07229]; +data.t2d_3mo.insulin_std = data.t2d_3mo.insulin_max - data.t2d_3mo.insulin_mean; +data.t2d_3mo.insulin_rel = data.t2d_3mo.insulin_mean - data.t2d_3mo.insulin_mean(1); + +data.t2d_1y.insulin_mean = [0.04894 0.04894 0.04894 0.04894 0.14446 0.37447 0.58897 0.42328 0.15141 0.07351 0.04182 0.03342]; +data.t2d_1y.insulin_max = [0.08778 0.08778 0.08778 0.08778 0.18847 0.44148 0.68675 0.53959 0.18847 0.09811 0.06454 0.05680]; +data.t2d_1y.insulin_std = data.t2d_1y.insulin_max - data.t2d_1y.insulin_mean; +data.t2d_1y.insulin_rel = data.t2d_1y.insulin_mean - data.t2d_1y.insulin_mean(1); + +% ngt post-prandial [nM] +data.ngt_pre.insulin_mean = [0.04339 0.04339 0.04339 0.04339 0.14100 0.41646 0.51149 0.41065 0.25279 0.14389 0.07045 0.04854] +data.ngt_pre.insulin_max = [0.09840 0.09840 0.09840 0.09840 0.22032 0.49717 0.58856 0.47105 0.36513 0.18173 0.09899 0.07492]; +data.ngt_pre.insulin_std = data.ngt_pre.insulin_max - data.ngt_pre.insulin_mean; +data.ngt_pre.insulin_rel = data.ngt_pre.insulin_mean - data.ngt_pre.insulin_mean(1); + +data.ngt_1wk.insulin_mean = [0.05886 0.05886 0.05886 0.05886 0.14358 0.42161 0.68674 0.64776 0.26827 0.07688 0.05756 0.04082]; +data.ngt_1wk.insulin_max = [0.09840 0.09840 0.09840 0.09840 0.20623 0.49952 0.83270 0.76448 0.36278 0.09958 0.07551 0.05614]; +data.ngt_1wk.insulin_std = data.ngt_1wk.insulin_max - data.ngt_1wk.insulin_mean; +data.ngt_1wk.insulin_rel = data.ngt_1wk.insulin_mean - data.ngt_1wk.insulin_mean(1); + +data.ngt_3mo.insulin_mean = [0.05887 0.05887 0.05887 0.05887 0.27760 0.93965 1.32333 1.01117 0.20897 0.07433 0.04210 0.03309]; +data.ngt_3mo.insulin_max = [0.10075 0.10075 0.10075 0.10075 0.31656 1.14271 1.62612 1.29264 0.36043 0.09723 0.06143 0.04440]; +data.ngt_3mo.insulin_std = data.ngt_3mo.insulin_max - data.ngt_3mo.insulin_mean; +data.ngt_3mo.insulin_rel = data.ngt_3mo.insulin_mean - data.ngt_3mo.insulin_mean(1); + +data.ngt_1y.insulin_mean = [0.05371 0.05371 0.05371 0.05371 0.25183 0.60202 0.89293 0.45703 0.06981 0.03308 0.02664 0.01761]; +data.ngt_1y.insulin_max = [0.09840 0.09840 0.09840 0.09840 0.23910 0.67792 1.02049 0.53912 0.09048 0.06201 0.04030 0.03267]; +data.ngt_1y.insulin_std = data.ngt_1y.insulin_max - data.ngt_1y.insulin_mean; +data.ngt_1y.insulin_rel = data.ngt_1y.insulin_mean - data.ngt_1y.insulin_mean(1); + +% +% c-peptide +% + +% t2d fasting [nmol/L] +data.t2d_pre.cpeptide_ss_mean = 1483/1000; +data.t2d_pre.cpeptide_ss_std = 543/1000; + +data.t2d_1wk.cpeptide_ss_mean = 1175/1000; +data.t2d_1wk.cpeptide_ss_std = 595/1000; + +data.t2d_3mo.cpeptide_ss_mean = 1049/1000; +data.t2d_3mo.cpeptide_ss_std = 501/1000; + +data.t2d_1y.cpeptide_ss_mean = 796/1000; +data.t2d_1y.cpeptide_ss_std = 345/1000; + +% ngt fasting [nmol/L] +data.ngt_pre.cpeptide_ss_mean = 1098/1000; +data.ngt_pre.cpeptide_ss_std = 227/1000; + +data.ngt_1wk.cpeptide_ss_mean = 834/1000; +data.ngt_1wk.cpeptide_ss_std = 187/1000; + +data.ngt_3mo.cpeptide_ss_mean = 816/1000; +data.ngt_3mo.cpeptide_ss_std = 191/1000; + +data.ngt_1y.cpeptide_ss_mean = 602/1000; +data.ngt_1y.cpeptide_ss_std = 198/1000; + +% t2d post-prandial [nM] +data.t2d_pre.cpeptide_mean = [1.56164 1.56164 1.56164 1.56164 1.59817 1.94521 2.23744 2.48402 2.72146 2.70320 2.27397 1.78995]; +data.t2d_pre.cpeptide_max = [1.73183 1.73183 1.73183 1.73183 1.77682 2.21394 2.54165 2.75994 2.90467 2.93090 2.53652 2.02361]; +data.t2d_pre.cpeptide_std = data.t2d_pre.cpeptide_max - data.t2d_pre.cpeptide_mean; +data.t2d_pre.cpeptide_rel = data.t2d_pre.cpeptide_mean - data.t2d_pre.cpeptide_mean(1); + +data.t2d_1wk.cpeptide_mean = [1.12329 1.12329 1.12329 1.12329 1.45205 2.01826 2.94977 3.36073 2.92237 2.42922 1.86301 1.58904]; +data.t2d_1wk.cpeptide_max = [1.38532 1.38532 1.38532 1.38532 1.58535 2.38721 3.24378 3.88151 3.34236 2.75766 2.09883 1.76829]; +data.t2d_1wk.cpeptide_std = data.t2d_1wk.cpeptide_max - data.t2d_1wk.cpeptide_mean; +data.t2d_1wk.cpeptide_rel = data.t2d_1wk.cpeptide_mean - data.t2d_1wk.cpeptide_mean(1); + +data.t2d_3mo.cpeptide_mean = [1.04110 1.04110 1.04110 1.04110 1.38813 2.37443 3.06849 3.44292 2.54795 2.08219 1.44292 1.26027]; +data.t2d_3mo.cpeptide_max = [1.36712 1.36712 1.36712 1.36712 1.59445 2.69723 3.48086 3.89064 2.83172 2.34732 1.67026 1.44002]; +data.t2d_3mo.cpeptide_std = data.t2d_3mo.cpeptide_max - data.t2d_3mo.cpeptide_mean; +data.t2d_3mo.cpeptide_rel = data.t2d_3mo.cpeptide_mean - data.t2d_3mo.cpeptide_mean(1); + +data.t2d_1y.cpeptide_mean = [0.77626 0.77626 0.77626 0.77626 1.29680 2.18265 2.85845 2.73973 1.98174 1.63470 1.11416 0.88584]; +data.t2d_1y.cpeptide_max = [1.00234 1.00234 1.00234 1.00234 1.54885 2.35072 3.22554 3.02438 2.20255 1.85494 1.25992 0.97496]; +data.t2d_1y.cpeptide_std = data.t2d_1y.cpeptide_max - data.t2d_1y.cpeptide_mean; +data.t2d_1y.cpeptide_rel = data.t2d_1y.cpeptide_mean - data.t2d_1y.cpeptide_mean(1); + +% ngt post-prandial [nM] +data.ngt_pre.cpeptide_mean = [1.13338 1.13338 1.13338 1.13338 1.44380 2.21150 2.68655 2.65853 2.22752 1.86966 1.43750 1.08765]; +data.ngt_pre.cpeptide_max = [1.18826 1.18826 1.18826 1.18826 1.55354 2.37618 2.82374 2.83232 2.42874 2.09832 1.61126 1.17911]; +data.ngt_pre.cpeptide_std = data.ngt_pre.cpeptide_max - data.ngt_pre.cpeptide_mean; +data.ngt_pre.cpeptide_rel = data.ngt_pre.cpeptide_mean - data.ngt_pre.cpeptide_mean(1); + +data.ngt_1wk.cpeptide_mean = [0.84069 0.84069 0.84069 0.84069 1.34317 2.39446 3.39996 3.52744 2.72141 1.80563 1.28200 1.03279]; +data.ngt_1wk.cpeptide_max = [0.94132 0.94132 0.94132 0.94132 1.55353 2.69629 3.89386 4.00305 3.19703 2.08917 1.35517 1.09681]; +data.ngt_1wk.cpeptide_std = data.ngt_1wk.cpeptide_max - data.ngt_1wk.cpeptide_mean; +data.ngt_1wk.cpeptide_rel = data.ngt_1wk.cpeptide_mean - data.ngt_1wk.cpeptide_mean(1); + +data.ngt_3mo.cpeptide_mean = [0.84986 0.84986 0.84986 0.84986 1.87369 3.55603 5.00970 4.76219 2.71229 1.60441 1.04421 0.88643]; +data.ngt_3mo.cpeptide_max = [0.94131 0.94131 0.94131 0.94131 1.99256 3.93105 5.68653 5.39328 2.46532 1.88796 1.18141 0.95961]; +data.ngt_3mo.cpeptide_std = data.ngt_3mo.cpeptide_max - data.ngt_3mo.cpeptide_mean; +data.ngt_3mo.cpeptide_rel = data.ngt_3mo.cpeptide_mean - data.ngt_3mo.cpeptide_mean(1); + +data.ngt_1y.cpeptide_mean = [0.59376 0.59376 0.59376 0.59376 1.44378 2.81516 4.03105 3.30792 1.52325 1.09224 0.69665 0.55716]; +data.ngt_1y.cpeptide_max = [0.80413 0.80413 0.80413 0.80413 1.55354 3.08958 4.37860 3.72866 1.69704 1.22029 0.77898 0.61205]; +data.ngt_1y.cpeptide_std = data.ngt_1y.cpeptide_max - data.ngt_1y.cpeptide_mean; +data.ngt_1y.cpeptide_rel = data.ngt_1y.cpeptide_mean - data.ngt_1y.cpeptide_mean(1); \ No newline at end of file diff --git a/models/minCPepModel/minCPepData.m b/models/minCPepModel/minCPepData.m new file mode 100644 index 0000000..c8e571a --- /dev/null +++ b/models/minCPepModel/minCPepData.m @@ -0,0 +1,26 @@ +function DATASET = minCPepData() + +DATASET.DESCRIPTION = 'Bariatric surgery data'; + +DATASET.FILE = 'bariatricData'; +DATASET.TYPE = 'Collection'; + +DATASET.GROUPS = { + 't2d_pre' + 't2d_1wk' + 't2d_3mo' + 't2d_1y' + 'ngt_pre' + 'ngt_1wk' + 'ngt_3mo' + 'ngt_1y' +}; + +DATASET.FIELDS = { + 'G' 0 't' 'glucose_mean' 'glucose_std' 1e9 [] + 'dGdt' 0 't' 'glucose_diff' 'glucose_std' 1e9 [] + 'CP' 1 't' 'cpeptide_mean' 'cpeptide_std' 1e3 [] + 'I' 0 't' 'insulin_mean' 'insulin_std' 1e3 [] + + 'BW' 0 [] 'm_mean' 'm_std' 1 [] +}; \ No newline at end of file diff --git a/models/minCPepModel/minCPepModel.m b/models/minCPepModel/minCPepModel.m new file mode 100644 index 0000000..fc0ee36 --- /dev/null +++ b/models/minCPepModel/minCPepModel.m @@ -0,0 +1,82 @@ +function MODEL = minCPepModel() + +MODEL.DESCRIPTION = 'Minimal CPeptide model by Dalla Man et. al'; + +MODEL.PREDICTOR = { + 't' [0 240] {'time' 'min' 'time'} +}; + +MODEL.CONSTANTS = { + 'BW' 'BW' {} + 'Gb' 'G' {} + 'CPb' 'CP' {} + 'Ib' 'I' {} +}; + +MODEL.INPUTS = { + 'G' 'Data' {'G'} 'Linear' {} + 'dGdt' 'Data' {'dGdt'} 'Linear' {} + + 'HE' 'Function' {[-45 0 15 30 45 60 90 120 180 240],'heb','he0','he1','he2','he3','he4','he5','he6','he7','he8',} 'Linear' {} +}; + +MODEL.PARAMETERS = { + % van Cauter + 'k01' 0 .067 [] {} + 'k12' 0 .051 [] {} + 'k21' 0 .065 [] {} + 'dV' 0 .0422 [] {} + + % Campioni + 'PHId' 1 200 [] {'' '-' 'kG'} + 'PHIs' 1 20 [] {'' '1/min' 'beta'} + 'T' 0 1 [] {} + + % Insulin + 'Vi' 0 10 [] {} + + % Hepatic extraction + 'heb' 0 .6 [0 1] {} % + 'he0' 0 .6 [0 1] {} % + 'he1' 1 .6 [0 1] {} % + 'he2' 1 .6 [0 1] {} % + 'he3' 1 .6 [0 1] {} % + 'he4' 1 .6 [0 1] {} % HE pars + 'he5' 1 .6 [0 1] {} % + 'he6' 1 .6 [0 1] {} % + 'he7' 1 .6 [0 1] {} % + 'he8' 1 .6 [0 1] {} % + +% 'HE' 0 .6 [0 1] {} +}; + +MODEL.STATES = { + 'CP1' 0 '-(k01 + k21) * CP1 + k12 * CP2 + SR' {} + 'CP2' 0 '-k12 * CP2 + k21 * CP1' {} + 'Y' 0 '-1/T * (Y - PHIs * 10^-9 * pG)' {} + 'I' 'I' '-(CL/Vi) * I + IDR / Vi' {} +}; + +MODEL.REACTIONS = { + 'V1' 'dV * BW' {} + + 'pdGdt' 'if((G < Gb) || (dGdt < 0), 0, dGdt)' {} + 'pG' 'if((G < Gb), 0, G-Gb)' {} + + 'SRs' 'Y' {} + 'SRd' 'PHId * 10^-9 * pdGdt' {} + 'SRb' 'CPb * k01' {} + + 'SR' 'SRs + SRd' {} + + 'ISR' '(SR + SRb) * V1' {} + 'ISR2' 'ISR / BW' {} + + 'CP' 'CP1 + CPb' {'conc.' 'pM' 'CPeptide'} + + 'PHIb' 'SRb / Gb' {} + + % Insulin + 'IDR' 'ISR * (1 - HE)' {} + 'CL' 'SRb * V1 * (1 - heb) / Ib' {} +}; \ No newline at end of file diff --git a/models/minCPepModel/minCPepModel2.m b/models/minCPepModel/minCPepModel2.m new file mode 100644 index 0000000..e8f21d5 --- /dev/null +++ b/models/minCPepModel/minCPepModel2.m @@ -0,0 +1,69 @@ +function MODEL = minCPepModel() + +MODEL.DESCRIPTION = 'Minimal CPeptide model by Dalla Man et. al'; + +MODEL.PREDICTOR = { + 't' [0 240] {'time' 'min' 'time'} +}; + +MODEL.CONSTANTS = { + 'BW' 'BW' {} + 'Gb' 'G' {} + 'CPb' 'CP' {} + 'Ib' 'I' {} +}; + +MODEL.INPUTS = { + 'G' 'Data' {'G'} 'Linear' {} + 'dGdt' 'Data' {'dGdt'} 'Linear' {} + 'CPI' 'Data' {'CP'} 'Linear' {} +}; + +MODEL.PARAMETERS = { + % van Cauter + 'k01' 0 .067 [] {} + 'k12' 0 .051 [] {} + 'k21' 0 .065 [] {} + 'dV' 0 .0422 [] {} + + % Campioni + 'PHId' 0 1160 [] {'' '-' 'kG'} + 'PHIs' 0 41 [] {'' '1/min' 'beta'} + 'T' 0 10 [] {} + + % Insulin + 'CL' 0 1.7 [] {} + 'Vi' 0 10 [] {} + + 'HE' 1 .6 [0 1] {} +}; + +MODEL.STATES = { + 'CP1' 0 '-(k01 + k21) * CP1 + k12 * CP2 + SR' {} + 'CP2' 0 '-k12 * CP2 + k21 * CP1' {} + 'Y' 0 '-1/T * (Y - PHIs * 10^-9 * pG)' {} + 'I' 'I' '-(CL/Vi) * I + IDR / Vi' {} +}; + +MODEL.REACTIONS = { + 'V1' 'dV * BW' {} + + 'pdGdt' 'if((G < Gb) || (dGdt < 0), 0, dGdt)' {} + 'pG' 'if((G < Gb), 0, G-Gb)' {} + + 'SRs' 'Y' {} + 'SRd' 'PHId * 10^-9 * pdGdt' {} + 'SRb' 'CPb * k01' {} + + 'SR' 'SRs + SRd' {} + + 'ISR' '(SR + SRb) * V1' {} + 'ISR2' 'ISR / BW' {} + + 'CP' 'CP1 + CPb' {'conc.' 'pM' 'CPeptide'} + + 'PHIb' 'SRb / Gb' {} + + % Insulin + 'IDR' 'ISR * (1 - HE)' {} +}; \ No newline at end of file diff --git a/models/minCPepModel/minCPepReg.m b/models/minCPepModel/minCPepReg.m new file mode 100644 index 0000000..4b235e2 --- /dev/null +++ b/models/minCPepModel/minCPepReg.m @@ -0,0 +1,10 @@ +function E = minCPepReg(model, m, d) + +r = model.result; + +ISRi = trapz(r.time, r.vcurr(:, m.v.ISR)); +IDRi = trapz(r.time, r.vcurr(:, m.v.IDR)); + +HE = 1 - IDRi / ISRi; + +E = (HE - .4) * 100; \ No newline at end of file diff --git a/models/minCPepModel/runMinCPep.asv b/models/minCPepModel/runMinCPep.asv new file mode 100644 index 0000000..b713949 --- /dev/null +++ b/models/minCPepModel/runMinCPep.asv @@ -0,0 +1,45 @@ +%% initialize + +import AMF.* + +model = Model('minCPepModel'); +data = DataSet('minCPepData'); + +loadGroup(data, 'ngt_1wk'); +initiateExperiment(model, data); + +%% config + +model.options.optimset.Display = 'iter'; +model.options.useMex = 1; + +parseAll(model); +compileAll(model); + +%% run + +model.functions.reg = @minCPepReg; + +result = fit(model); +% result = simulate(model); + +%% plot +close all; + +plot(result, {'CP','ISR2','I','HE','G','IDR'}); +% manipulate(model, 'CP'); + +fprintf('\n'); +fprintf('T: %.2f\n', getValue(result, 'T', 1)) +fprintf('PHIb: %.2f\n', getValue(result, 'PHIb', 1) * 1e9) +fprintf('PHId: %.2f\n', getValue(result, 'PHId', 1)) +fprintf('PHIs: %.2f\n', getValue(result, 'PHIs', 1)) + +ISR = getValue(result, 'ISR'); +IDR = getValue(result, 'IDR'); + +ISRi = trapz(result.time, ISR); +IDRi = trapz(result.time, IDR); + +fprintf('HE: %.2f\n', 1-IDRi/ISRi); +fprintf('\n'); \ No newline at end of file diff --git a/models/minCPepModel/runMinCPep.m b/models/minCPepModel/runMinCPep.m new file mode 100644 index 0000000..e4097b9 --- /dev/null +++ b/models/minCPepModel/runMinCPep.m @@ -0,0 +1,45 @@ +%% initialize + +import AMF.* + +model = Model('minCPepModel'); +data = DataSet('minCPepData'); + +loadGroup(data, 'ngt_pre'); +initiateExperiment(model, data); + +%% config + +model.options.optimset.Display = 'iter'; +model.options.useMex = 1; + +parseAll(model); +compileAll(model); + +%% run + +% model.functions.reg = @minCPepReg; + +result = fit(model); +% result = simulate(model); + +%% plot +close all; + +plot(result, {'CP','ISR2','I','HE','G','IDR'}); +% manipulate(model, 'CP'); + +fprintf('\n'); +fprintf('T: %.2f\n', getValue(result, 'T', 1)) +fprintf('PHIb: %.2f\n', getValue(result, 'PHIb', 1) * 1e9) +fprintf('PHId: %.2f\n', getValue(result, 'PHId', 1)) +fprintf('PHIs: %.2f\n', getValue(result, 'PHIs', 1)) + +ISR = getValue(result, 'ISR'); +IDR = getValue(result, 'IDR'); + +ISRi = trapz(result.time, ISR); +IDRi = trapz(result.time, IDR); + +fprintf('HE: %.2f\n', 1-IDRi/ISRi); +fprintf('\n'); \ No newline at end of file diff --git a/models/minCPepModel/runMinCPep2.m b/models/minCPepModel/runMinCPep2.m new file mode 100644 index 0000000..488490c --- /dev/null +++ b/models/minCPepModel/runMinCPep2.m @@ -0,0 +1,38 @@ +%% initialize + +import AMF.* + +model = Model('minCPepModel2'); +data = DataSet('minCPepData'); + +loadGroup(data, 't2d_3mo'); +initiateExperiment(model, data); + +%% config + +model.options.optimset.Display = 'off'; +model.options.useMex = 1; +model.options.numIter = 1; +model.options.numTimeSteps = 20; +model.options.SStime = 30; +model.options.seed = 2; +model.options.randPars = 0; +model.options.randData = 0; + +parseAll(model); +compileAll(model); + +%% run + +% model.functions.reg = @minCPepReg; + +result = runADAPT(model); + +%% plot +close all; + +plot(result, {'CP','CP1','I','HE','G','dGdt','pdGdt','SRd','SRs'}); + +% pdGdt haywire - standard deviations too big (will be better if calculated +% using propagation of uncertainty. Will be fixed in combined minModel (no +% inputs just states). \ No newline at end of file diff --git a/models/minGlucModel/minGlucData.m b/models/minGlucModel/minGlucData.m new file mode 100644 index 0000000..70a57dd --- /dev/null +++ b/models/minGlucModel/minGlucData.m @@ -0,0 +1,25 @@ +function DATASET = minGlucData() + +import AMF.functions.* + +DATASET.DESCRIPTION = 'Bariatric surgery data'; + +DATASET.FILE = 'bariatricData'; +DATASET.TYPE = 'Collection'; + +DATASET.GROUPS = { + 't2d_pre' + 't2d_1wk' + 't2d_3mo' + 't2d_1y' + 'ngt_pre' + 'ngt_1wk' + 'ngt_3mo' + 'ngt_1y' +}; + +DATASET.FIELDS = { + 'G' 1 't' 'glucose_mean' 'glucose_std' 1e9 [] + 'I' 0 't' 'insulin_mean' 'insulin_std' 1e3 [] + 'BW' 0 [] 'm_mean' 'm_std' 1 [] +}; \ No newline at end of file diff --git a/models/minGlucModel/minGlucModel.m b/models/minGlucModel/minGlucModel.m new file mode 100644 index 0000000..ece8e90 --- /dev/null +++ b/models/minGlucModel/minGlucModel.m @@ -0,0 +1,54 @@ +function MODEL = minGlucModel() + +MODEL.DESCRIPTION = 'Minimal Glucose model by Dalla Man et. al'; + +MODEL.PREDICTOR = { + 't' [0 240] {'time' 'min' 'time'} +}; + +MODEL.CONSTANTS = { + 'Gtot' 40 {'mass' 'g' 'Gluc intake'} + 'Vg' 1.7 {'' 'dl/kg' 'dV gluc'} + 'BW' 'BW' {'mass' 'kg' 'Avg. BW'} + 'Gb' 'G' {} + 'Ib' 'I' {} +}; + +MODEL.INPUTS = { + 'I' 'Data' {'I'} 'Linear' {'conc.' 'uU/ml' 'Insulin'} + 'Ra' 'Function' {[-45 0 15 30 45 60 90 120 180 240], 'rab', 'ra0', 'ra1', 'ra2', 'ra3', 'ra4', 'ra5', 'ra6', 'ra7', 'ra8',} 'Linear' {'' 'mg/kg/min' 'Rate of appearance'} +}; + +MODEL.PARAMETERS = { + 'p1' 0 .014 [] {'rate' '1/min' 'p1'} % Fractional glucose effectiveness (GE) + 'p2' 0 .03 [] {'rate' '1/min' 'p2'} % Rate constant of remove insulin compartment + 'p3' 1 1e-6 [] {'rate' 'ml/uU' 'p3'} % Scale factor for amplitude of insulin action + + 'rab' 0 0 [] {} + 'ra0' 0 0 [] {} % + 'ra1' 1 1 [] {} % + 'ra2' 1 1 [] {} % + 'ra3' 1 1 [] {} % + 'ra4' 1 1 [] {} % Rate of appearence parameters + 'ra5' 1 1 [] {} % + 'ra6' 1 1 [] {} % + 'ra7' 1 1 [] {} % + 'ra8' 1 1 [] {} % +}; + +MODEL.STATES = { + 'G' 'G' 'dGdt' {'conc.' 'mg/dl' 'Glucose'} + 'X' 0 'dXdt' {'' '-' 'Insulin action'} + 'Gin' 0 'Ra_g' {'mass' 'g' 'App. gluc'} +}; + +MODEL.REACTIONS = { + 'Ir' 'if((I-Ib) > 0, I-Ib,0)' {} + + 'dGdt' '-(p1 + X) * G + p1 * Gb + Ra/Vg * 1e9/18.0182' {} + 'dXdt' '-p2 * X + p3/6.94 * Ir' {} + + % --- + 'Ra_g' 'Ra * BW / 1000' {'' 'g/min' 'Ra'} + 'SI' 'p3/p2' {'' '1/min/(uU/ml)' 'Frac. SI idx'} +}; \ No newline at end of file diff --git a/models/minGlucModel/minGlucReg.m b/models/minGlucModel/minGlucReg.m new file mode 100644 index 0000000..38310a7 --- /dev/null +++ b/models/minGlucModel/minGlucReg.m @@ -0,0 +1,7 @@ +function E = minGlucReg(model, m, d) + +r = model.result; + +AUC = trapz(r.time, r.vcurr(:, m.v.Ra_g)); + +E = AUC - m.c.Gtot; \ No newline at end of file diff --git a/models/minGlucModel/runMinGluc.m b/models/minGlucModel/runMinGluc.m new file mode 100644 index 0000000..17b148d --- /dev/null +++ b/models/minGlucModel/runMinGluc.m @@ -0,0 +1,33 @@ +%% initialize + +import AMF.* + +model = Model('minGlucModel'); +data = DataSet('minGlucData'); + +loadGroup(data, 'ngt_pre'); +initiateExperiment(model, data); + + +%% config + +model.options.optimset.Display = 'iter'; +model.options.useMex = 1; + +parseAll(model); +compileAll(model); + +%% run + +model.functions.reg = @minGlucReg; + +result = fit(model); +result = simulate(model); + +%% plot + +% manipulate(model, 'G'); +figure;plot(result, {'G', 'X', 'dGdt', 'Ra_g', 'Gin'}); + +getValue(result, 'p3') +getValue(result, 'SI', 1) \ No newline at end of file diff --git a/models/minGlucModel2/minGlucData2.m b/models/minGlucModel2/minGlucData2.m new file mode 100644 index 0000000..60b82fd --- /dev/null +++ b/models/minGlucModel2/minGlucData2.m @@ -0,0 +1,25 @@ +function DATASET = minGlucData2() + +import AMF.functions.* + +DATASET.DESCRIPTION = 'Bariatric surgery data'; + +DATASET.FILE = 'bariatricData'; +DATASET.TYPE = 'Collection'; + +DATASET.GROUPS = { + 't2d_pre' + 't2d_1wk' + 't2d_3mo' + 't2d_1y' + 'ngt_pre' + 'ngt_1wk' + 'ngt_3mo' + 'ngt_1y' +}; + +DATASET.FIELDS = { + 'G' 1 't' 'glucose_mean' 'glucose_std' 18.0182 [] + 'I' 0 't' 'insulin_mean' 'insulin_std' 1000/6.94 [] + 'BW' 0 [] 'm_mean' 'm_std' 1 [] +}; \ No newline at end of file diff --git a/models/minGlucModel2/minGlucModel2.m b/models/minGlucModel2/minGlucModel2.m new file mode 100644 index 0000000..555f5f0 --- /dev/null +++ b/models/minGlucModel2/minGlucModel2.m @@ -0,0 +1,44 @@ +function MODEL = minGlucModel2() + +MODEL.DESCRIPTION = 'Minimal Glucose model by Dalla Man et. al'; + +MODEL.PREDICTOR = { + 't' [0 240] {'time' 'min' 'time'} +}; + +MODEL.CONSTANTS = { + 'Gtot' 40 {'mass' 'g' 'Gluc intake'} + 'Vg' 1.7 {'' 'dl/kg' 'dV gluc'} + 'BW' 'BW' {'mass' 'kg' 'Avg. BW'} + 'Gb' 'G' {} + 'Ib' 'I' {} +}; + +MODEL.INPUTS = { + 'I' 'Data' {'I'} 'Linear' {'conc.' 'uU/ml' 'Insulin'} +}; + +MODEL.PARAMETERS = { + 'p1' 0 .014 [] {'rate' '1/min' 'p1'} % Fractional glucose effectiveness (GE) + 'p2' 0 .03 [] {'rate' '1/min' 'p2'} % Rate constant of remove insulin compartment + 'p3' 0 1.0539e-05 [] {'rate' 'ml/uU' 'p3'} % Scale factor for amplitude of insulin action + + 'Ra' 1 0 [] {} +}; + +MODEL.STATES = { + 'G' 'G' 'dGdt' {'conc.' 'mg/dl' 'Glucose'} + 'X' 0 'dXdt' {'' '-' 'Insulin action'} + 'Gin' 0 'Ra_g' {'mass' 'g' 'App. gluc'} +}; + +MODEL.REACTIONS = { + 'Ir' 'if((I-Ib) > 0, I-Ib,0)' {} + + 'dGdt' '-(p1 + X) * G + p1 * Gb + Ra/Vg' {} + 'dXdt' '-p2 * X + p3 * Ir' {} + + % --- + 'Ra_g' 'Ra * BW / 1000' {'' 'g/min' 'Ra'} + 'SI' 'p3/p2' {'' '1/min/(uU/ml)' 'Frac. SI idx'} +}; \ No newline at end of file diff --git a/models/minGlucModel2/runMinGluc2.m b/models/minGlucModel2/runMinGluc2.m new file mode 100644 index 0000000..9c9898f --- /dev/null +++ b/models/minGlucModel2/runMinGluc2.m @@ -0,0 +1,37 @@ +%% initialize + +import AMF.* + +model = Model('minGlucModel2'); +data = DataSet('minGlucData2'); + +loadGroup(data, 'ngt_pre'); +initiateExperiment(model, data); + + +%% config + +model.options.numIter = 500; +model.options.numTimeSteps = 100; + +model.options.optimset.Display = 'off'; +model.options.useMex = 1; +model.options.SSTime = 30; +model.options.lab1 = .1; +model.options.randPars = 0; +model.options.randData = 1; + +parseAll(model); +compileAll(model); + +%% run + +result = runADAPT(model); + + +%check whether AUC satisfies carbohydrate dose + +%% plot +close all + +figure;plot(result, {'G', 'dGdt', 'Ra_g', 'Gin'}, 'hist'); \ No newline at end of file diff --git a/models/minModel/minData.m b/models/minModel/minData.m new file mode 100644 index 0000000..7c67162 --- /dev/null +++ b/models/minModel/minData.m @@ -0,0 +1,26 @@ +function DATASET = minData() + +DATASET.DESCRIPTION = 'Bariatric surgery data'; + +DATASET.FILE = 'bariatricData'; +DATASET.TYPE = 'Collection'; + +DATASET.GROUPS = { + 't2d_pre' + 't2d_1wk' + 't2d_3mo' + 't2d_1y' + 'ngt_pre' + 'ngt_1wk' + 'ngt_3mo' + 'ngt_1y' +}; + +DATASET.FIELDS = { + 'G' 1 't' 'glucose_mean' 'glucose_std' 1e9 [] + 'CP' 1 't' 'cpeptide_mean' 'cpeptide_std' 1e3 [] + 'I' 1 't' 'insulin_mean' 'insulin_std' 1e3 [] +% 'dGdt' 0 't' 'glucose_diff' 'glucose_std' 1e9 [] + + 'BW' 0 [] 'm_mean' 'm_std' 1 [] +}; \ No newline at end of file diff --git a/models/minModel/minModel.m b/models/minModel/minModel.m new file mode 100644 index 0000000..646e1c9 --- /dev/null +++ b/models/minModel/minModel.m @@ -0,0 +1,120 @@ +function MODEL = minModel() + +MODEL.DESCRIPTION = 'Combined minimal model by Dalla Man et. al'; + +MODEL.PREDICTOR = { + 't' [0 240] {'time' 'min' 'time'} +}; + +MODEL.CONSTANTS = { + 'BW' 'BW' {} + 'Gb' 'G' {} + 'CPb' 'CP' {} + 'Ib' 'I' {} + + 'Gtot' 40 {'mass' 'g' 'Gluc intake'} + 'HEi' .4 {} + + 'Vg' 1.7 {'' 'dl/kg' 'dV gluc'} +}; + +MODEL.INPUTS = { +% 'G' 'Data' {'G'} 'Linear' {} +% 'dGdt' 'Data' {'dGdt'} 'Linear' {} + + 'HE' 'Function' {[-45 0 15 30 45 60 90 120 180 240],'heb','he0','he1','he2','he3','he4','he5','he6','he7','he8',} 'Linear' {} + 'Ra' 'Function' {[-45 0 15 30 45 60 90 120 180 240],'rab','ra0','ra1','ra2','ra3','ra4','ra5','ra6','ra7','ra8',} 'Linear' {'' 'mg/kg/min' 'Ra'} +}; + +MODEL.PARAMETERS = { + % van Cauter + 'k01' 0 .067 [] {} + 'k12' 0 .051 [] {} + 'k21' 0 .065 [] {} + 'dV' 0 .0422 [] {} + + % Campioni + 'PHId' 1 200 [] {'' '10^-9' 'PHId(=kG)'} + 'PHIs' 1 20 [] {'' '10^-9/min' 'PHIs(=beta)'} + 'T' 0 3 [] {} + + % Insulin + 'Vi' 0 10 [] {} + + % Hepatic extraction + 'heb' 0 .6 [0 1] {} % + 'he0' 0 .6 [0 1] {} % + 'he1' 1 .6 [0 1] {} % + 'he2' 1 .6 [0 1] {} % + 'he3' 1 .6 [0 1] {} % + 'he4' 1 .6 [0 1] {} % HE pars + 'he5' 1 .6 [0 1] {} % + 'he6' 1 .6 [0 1] {} % + 'he7' 1 .6 [0 1] {} % + 'he8' 1 .6 [0 1] {} % + + % Glucose + 'p1' 0 .014 [] {'rate' '1/min' 'p1'} % Fractional glucose effectiveness (GE) + 'p2' 0 .03 [] {'rate' '1/min' 'p2'} % Rate constant of remove insulin compartment + 'p3' 1 1e-6 [] {'rate' 'ml/uU' 'p3'} % Scale factor for amplitude of insulin action + + 'rab' 0 0 [] {} + 'ra0' 0 0 [] {} % + 'ra1' 1 1 [] {} % + 'ra2' 1 1 [] {} % + 'ra3' 1 1 [] {} % + 'ra4' 1 1 [] {} % Rate of appearence parameters + 'ra5' 1 1 [] {} % + 'ra6' 1 1 [] {} % + 'ra7' 1 1 [] {} % + 'ra8' 1 1 [] {} % +}; + +MODEL.STATES = { + % C-peptide + 'CP1' 0 '-(k01 + k21) * CP1 + k12 * CP2 + SR' {} + 'CP2' 0 '-k12 * CP2 + k21 * CP1' {} + 'Y' 0 '-1/T * (Y - PHIs * 10^-9 * pG)' {} + + % Insulin + 'I' 'I' '-(CL/Vi) * I + IDR / Vi' {} + + % Glucose + 'G' 'G' 'dGdt' {'conc.' 'mg/dl' 'Glucose'} + 'X' 0 'dXdt' {'' '-' 'Insulin action'} + 'Gin' 0 'Ra_g' {'mass' 'g' 'App. gluc'} +}; + +MODEL.REACTIONS = { + % Glucose + 'Ir' 'if((I-Ib) > 0, I-Ib,0)' {} + + 'dGdt' '-(p1 + X) * G + p1 * Gb + Ra/Vg * 1e9/18.0182' {} + 'dXdt' '-p2 * X + p3/6.94 * Ir' {} + + 'Ra_g' 'Ra * BW / 1000' {'' 'g/min' 'Ra'} + 'SI' 'p3/p2' {'' '1/min/(uU/ml)' 'Frac. SI idx'} + + % C-peptide + 'V1' 'dV * BW' {} + + 'pdGdt' 'if((G < Gb) || (dGdt < 0), 0, dGdt)' {} + 'pG' 'if((G < Gb), 0, G-Gb)' {} + + 'SRs' 'Y' {} + 'SRd' 'PHId * 10^-9 * pdGdt' {} + 'SRb' 'CPb * k01' {} + + 'SR' 'SRs + SRd' {} + + 'ISR' '(SR + SRb) * V1' {} + 'ISR2' 'ISR / BW' {} + + 'CP' 'CP1 + CPb' {'conc.' 'pM' 'CPeptide'} + + 'PHIb' 'SRb / Gb' {} + + % Insulin + 'IDR' 'ISR * (1 - HE)' {} + 'CL' 'SRb * V1 * (1 - heb) / Ib' {} +}; \ No newline at end of file diff --git a/models/minModel/minModel2.m b/models/minModel/minModel2.m new file mode 100644 index 0000000..5a08182 --- /dev/null +++ b/models/minModel/minModel2.m @@ -0,0 +1,96 @@ +function MODEL = minModel() + +MODEL.DESCRIPTION = 'Combined minimal model by Dalla Man et. al'; + +MODEL.PREDICTOR = { + 't' [0 240] {'time' 'min' 'time'} +}; + +MODEL.CONSTANTS = { + 'BW' 'BW' {} + 'Gb' 'G' {} + 'CPb' 'CP' {} + 'Ib' 'I' {} + + % Constraints + 'Gtot' 40 {'mass' 'g' 'Gluc intake'} + 'HEi' .4 {} +}; + +MODEL.PARAMETERS = { + % van Cauter + 'k01' 0 .067 [] {} + 'k12' 0 .051 [] {} + 'k21' 0 .065 [] {} + 'dV' 0 .0422 [] {} + + % Insulin + 'Vi' 0 10 [] {} + + % Hepatic extraction + 'heb' 0 .6 [0 1] {} % + + % Glucose + 'p1' 0 .014 [] {'rate' '1/min' 'p1'} % Fractional glucose effectiveness (GE) + 'p2' 0 .03 [] {'rate' '1/min' 'p2'} % Rate constant of remove insulin compartment + + 'Vg' 0 1.7 [] {'' 'dl/kg' 'dV gluc'} + + % Fitpars + 'T' 0 3 [] {} + 'PHId' 0 565.44 [] {'' '10^-9' 'PHId(=kG)'} + 'PHIs' 0 38.57 [] {'' '10^-9/min' 'PHIs(=beta)'} + 'p3' 0 1.0888e-05 [] {'rate' 'ml/uU' 'p3'} % Scale factor for amplitude of insulin action + + 'Ra' 1 0 [] {} + 'HE' 1 .6 [0 1] {} +}; + +MODEL.STATES = { + % C-peptide + 'CP1' 0 '-(k01 + k21) * CP1 + k12 * CP2 + SR' {} + 'CP2' 0 '-k12 * CP2 + k21 * CP1' {} + 'Y' 0 '-1/T * (Y - PHIs * 10^-9 * pG)' {} + + % Insulin + 'I' 'I' '-(CL/Vi) * I + IDR / Vi' {} + + % Glucose + 'G' 'G' 'dGdt' {'conc.' 'mg/dl' 'Glucose'} + 'X' 0 'dXdt' {'' '-' 'Insulin action'} + 'Gin' 0 'Ra_g' {'mass' 'g' 'App. gluc'} +}; + +MODEL.REACTIONS = { + % Glucose + 'Ir' 'if((I-Ib) > 0, I-Ib,0)' {} + + 'dGdt' '-(p1 + X) * G + p1 * Gb + Ra/Vg * 1e9/18.0182' {} + 'dXdt' '-p2 * X + p3/6.94 * Ir' {} + + 'Ra_g' 'Ra * BW / 1000' {'' 'g/min' 'Ra'} + 'SI' 'p3/p2' {'' '1/min/(uU/ml)' 'Frac. SI idx'} + + % C-peptide + 'V1' 'dV * BW' {} + + 'pdGdt' 'if((G < Gb) || (dGdt < 0), 0, dGdt)' {} + 'pG' 'if((G < Gb), 0, G-Gb)' {} + + 'SRs' 'Y' {} + 'SRd' 'PHId * 10^-9 * pdGdt' {} + 'SRb' 'CPb * k01' {} + + 'SR' 'SRs + SRd' {} + + 'ISR' '(SR + SRb) * V1' {} + 'ISR2' 'ISR / BW' {} + + 'CP' 'CP1 + CPb' {'conc.' 'pM' 'CPeptide'} + + 'PHIb' 'SRb / Gb' {} + + % Insulin + 'IDR' 'ISR * (1 - HE)' {} + 'CL' 'SRb * V1 * (1 - heb) / Ib' {} +}; \ No newline at end of file diff --git a/models/minModel/minReg.m b/models/minModel/minReg.m new file mode 100644 index 0000000..0a65aaf --- /dev/null +++ b/models/minModel/minReg.m @@ -0,0 +1,14 @@ +function E = minReg(model, m, d) + +r = model.result; + +% C-pep HE +ISRi = trapz(r.time, r.vcurr(:, m.v.ISR)); +IDRi = trapz(r.time, r.vcurr(:, m.v.IDR)); + +HE = 1 - IDRi / ISRi; + +% Gluc RA +AUC_Ra = trapz(r.time, r.vcurr(:, m.v.Ra_g)); + +E = [(HE - m.c.HEi) * 1; AUC_Ra - m.c.Gtot]; \ No newline at end of file diff --git a/models/minModel/runMin.m b/models/minModel/runMin.m new file mode 100644 index 0000000..7e860dc --- /dev/null +++ b/models/minModel/runMin.m @@ -0,0 +1,46 @@ +%% initialize + +import AMF.* + +model = Model('minModel'); +data = DataSet('minData'); + +loadGroup(data, 't2d_1y'); +initiateExperiment(model, data); + +%% config + +model.options.optimset.Display = 'iter'; +model.options.useMex = 1; + +parseAll(model); +compileAll(model); + +%% run + +model.functions.reg = @minReg; + +result = fit(model); +% result = simulate(model); + +%% plot +close all; + +plot(result, {'CP','I','G','dGdt','HE','Ra','ISR2','Gin'}); +% manipulate(model, 'CP'); + +fprintf('\n'); +fprintf('T: %.2f\n', getValue(result, 'T', 1)) +fprintf('PHIb: %.2f\n', getValue(result, 'PHIb', 1) * 1e9) +fprintf('PHId: %.2f\n', getValue(result, 'PHId', 1)) +fprintf('PHIs: %.2f\n', getValue(result, 'PHIs', 1)) +fprintf('p3: %.4e\n', getValue(result, 'p3', 1)) + +ISR = getValue(result, 'ISR'); +IDR = getValue(result, 'IDR'); + +ISRi = trapz(result.time, ISR); +IDRi = trapz(result.time, IDR); + +fprintf('HE: %.2f\n', 1-IDRi/ISRi); +fprintf('\n'); \ No newline at end of file diff --git a/models/minModel/runMin2.m b/models/minModel/runMin2.m new file mode 100644 index 0000000..f694804 --- /dev/null +++ b/models/minModel/runMin2.m @@ -0,0 +1,34 @@ +%% initialize + +import AMF.* + +model = Model('minModel2'); +data = DataSet('minData'); + +loadGroup(data, 't2d_1y'); +initiateExperiment(model, data); + +%% config + +model.options.optimset.Display = 'off'; +model.options.useMex = 1; +model.options.numIter = 10; +model.options.numTimeSteps = 100; +model.options.SSTime = 45; +model.options.lab1 = .1; +model.options.randPars = 0; +model.options.randData = 1; + +parseAll(model); +compileAll(model); + +%% run + +% model.functions.reg = @minReg; + +result = runADAPT(model); + +%% plot +close all; + +plot(result, {'CP','I','G','Ir','dGdt','HE','Ra_g','ISR2','Gin'}); \ No newline at end of file diff --git a/models/tiemannModel/dat.m b/models/tiemannModel/dat.m new file mode 100644 index 0000000..dab73a6 --- /dev/null +++ b/models/tiemannModel/dat.m @@ -0,0 +1,95 @@ +load('data_Oosterveer.mat') + +C16_0 = [11.5556 17.1852 34.3704 59.2593]; +C18_1 = [14.9466 34.1637 128.114 200.712]; +C16_0_i = interp1(data.t2,C16_0,data.t1,'linear','extrap') ; +C18_1_i = interp1(data.t2,C18_1,data.t1,'linear','extrap') ; +w16 = C16_0_i ./ (C16_0_i + C18_1_i); +w18 = C18_1_i ./ (C16_0_i + C18_1_i); + +% -- +hep_DNL = data.DNL_16_0 .* repmat(w16,size(data.DNL_16_0,1),1) + data.DNL_18_1 .* repmat(w18,size(data.DNL_18_1,1),1); +d.hep_DNL = nanmean(hep_DNL); +d.hep_DNL_std = nanstd(hep_DNL); + +hep_CE_abs = data.hep_CE.*data.hep_mass; +d.hep_CE_abs = nanmean(hep_CE_abs); +d.hep_CE_abs_std = nanstd(hep_CE_abs); + +hep_FC_abs = data.hep_FC.*data.hep_mass; +d.hep_FC_abs = nanmean(hep_FC_abs); +d.hep_FC_abs_std = nanstd(hep_FC_abs); + +hep_TG_abs = data.hep_TG.*data.hep_mass; +d.hep_TG_abs = nanmean(hep_TG_abs); +d.hep_TG_abs_std = nanstd(hep_TG_abs); + +hep_CE_rel = data.hep_CE; +d.hep_CE_rel = nanmean(hep_CE_rel); +d.hep_CE_rel_std = nanstd(hep_CE_rel); + +hep_FC_rel = data.hep_FC; +d.hep_FC_rel = nanmean(hep_FC_rel); +d.hep_FC_rel_std = nanstd(hep_FC_rel); + +hep_TG_rel = data.hep_TG; +d.hep_TG_rel = nanmean(hep_TG_rel); +d.hep_TG_rel_std = nanstd(hep_TG_rel); + +hep_mass = data.hep_mass; +d.hep_mass = nanmean(hep_mass); +d.hep_mass_std = nanstd(hep_mass); + +plasma_FFA = data.FFA; +d.plasma_FFA = nanmean(plasma_FFA); +d.plasma_FFA_std = nanstd(plasma_FFA); + +plasma_TG = data.plasma_TG; +d.plasma_TG = nanmean(plasma_TG); +d.plasma_TG_std = nanstd(plasma_TG); + +VLDL_clearance = data.VLDL_clearance ./ mean(data.VLDL_clearance(:,1)); +d.VLDL_clearance = nanmean(VLDL_clearance); +d.VLDL_clearance_std = nanstd(VLDL_clearance); + +VLDL_diameter = data.VLDL_diameter; +d.VLDL_diameter = nanmean(VLDL_diameter); +d.VLDL_diameter_std = nanstd(VLDL_diameter); + +VLDL_TG_C_ratio = data.VLDL_TG ./ data.VLDL_CE; +d.VLDL_TG_C_ratio = nanmean(VLDL_TG_C_ratio); +d.VLDL_TG_C_ratio_std = nanstd(VLDL_TG_C_ratio); + +VLDL_production = data.VLDL_production; +d.VLDL_production = nanmean(VLDL_production); +d.VLDL_production_std = nanstd(VLDL_production); + +% -- + +d.plasma_TG_FPLC = data.plasma_TG_FPLC; +d.plasma_TG_FPLC_std = sqrt(interp1(data.t2,nanstd(data.plasma_TG).^2,data.t1,'linear')); +d.plasma_TG_FPLC_std(end) = d.plasma_TG_FPLC_std(end-1); + +d.plasma_TC_FPLC = data.plasma_C_FPLC; +d.plasma_TC_FPLC_std = sqrt(interp1([0 336],[137.6 302.7].^2,data.t1,'linear')); % estimated from Grefhorst 2012 et al. Atherosclerosis +d.plasma_TC_FPLC_std(end) = d.plasma_TC_FPLC_std(end-1); + +d.plasma_C_HDL_FPLC = data.plasma_C_HDL_FPLC; +d.plasma_C_HDL_FPLC_std = (d.plasma_C_HDL_FPLC./d.plasma_TC_FPLC) .* d.plasma_TC_FPLC_std; + +d.plasma_C_HDL_FPLC_2 = d.plasma_C_HDL_FPLC ./ d.plasma_TC_FPLC; +d.plasma_C_HDL_FPLC_2_std = d.plasma_C_HDL_FPLC_std; + +d.hep_SRB1 = data.hep_SRB1'; +d.hep_SRB1_std = data.hep_SRB1_std'; + +d.t1 = data.t1; +d.t2 = data.t2; + +% Xie +bodymass = 25e-3; + +mwFC = 386.7; % molecular weight of FC [g / mol], Teerlink et al. + +d.hep_HDL_CE_upt = ( bodymass * 1e6 * 44.8 * 1e-3) / (24 * mwFC); % umol/h +d.hep_HDL_CE_upt_std = ( bodymass * 1e6 * 6.79 * 1e-3) / (24 * mwFC); % umol/h \ No newline at end of file diff --git a/models/tiemannModel/data_Oosterveer.mat b/models/tiemannModel/data_Oosterveer.mat new file mode 100644 index 0000000000000000000000000000000000000000..edd769a7e9fcbf3c8504828b36f7e0353ba0fa05 GIT binary patch literal 18576 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 Bvd91c literal 0 HcmV?d00001 diff --git a/models/tiemannModel/runTiemann.m b/models/tiemannModel/runTiemann.m new file mode 100644 index 0000000..3952276 --- /dev/null +++ b/models/tiemannModel/runTiemann.m @@ -0,0 +1,38 @@ +%% initialize + +import AMF.* + +model = Model('tiemannModel'); +data = DataSet('tiemannData'); + +loadGroup(data, 'oosterveer'); +initiateExperiment(model, data); + +%% config + +model.options.useMex = 1; +model.options.savePrefix = ''; +model.options.odeTol = [1e-12 1e-12 100]; +model.options.numIter = 1; +model.options.numTimeSteps = 3; +model.options.parScale = [2 -2]; +model.options.seed = 3; +model.options.SSTime = 1000; +model.options.lab1 = .1; +model.options.optimset.Display = 'iter'; + +parseAll(model); +compileAll(model); + +%% run + +model.functions.reg = @tiemannReg; + +result = runADAPT(model); + + +%% plot + +plotAll(result, 'parameters', 'traj'); +plotAll(result, 'states', 'traj'); +plotAll(result, 'reactions', 'traj'); \ No newline at end of file diff --git a/models/tiemannModel/tiemannData.m b/models/tiemannModel/tiemannData.m new file mode 100644 index 0000000..a9925fa --- /dev/null +++ b/models/tiemannModel/tiemannData.m @@ -0,0 +1,32 @@ +function DATASET = tiemannData() + +DATASET.DESCRIPTION = 'Tiemann model data (Oosterveer & Xie)'; + +DATASET.FILE = 'tiemannData'; +DATASET.TYPE = 'Collection'; + +DATASET.GROUPS = { + 'oosterveer' +}; + +DATASET.FIELDS = { + 'dhep_TG_abs' 1 't1' 'hep_TG_abs' 'hep_TG_abs_std' 1 [] + 'dhep_CE_abs' 1 't1' 'hep_CE_abs' 'hep_CE_abs_std' 1 [] + 'dhep_FC_abs' 1 't1' 'hep_FC_abs' 'hep_FC_abs_std' 1 [] + 'dplasma_C' 1 't1' 'plasma_TC_FPLC' 'plasma_TC_FPLC_std' 1 [] + 'dplasma_TG' 1 't1' 'plasma_TG_FPLC' 'plasma_TG_FPLC_std' 1 [] + 'dVLDL_TG_C_ratio' 1 't2' 'VLDL_TG_C_ratio' 'VLDL_TG_C_ratio_std' 1 [] + 'dVLDL_diameter' 1 't2' 'VLDL_diameter' 'VLDL_diameter_std' 1 [] + 'dVLDL_production' 1 't2' 'VLDL_production' 'VLDL_production_std' 1 [] + 'dVLDL_clearance' 1 't2' 'VLDL_clearance' 'VLDL_clearance_std' 1 [] + 'dDNL' 1 't1' 'hep_DNL' 'hep_DNL_std' 1 [] + 'dFFA' 1 't1' 'plasma_FFA' 'plasma_FFA_std' 1 [] + + 'dhep_HDL_CE_upt' 1 't3' 'hep_HDL_CE_upt' 'hep_HDL_CE_upt_std' 1 [] + 'dplasma_C_HDL_FPLC' 0 't1' 'plasma_C_HDL_FPLC_2' 'plasma_C_HDL_FPLC_2_std' 1 [] +}; + +DATASET.FUNCTIONS = { + 'dplasma_C_HDL' 1 't1' 'dplasma_C .* dplasma_C_HDL_FPLC' 'dplasma_C_HDL_FPLC' + 'dplasma_C_0' 0 't1' 'dplasma_C - dplasma_C_HDL' 'dplasma_C' +}; \ No newline at end of file diff --git a/models/tiemannModel/tiemannData.mat b/models/tiemannModel/tiemannData.mat new file mode 100644 index 0000000000000000000000000000000000000000..43b109f6aaa13aecacd6a3d7d3db27d0a7620b82 GIT binary patch literal 2352 zcmV-03D5RTK~zjZLLfCRFd$7qR4ry{Y-KDUP;6mzW^ZzBIv`L(S4mDbG%O%Pa%Ew3 zWn>_4ZaN@Tb!8wf8YPR*0gvg$d3e)k9$$34nAG_H{Ja?ENOL3Wm>OeKW1N#c84lApNtaBu^PH|9!PuDwBJ*RX(!KW^$8=dOuOeO2- zZJey1;FB}Pxw$^ZRnKl|vVoP!;}c1v+`)#>Z2pbM^1&)kiZp-+kLw?UhqL*H=DuKQN{#$GJLp&Z)z(Wbbt^H^%q)gbPE1 zdmRx@4mNSG%o^w4-Yb0LPfiH1hbDVy?Yds_=1K-i3a?dsE_MTjwHM6#XnPm+1my|c zr7VDdi!)LoPIWy8?}c?zJr5 z-KE-#PRXuQGfW{Y$J0#oPRL?)=&3=x%z{fLzo)+BCu|6 ztJCMVyb!E|rQ1^Yp?lz3Ns1N*C}#zZ77BX2~D{DUX&e~ zk?5uhQObG2WojEB0^1<{agH&}<@?jPywVElyzTBj++hK!hG&ZUA^{{XH%nx%VIi^oAb6fRgic>H zQ7^Z~Al@%FKZ@Cb+i(BzLlq~Kn-FV&@mfm15m~Sb=;>|s=$Z`8QFNphnfT}Z6t}tx zvDS4*7ezE8`m^wtbGmA9`^kUI4!t4!6GZtJNDE(C12RjAo6VhcVDSpa%ujA6(EV}9 zO}A?kyiG6~uIM)f=WEEZc!m+~{qpqcb3ubZ@>8&s1rhVys2ou~kpI;tRzwb< zF2UI$Ya0;`ggxk`&sq*fH5x%weMQ`UZzYZVt~d7}U-5MPCLb1R-;yI6)ZUMT8PDLd z@E{6PEZp83I)rxghO*xXux~U7xc&G`Uj)ZU<{(UK`D>C=CTidv*?i*tZR8M={P3n? z2}-jc)IO~FC%P%~Q0#1116r@UnDr*F829%R628vNQSt{$Wf7swJpc;-GFV^X5CFMl z;oG&A_ycou(ZW5&fsnO=*-t`8!Ea$T46Zne|9(-aHD6U=01x&1t4r$*p=z(*zNa!q za9&}J_F(E3xQ^LX5WxVTY>w=iG;?55DSUO?tw#OK{)->)6hC?Ph#`g2FVA4lPjKz3 zl!ak{{cWA)pXCf)3(m$HXzs#Y_m;J1lWMLt?Ay7mWSRC}pgiggGh>iJw>vz1osTi@ zy2B%!=t57#u8`G(x{>S!BTGNg_b6-jTQy&$&j@c_kNeuKk@Cfe@Vm<^^|%_O^5oG- z3atj+&Xr-_QmMgR*Ds>}Md~d(koPpstV-AoR`~(86-v$!FC$5cmGHp54$49EU4wau zz*pVwUvo?Wo>t8dpt@XN@@MtQfYibMofWx@KwLbz!_QY9_AJy8 zBAP1TuA8#XWnfdr2jsWJOTHzJh4OTiPqjAmps*#+(^a;7z`ee8l}E{K`{qGgOOAB? z%>|&dbk}}O@r7_K$h!9SABwp9jY~}LUD=62OPI6U-LBWDKjm}!@sjr_*X|RsFt-o) zeIop6v8g~z05q112M(%6L#FwWP&@KTNMKU*7d0LQsp9wX&zcXx+GSQDf>}o)lb&4Q ze%KH9eKPeNhEud^?^QcOs!ff=rHiy_=knY0iO27A^F_XOyQ9F+Vp&uCrfA@EQa|=| zUMvLMzln&XSlCK&UK!*4JA61)+H>ShBG~0Ws8HLNgxgPJG^mgyEJ z8YHWwNUd#g1W~Kp&~kfc7?rhqe0}2e%cWenb7EyA1iuVcS}lAMq;)?i^_`1`fEePT zh@2SMXddw>hIt+`a||q#-d%tV49{$N&qUmQo24&3nSW>(NC&tueDtY6(XtL~lCy{X zk4NeXH|~MhQpFkfV*U-@(E@>8EO*FIb=vOH>5khkDKO3~%%%gik9giW?$d!b6R`6&@5Fr`{-62bIoD&+jeaqG6lpWu zjz(_y_GXwhA+IPYUQ3ZC-1ktn-Qjwz135^DM_}f1f+ii52w3W30 literal 0 HcmV?d00001 diff --git a/models/tiemannModel/tiemannModel.m b/models/tiemannModel/tiemannModel.m new file mode 100644 index 0000000..da1dbfd --- /dev/null +++ b/models/tiemannModel/tiemannModel.m @@ -0,0 +1,144 @@ +function MODEL = tiemannModel() + +MODEL.PREDICTOR = { + 't' [0 504] {} +}; + +MODEL.PARAMETERS = { + 'Vm_FC_prod' 1 0 [] {} + 'Vm_FC_met' 1 0 [] {} + 'Vm_CE_for' 1 0 [] {} + 'Vm_CE_def' 1 0 [] {} + 'Vm_CE_ER_for' 1 0 [] {} + 'Vm_CE_ER_def' 1 0 [] {} + 'Vm_TG_prod' 1 0 [] {} + 'Vm_TG_met' 1 0 [] {} + 'Vm_TG_for' 1 0 [] {} + 'Vm_TG_ER_prod' 1 0 [] {} + 'Vm_TG_ER_for' 1 0 [] {} + 'Vm_FFA_upt' 1 0 [] {} + 'Vm_FFA_prod' 1 0 [] {} + 'Vm_VLDL_TG' 1 0 [] {} + 'Vm_VLDL_CE' 1 0 [] {} + 'Vm_TG_CE_upt' 1 0 [] {} + 'Vm_TG_CE_upt_ph' 1 0 [] {} + 'Vm_TG_hyd' 1 0 [] {} + 'Vm_TG_hyd_ph' 1 0 [] {} + 'Vm_HDL_CE_for' 1 0 [] {} + 'Vm_HDL_CE_upt' 1 0 [] {} + 'Vm_ApoB_prod' 1 0 [] {} + + % copied + 'Vm_TG_CE_upt_0' 0 'Vm_TG_CE_upt' [] {} + 'Vm_TG_CE_upt_ph_0' 0 'Vm_TG_CE_upt_ph' [] {} +}; + +MODEL.CONSTANTS = { + 'mwTG' 859.2 {} % molecular weight of TG [g / mol], Teerlink et al. + 'mvTG' 859.2 * 1.102 {} % molecular volume of TG [ml / mol], Teerlink et al. + 'mwCE' 647.9 {} % molecular weight of CE [g / mol], Teerlink et al. + 'mvCE' 647.9 * 1.058 {} % molecular volume of CE [ml / mol], Teerlink et al. + 'mwFC' 386.7 {} % molecular weight of FC [g / mol], Teerlink et al. + 'mvFC' 386.7 * 1.021 {} % molecular volume of FC [ml / mol], Teerlink et al. + 'mwPL' 786.0 {} % molecular weight of PL [g / mol], Teerlink et al. + 'mvPL' 786.0 * 0.984 {} % molecular volume of PL [ml / mol], Teerlink et al. + 'mwApoB' 546340 {} % molecular weight of apoB [g / mol], Hubner et al. + 'navg' 6.02214179 {} % number of Avogadro [10^23] + 'uH' 1.660538782 {} % atomic mass of a hydrogen atom [10^-24] + 'plasma_volume' 0.001 {} % 4.125% of bodyweight [L] + 'rs' 2 {} % radius of lipoprotein surface [nm], Hubner et al. 2009 + 'npi' pi {} % pi +}; + +MODEL.STATES = { + 'hep_FC' 'dhep_FC_abs' 'J_FC_production - J_FC_metabolism - J_CE_formation + J_CE_deformation - J_CE_ER_formation + J_CE_ER_deformation' {} + 'hep_CE' 'dhep_CE_abs' 'J_CE_formation - J_CE_deformation + J_CE_upt_2 + J_CE_HDL_upt_2' {} + 'hep_CE_ER' 0 'J_CE_ER_formation - J_CE_ER_deformation - J_VLDL_CE_1' {} + 'hep_TG' 'dhep_TG_abs' '- J_TG_metabolism + J_TG_formation - J_TG_ER_formation + (J_FFA_upt_2/3.0) + J_TG_upt_2 + J_TG_hyd_2' {} + 'hep_TG_ER' 0 '- J_TG_formation + J_TG_ER_formation - J_VLDL_TG_1' {} + 'hep_TG_DNL' 0 'J_TG_production - J_TG_metabolism_DNL + J_TG_formation_DNL - J_TG_ER_formation_DNL' {} + 'hep_TG_ER_DNL' 0 'J_TG_ER_production - J_TG_formation_DNL + J_TG_ER_formation_DNL - J_VLDL_TG_DNL_1' {} + 'plasma_TG' 'dplasma_TG' 'J_VLDL_TG_2 + J_VLDL_TG_DNL_2 - J_TG_upt_1 - J_TG_upt_ph - J_TG_hyd_1 - J_TG_hyd_ph' {} + 'plasma_C' 'dplasma_C_0' 'J_VLDL_CE_2 - J_CE_upt_1 - J_CE_upt_ph' {} + 'plasma_C_HDL' 'dplasma_C_HDL' 'J_CE_HDL_for - J_CE_HDL_upt_1' {} + 'plasma_FFA' 'dFFA' 'J_FFA_prod - J_FFA_upt_1' {} +}; + +MODEL.REACTIONS = { + % cholesterol + 'J_FC_production' 'Vm_FC_prod' {} %production of free cholesterol + 'J_FC_metabolism' 'Vm_FC_met * hep_FC' {} %metabolism of free cholesterol + 'J_CE_formation' 'Vm_CE_for * hep_FC' {} %formation of cholesterol ester from free cholesterol (cytosol) + 'J_CE_deformation' 'Vm_CE_def * hep_CE' {} %deformation of cholesterol ester to free cholesterol (cytosol) + 'J_CE_ER_formation' 'Vm_CE_ER_for * hep_FC' {} %formation of cholesterol ester from free cholesterol (ER) + 'J_CE_ER_deformation' 'Vm_CE_ER_def * hep_CE_ER' {} %deformation of cholesterol ester to free cholesterol (ER) + + % triglyceride + 'J_TG_production' 'Vm_TG_prod' {} %production of triglyceride (cytosol) + 'J_TG_metabolism' 'Vm_TG_met * hep_TG' {} %metabolism of triglyceride (cytosol) + 'J_TG_metabolism_DNL' 'Vm_TG_met * hep_TG_DNL' {} %metabolism of triglyceride (cytosol) + 'J_TG_formation' 'Vm_TG_for * hep_TG_ER' {} %transport of triglyceride from ER to cytosol + 'J_TG_formation_DNL' 'Vm_TG_for * hep_TG_ER_DNL' {} %transport of triglyceride from ER to cytosol + 'J_TG_ER_production' 'Vm_TG_ER_prod' {} %production of triglyceride (ER) + 'J_TG_ER_formation' 'Vm_TG_ER_for * hep_TG' {} %transport of triglyceride from cytosol to ER + 'J_TG_ER_formation_DNL' 'Vm_TG_ER_for * hep_TG_DNL' {} %transport of triglyceride from cytosol to ER + 'J_FFA_upt_1' 'Vm_FFA_upt * plasma_FFA' {} %uptake of free fatty acids by the liver (cytosol) + 'J_FFA_upt_2' 'Vm_FFA_upt * plasma_FFA * plasma_volume' {} %uptake of free fatty acids by the liver (cytosol) + 'J_FFA_prod' 'Vm_FFA_prod' {} % + + % lipoprotein production + 'J_VLDL_TG_1' 'Vm_VLDL_TG * hep_TG_ER' {} %amount of triglycerides transported to VLDL + 'J_VLDL_TG_DNL_1' 'Vm_VLDL_TG * hep_TG_ER_DNL' {} %amount of triglycerides transported to VLDL + 'J_VLDL_CE_1' 'Vm_VLDL_CE * hep_CE_ER' {} %amount of cholesterol ester transported to VLDL + 'J_VLDL_TG_2' 'Vm_VLDL_TG * hep_TG_ER / plasma_volume' {} %amount of triglycerides transported to VLDL + 'J_VLDL_TG_DNL_2' 'Vm_VLDL_TG * hep_TG_ER_DNL / plasma_volume' {} %amount of triglycerides transported to VLDL + 'J_VLDL_CE_2' 'Vm_VLDL_CE * hep_CE_ER / plasma_volume' {} %amount of cholesterol ester transported to VLDL + + % lipoprotein uptake + 'J_TG_upt_1' 'Vm_TG_CE_upt * plasma_TG' {} %whole particle uptake by liver (TG) + 'J_CE_upt_1' 'Vm_TG_CE_upt * plasma_C' {} %whole particle uptake by liver (CE) + 'J_TG_upt_ph' 'Vm_TG_CE_upt_ph * plasma_TG' {} %whole particle uptake by peripheral tissue (TG) + 'J_CE_upt_ph' 'Vm_TG_CE_upt_ph * plasma_C' {} %whole particle uptake by peripheral tissue (CE) + 'J_CE_HDL_for' 'Vm_HDL_CE_for' {} %CE uptake from peripheral tissues by HDL + 'J_CE_HDL_upt_1' 'Vm_HDL_CE_upt * plasma_C_HDL' {} %CE uptake by liver from HDL + 'J_TG_hyd_1' 'Vm_TG_hyd * plasma_TG' {} %hydrolysis of TG at liver + 'J_TG_hyd_ph' 'Vm_TG_hyd_ph * plasma_TG' {} %hydrolysis of TG at peripheral tissue + 'J_TG_upt_2' 'Vm_TG_CE_upt * plasma_TG * plasma_volume' {} %whole particle uptake by liver (TG) + 'J_CE_upt_2' 'Vm_TG_CE_upt * plasma_C * plasma_volume' {} %whole particle uptake by liver (CE) + 'J_CE_HDL_upt_2' 'Vm_HDL_CE_upt * plasma_C_HDL * plasma_volume' {} %CE uptake by liver from HDL + 'J_TG_hyd_2' 'Vm_TG_hyd * plasma_TG * plasma_volume' {} %hydrolysis of TG at liver + + % helpers + 'J_VLDL_TG' 'Vm_VLDL_TG * (hep_TG_ER + hep_TG_ER_DNL)' {} + 'J_VLDL_CE' 'Vm_VLDL_CE * hep_CE_ER' {} + 'J_ApoB_prod' 'Vm_ApoB_prod' {} + 'ApoB_count' 'J_ApoB_prod * navg * 10^23 * 10^-6' {} + 'TG_count' 'J_VLDL_TG * navg * 10^23 * 10^-6 / ApoB_count' {} + 'CE_count' 'J_VLDL_CE * navg * 10^23 * 10^-6 / ApoB_count' {} + 'DNL' '(hep_TG_DNL + hep_TG_ER_DNL) / (hep_TG + hep_TG_ER + hep_TG_DNL + hep_TG_ER_DNL)' {} + + 'lipo_vc' '( (TG_count * mvTG) + (CE_count * mvCE) ) * (pow(10,21) / (navg * 10^23))' {} + 'lipo_rc' 'pow((3 * lipo_vc) / (4 * npi), 1/3)' {} + 'VLDL_diameter' '(lipo_vc + lipo_rc) * 2' {} + 'VLDL_clearance' '(Vm_TG_CE_upt + Vm_TG_CE_upt_ph) / (Vm_TG_CE_upt_0 + Vm_TG_CE_upt_ph_0)' {} + + 'J_CE_HDL_upt' 'Vm_HDL_CE_upt * plasma_C_HDL' {} + + % observables + 'dhep_TG_abs' 'hep_TG + hep_TG_ER + hep_TG_DNL + hep_TG_ER_DNL' {} + 'dhep_CE_abs' 'hep_CE + hep_CE_ER' {} + 'dhep_FC_abs' 'hep_FC' {} + 'dplasma_C' 'plasma_C + plasma_C_HDL' {} + 'dplasma_TG' 'plasma_TG' {} + 'dVLDL_TG_C_ratio' 'TG_count / CE_count' {} + + 'dVLDL_diameter' 'VLDL_diameter' {} + 'dVLDL_production' 'J_VLDL_TG' {} + 'dVLDL_clearance' 'VLDL_clearance' {} + + 'dDNL' 'DNL' {} + 'dFFA' 'plasma_FFA' {} + + 'dplasma_C_HDL' 'plasma_C_HDL' {} + 'dhep_HDL_CE_upt' 'J_CE_HDL_upt * plasma_volume' {} +}; \ No newline at end of file diff --git a/models/tiemannModel/tiemannReg.m b/models/tiemannModel/tiemannReg.m new file mode 100644 index 0000000..39aa256 --- /dev/null +++ b/models/tiemannModel/tiemannReg.m @@ -0,0 +1,5 @@ +function reg = tiemannReg(model, m, d) + +r = model.result; + +reg = (r.pcurr(m.p.Vm_TG_prod) + r.pcurr(m.p.Vm_TG_ER_prod) - r.pprev(m.p.Vm_TG_prod) - r.pprev(m.p.Vm_TG_ER_prod)) / (r.pinit(m.p.Vm_TG_prod) + r.pinit(m.p.Vm_TG_ER_prod)); \ No newline at end of file diff --git a/models/toyModel/runToy.m b/models/toyModel/runToy.m new file mode 100644 index 0000000..ccff834 --- /dev/null +++ b/models/toyModel/runToy.m @@ -0,0 +1,45 @@ +%% initialize + +import AMF.* + +model = Model('toyModel'); +data = DataSet('toyData'); + +loadGroup(data, 'toy'); +initiateExperiment(model, data); + +%% config + +model.options.useMex = 1; +model.options.savePrefix = ''; +model.options.odeTol = [1e-12 1e-12 100]; +model.options.numIter = 20; +model.options.numTimeSteps = 100; +model.options.parScale = [2 -2]; +model.options.seed = 1; +model.options.SSTime = 1000; +model.options.lab1 = .1; +model.options.optimset.Display = 'off'; + +parseAll(model); +compileAll(model); + +%% run + +result = runADAPT(model); +% result = simulate(model); + +%% plot +close all + +plot(result, {'s3','ds3dt','k1'}); + +% plotAll(result, 'states', 'traj'); +% plotAll(result, 'parameters', 'traj'); + +% v1 = getValue(result, 'v1'); +% v2 = getValue(result, 'v2'); +% s3 = getValue(result, 's3'); +% t = result.time; +% +% figure;plot(diff(s3)./repmat(diff(t(:)),1,size(s3,2)), 'r');hold on;plot(v1-v2, 'b'); \ No newline at end of file diff --git a/models/toyModel/toyData.m b/models/toyModel/toyData.m new file mode 100644 index 0000000..8eb1956 --- /dev/null +++ b/models/toyModel/toyData.m @@ -0,0 +1,16 @@ +function DATASET = toyData() + +DATASET.DESCRIPTION = 'Toy test data.'; + +DATASET.FILE = 'toyData'; + +DATASET.GROUPS = { + 'toy' +}; + +DATASET.FIELDS = { + 's1' 1 't' 's1_mean' 's1_std' 1 [] + 's2' 1 't' 's2_mean' 's2_std' 1 [] + 's3' 1 't' 's3_mean' 's3_std' 1 [] + 's4' 1 't' 's4_mean' 's4_std' 1 [] +}; \ No newline at end of file diff --git a/models/toyModel/toyData.mat b/models/toyModel/toyData.mat new file mode 100644 index 0000000000000000000000000000000000000000..9e082e506f45ec1c3db0bed21c29de4ac07e10d7 GIT binary patch literal 595 zcmeZu4DoSvQZUssQ1EpO(M`+DN!3vZ$Vn_o%P-2cQV4Jk_w+L}(NSSQxP%t#MGB&a@HCHe)Ff>sh5-`93qo*%FkbRnwfuUl~1&X)7+CWo6CAM%-*ly6Yl*~<9JZ-NA~vaz-}vr9b-=P%2~29?}-+N6n}AAuWR|2XFT?d&g~nbFVVHr|ijY`-Vta_XkD{&&C5oBF!4zxIXlWq!q0?l-dM zRqM8WkItz7*ZkpR>HBB5*7Mw1@cih;89ASm!*}nCHTt>lZ{F(J`OiY{ZJ3_3@^-24@zx%&b%-nmk{NDb#X5DYLi|+ri OG|c|A97B24!MOmzFc?t) literal 0 HcmV?d00001 diff --git a/models/toyModel/toyModel.m b/models/toyModel/toyModel.m new file mode 100644 index 0000000..82a305f --- /dev/null +++ b/models/toyModel/toyModel.m @@ -0,0 +1,37 @@ +function MODEL = toyModel() + +MODEL.DESCRIPTION = 'Toy model created by N.A.W van Riel.'; + +MODEL.PREDICTOR = { + 't' [0 10] {'time' 'days' 'Time'} +}; + +MODEL.CONSTANTS = { + 'u1' 1 {} + 'u2' 1 {} +}; + +MODEL.PARAMETERS = { + 'k1' 1 1 [] {} + 'k2' 0 1 [] {} + 'k3' 0 .1 [] {} + 'k4' 0 .5 [] {} + 'k5' 0 1 [] {} +}; + +MODEL.STATES = { + 's1' 's1' 'v1 - v3 - v4' {} + 's2' 's2' '-v1 + v2' {} + 's3' 's3' 'ds3dt' {} + 's4' 's4' 'v4 - v5' {} +}; + +MODEL.REACTIONS = { + 'v1' 'k1 * u1 * s2' {} + 'v2' 'k2 * u2 * s3' {} + 'v3' 'k3 * s1' {} + 'v4' 'k4 * s1' {} + 'v5' 'k5 * s4' {} + + 'ds3dt' 'v1 - v2' {} +}; \ No newline at end of file diff --git a/models/toyModel/toyReg.m b/models/toyModel/toyReg.m new file mode 100644 index 0000000..8d94bac --- /dev/null +++ b/models/toyModel/toyReg.m @@ -0,0 +1,14 @@ +function reg = toyReg(model) + +t = getTime(model); +p = model.fitParameters; + +lab1 = model.options.lab1; + +dt = t(end) - t(1); + +if t(end) == 0 + reg = 0; +else + reg = ([p.curr] - [p.prev]) ./ [p.init] ./ dt * lab1; +end \ No newline at end of file diff --git a/odemex/COPYING b/odemex/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/odemex/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/odemex/Examples/SBMLexample.m b/odemex/Examples/SBMLexample.m new file mode 100644 index 0000000..5f11ae3 --- /dev/null +++ b/odemex/Examples/SBMLexample.m @@ -0,0 +1,61 @@ + +if exist( 'Parser' ) ~= 7 + error ( 'Run this one level up from the parser dir' ); +end + +inDir = 'SBML_Files'; +inFn = 'HIF_4.xml'; +outFn = 'HIF_4.m'; +outDir = 'tmp'; +mkdir( outDir ); + +[ mStruct, p, x0, u0 ] = SBMLtoM( inDir, inFn, outDir, outFn ); + +odeInput = [ outDir '/' outFn ]; +addPath( [ outDir '/' ] ); + +a = dir( [ outDir ] ); +c = 1; +for b = 1 : length( a ) + if a(b).isdir == 0 + if strcmp( a(b).name, outFn ) == 0 + dependencies{ c } = [ outDir '/' a(b).name ]; + end + end +end + +options = cParserSet( 'blockSize', 5000 ); +convertToC_IDA( mStruct, odeInput, dependencies, options ); +convertToC( mStruct, odeInput, dependencies, options ); + +compileC( 'HIF_CV', 0 ); +compileC( 'HIF_IDA', 1 ); + + +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Examples/example.m b/odemex/Examples/example.m new file mode 100644 index 0000000..d504b47 --- /dev/null +++ b/odemex/Examples/example.m @@ -0,0 +1,58 @@ + clear all; + + mStruct.s.x1 = 1; + mStruct.s.x2 = 2; + mStruct.p.k1 = 1; + mStruct.p.k2 = 2; + mStruct.p.k3 = 3; + mStruct.u.u1 = 1; + + mStruct.c.c1 = 1; + + %% Custom options + odeInput = 'MATLAB_models/mymodel2.m'; + dependencies = { 'MATLAB_models/addtwo.m' }; + + options = cParserSet( 'blockSize', 5000 ); + convertToC( mStruct, odeInput, dependencies, options ); + compileC( 'mymodel2C' ); + + options = odeset( 'RelTol', 1e-6, 'AbsTol', 1e-8 ); + + addpath( 'MATLAB_models' ); + [t y_MATLAB] = ode15s( @mymodel2, [0:.001:10], [3,5], options, ... + [2, 3, 4], [1], mStruct ); + + + [ t y_odeC ] = mymodel2C( [0:.001:10], [3,5], [2, 3, 4], ... + [1], [ 1e-6 1e-8 10 ] ); + + + plot( t, ( y_MATLAB - y_odeC.' ) ./ y_MATLAB ); +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Examples/fitExample.m b/odemex/Examples/fitExample.m new file mode 100644 index 0000000..2bb050c --- /dev/null +++ b/odemex/Examples/fitExample.m @@ -0,0 +1,132 @@ +clear all; + +%% Set up the mstruct for a 25 state goodwin oscillator +mStruct.p.a1 = 1; +mStruct.p.a2 = 2; +mStruct.p.alf = 3; + +N = 25; +for k = 1 : N + eval( sprintf( 'mStruct.p.k%d = %d;', k, k+3 ) ); +end + +for k = 1 : N + eval( sprintf ( 'mStruct.s.x%d = %d;', k, k ) ); +end + +mStruct.o.sigma1 = 1; + +%% Compile with and without analytical Jacobian +odeInput = 'MATLAB_models/goodwinN.m'; +dependencies = { }; + +options = cParserSet( 'blockSize', 5000, 'aJac', 0, 'fJac', 1, 'maxStepSize', 0.1, 'debug', 1 ); +convertToC( mStruct, odeInput, dependencies, options ); +compileC( 'goodwin' ); + +options = cParserSet( 'blockSize', 5000, 'aJac', 1, 'fJac', 1, 'maxStepSize', 0.1, 'debug', 1 ); +convertToC( mStruct, odeInput, dependencies, options ); +compileC( 'goodwin_jac' ); + +% Simulate the true model +tols = [ 1e-4 1e-4 10 ]; +t = [ 0 : 1 : 40 ]; +trueSig = 2; +parTrue = rand( 1, N+3 ); +parTrue(1:3) = [ 0.6625 0.5233 0.2599 ]; +lb = zeros( length( parTrue ) + 1, 1 ); +x0 = zeros( 25, 1 ); +data = goodwin( t, x0, parTrue, [], tols ); +data = data(1,:) + trueSig * randn( 1, length(t) ); + +%% Set up the observer functions (3 observers) +obs{1} = '100*(x1([0:1:40])-data({1:41}))/(sigma1)'; +obs{2} = 'sqrt(41*log(sigma1))'; + +% Create and compile the observerfunctions with Jacobian (last flag) +[ timePts, parIndices, obsIndices, icIndices ] = observerFunctions( 'goodwinObs', obs, mStruct, 1 ); + +% Do a Monte Carlo sampling of random parameter vectors +N_samples = 100; +for a = 1 : N_samples + par(a,:) = [parTrue trueSig*100] .* (1+3*randn( 1, length(parTrue) + 1 )); +end + +%% Set up the simulation functions +simJac = @(pars)goodwin_jac( t, x0, pars(parIndices), [], [ 1e-5 1e-5 30 ], 1 ); +simNonJac = @(pars)goodwin( t, x0, pars(parIndices), [], [ 1e-8 1e-8 30 ] ); + +%% Set up the observation functions +obsJac = @(sims,pars,J)goodwinObs( sims, pars, data, [], J ); +obsNonJac = @(sims,pars)goodwinObs( sims, pars, data, [] ); + +%% Link the two +lsqFunJac = @(pars)useObserver( obsJac, simJac, pars ); +lsqFunNonJac = @(pars)useObserver( obsNonJac, simNonJac, pars ); + +%% Do N_samples fits with Jacobian based on Sensitivity Equations +disp( 'With Jacobian' ); +tic; +options = optimset('Jacobian','on','TolFun',1e-6,'TolX',1e-6,'Display', 'off' ); +for a = 1 : N_samples + disp( sprintf( '%d/%d', a, N_samples ) ); + try + [X,RESNORM,RESIDUAL,EXITFLAG,OUTPUT,LAMBDA,JACOBIAN1] = lsqnonlin(lsqFunJac,par(a,:),lb,[],options); + with(a) = RESNORM; + catch + with(a) = inf; + end +end +withTime = toc; + +%% Do N_samples fits with Jacobian based on Finite Differences +disp( 'Without Jacobian' ); +tic; +options = optimset('Jacobian','off','TolFun',1e-6,'TolX',1e-6,'Display', 'off' ); +for a = 1 : N_samples + disp( sprintf( '%d/%d', a, N_samples ) ); + try + [X,RESNORM,RESIDUAL,EXITFLAG,OUTPUT,LAMBDA,JACOBIAN2] = lsqnonlin(lsqFunNonJac,par(a,:),lb,[],options); + without(a) = RESNORM; + catch + without(a) = inf; + end +end +withoutTime = toc; + +%% Plot some stuff +plot( sort( with ), 'k' ); hold on; +plot( sort( without ), 'r' ); +ylabel( 'Final sum of squared error' ); +xlabel( 'Sorted index' ); +legend( 'Sensitivity equations', 'Finite differences' ); +title( sprintf( 'T_{SE} = %f s, T_{FD} = %f s', withTime, withoutTime ) ); + + +% +% Joep Vanlier, 2012 +% +% Licensing: +% Copyright (C) 2009-2012 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Examples/goodwin.m b/odemex/Examples/goodwin.m new file mode 100644 index 0000000..a382e33 --- /dev/null +++ b/odemex/Examples/goodwin.m @@ -0,0 +1,64 @@ +%% Model 1 +mStruct.p.a1 = 1; +mStruct.p.a2 = 2; +mStruct.p.alf = 3; + +N = 25; +for k = 1 : N + eval( sprintf( 'mStruct.p.k%d = %d;', k, k+3 ) ); +end + +for k = 1 : N + eval( sprintf ( 'mStruct.s.x%d = %d;', k, k ) ); +end + + +%% Compile with analytical Jacobian +odeInput = 'MATLAB_models/goodwinN.m'; + +options = cParserSet( 'blockSize', 5000, 'fJac', 0 ); +convertToC( mStruct, odeInput, {}, options ); +compileC( 'goodwin5' ); + +options = cParserSet( 'blockSize', 5000, 'fJac', 1 ); +convertToC( mStruct, odeInput, {}, options ); +compileC( 'goodwin5_jac' ); + +%par = [0.6625 0.5233 0.2599 0.9620 0.5402 0.0303 0.6963 0.9620 0.5402 0.0303 0.6963]; +rand( 'state', 5805 ); +par = rand( N+3, 1 ); +par(1:3) = [ 0.6625 0.5233 0.2599 ]; +tols = [ 1e-10, 1e-12, 10 ]; +x0 = zeros( N, 1 ); +t = [ 0 : 0.1 : 2000 ]; + + +%% simulation +disp( 'Without Jacobian' ); +tic; +for q = 1 : 100 + [t,g1] = goodwin5( t, x0, par, [], tols ); +end +toc; + +disp( 'With Jacobian' ); +tic; +for q = 1 : 100 + [t,g2] = goodwin5_jac( t, x0, par, [], tols ); +end +toc; + +subplot(3,1,1); +plot( t, g1 ); +title( 'Without jacobian' ); + +subplot(3,1,2); +plot( t, g2 ); +title( 'With jacobian' ); + +subplot(3,1,3); +plot( t, g2 - g1 ); +title( 'Difference' ); + +clear goodwin5 +clear goodwin5_jac \ No newline at end of file diff --git a/odemex/Examples/ifExample.m b/odemex/Examples/ifExample.m new file mode 100644 index 0000000..1bf66a1 --- /dev/null +++ b/odemex/Examples/ifExample.m @@ -0,0 +1,53 @@ + clear all + + mStruct.s.x1 = 1; + mStruct.s.x2 = 2; + mStruct.p.k1 = 1; + + %% Custom options + odeInput = 'MATLAB_models/mymodel4.m'; + dependencies = {}; + + options = cParserSet( 'blockSize', 5000 ); + convertToC( mStruct, odeInput, dependencies, options ); + compileC( 'mymodel4C' ); + + options = odeset( 'RelTol', 1e-6, 'AbsTol', 1e-8 ); + + % Time points for the simulation + dt = .01; + tend = 15; + tPoints = [0:dt:tend]; + x0 = [3,5]; + + [ tz y_odeC ] = mymodel4C( tPoints, x0, [1], [], [ 1e-6 1e-8 10 ] ); + + plot( tz, y_odeC.' ); + +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Examples/interpolationExample.m b/odemex/Examples/interpolationExample.m new file mode 100644 index 0000000..fa1a21a --- /dev/null +++ b/odemex/Examples/interpolationExample.m @@ -0,0 +1,88 @@ + clear all + + mStruct.s.x1 = 1; + mStruct.s.x2 = 2; + mStruct.p.k1 = 1; + mStruct.u.u1 = 1; + + % Note that you need to allocate elements for both time as well as the + % actual data. + nelem = 6; + mStruct.u.time1 = 2:2+6-1; + mStruct.u.linear1 = 2+6:2+2*6-1; + + mStruct.u.time2 = 14:14+6-1; + mStruct.u.linear2 = 14+6:14+2*6-1; + + %% Custom options + odeInput = 'MATLAB_models/mymodel3.m'; + dependencies = {}; + + options = cParserSet( 'blockSize', 5000 ); + convertToC( mStruct, odeInput, dependencies, options ); + compileC( 'mymodel3C' ); + + options = odeset( 'RelTol', 1e-6, 'AbsTol', 1e-8 ); + + %[t y_MATLAB] = ode15s( @mymodel2, [0:.001:10], [3,5], options, ... + % [2, 3, 4], [1], mStruct ); + + % Time points for the driving inputs + t = 0:2:10; + + % Values at the time points for the driving inputs + u1 = [4,5,6,7,6,9]; + u2 = [1,2,3,4,8,9]; + + % Time points for the simulation + dt = .01; + tend = 15; + tPoints = [0:dt:tend]; + x0 = [3,5]; + + % Inputs + inputs = [1, t, u1, t, u2 ]; + + [ tz y_odeC ] = mymodel3C( tPoints, x0, [1], inputs, [ 1e-6 1e-8 10 ] ); + + % Manually integrate + u1S = interp1( t, u1, tPoints, 'linear' ); + u2S = interp1( t, u2, tPoints, 'linear' ); + for z = 1 : length( tPoints ) + u1I(z) = dt * trapz( u1S(1:z) ) + x0(1); + u2I(z) = dt * trapz( u2S(1:z) ) + x0(2); + end + + plot( tz, y_odeC.' ); + hold on; + plot( tPoints, u1I, 'b.-' ); + plot( tPoints, u2I, 'g.-' ); + + legend( 'Integrator State 1', 'Integrator State 2', 'Manual State 1', 'Manual State 2' ); +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Examples/obsTest.m b/odemex/Examples/obsTest.m new file mode 100644 index 0000000..59acaed --- /dev/null +++ b/odemex/Examples/obsTest.m @@ -0,0 +1,93 @@ +clear all; +mStruct.s.x1 = 1; +mStruct.s.x2 = 2; +mStruct.p.k1 = 1; +mStruct.p.k2 = 2; +mStruct.p.k3 = 3; +mStruct.u.u1 = 1; +mStruct.c.c1 = 1; + +mStruct.o.sigma1 = 1; +mStruct.o.sigma2 = 2; +mStruct.i.x2_0 = mStruct.s.x2; + +%% Compile with analytical Jacobian +odeInput = 'MATLAB_models/mymodel2.m'; +dependencies = { 'MATLAB_models/addtwo.m' }; + +options = cParserSet( 'blockSize', 5000, 'aJac', 1 ); +convertToC( mStruct, odeInput, dependencies, options ); +compileC( 'mymodel2D' ); + +%% Set up the observer functions (3 observers) +obs{1} = 'k1*u1*x1([0:.1:1]) * (1+sigma1)'; +obs{2} = 'k2*(x1([0,1,2,3,4]) + x2([0,1,2,3,4]) - data({1,2,3,4,5})) / (1+sigma2)'; +obs{3} = 'k3*x2([0:.1:5])./x1([0:.1:5])/k2'; + +% All the parameters (3 model parameters, one initial condition and two +% observer parameters) +params = [ 2 3 4 5 1 1 ]; +data = [4,3,7,4,5]; +input = 1; +tols = [ 1e-6 1e-8 10 ]; + +% Create and compile the observerfunctions with Jacobian +[ timePts, parIndices, obsIndices, icIndices ] = observerFunctions( 'test', obs, mStruct, 1 ); + +% Make a quick wrapper which calls the model and observation function +disp( 'Finite Differencing' ); +tic +for a = 1 : 1000 + func = @(pars)test( mymodel2D( timePts, [3 pars(icIndices(mStruct.i.x2_0))], pars(parIndices), input, tols ), pars, data, input ); + jac = nJac( func, params, 1e-8 ); +end +toc + +% Use the observation function on the model simulation and actually +% propagate sensitivities +disp( 'Sensitivity Equations' ); +tic +for a = 1 : 1000 + [ t y_odeC, S1 ] = mymodel2D( timePts, [3 params(icIndices(mStruct.i.x2_0))], params(parIndices), input, tols, 1 ); + [ observ, sens ] = test( y_odeC, params, data, input, S1 ); +end +toc + +close all; +subplot(3,1,1); +plot( sens ) +title( 'Sensitivity Equations' ); +subplot(3,1,2); +plot( jac ); +title( 'Finite Differences' ); +subplot(3,1,3); +plot( sens-jac ); +title( 'Difference' ); + +% +% Joep Vanlier, 2012 +% +% Licensing: +% Copyright (C) 2009-2012 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Examples/sens1.m b/odemex/Examples/sens1.m new file mode 100644 index 0000000..3b22b27 --- /dev/null +++ b/odemex/Examples/sens1.m @@ -0,0 +1,90 @@ + clear all; + + mStruct.s.x1 = 1; + mStruct.s.x2 = 2; + mStruct.p.k1 = 1; + mStruct.p.k2 = 2; + mStruct.p.k3 = 3; + mStruct.u.u1 = 1; + mStruct.c.c1 = 1; + + %% Custom options + odeInput = 'MATLAB_models/mymodel2.m'; + dependencies = { 'MATLAB_models/addtwo.m' }; + + options = cParserSet( 'blockSize', 5000 ); + convertToC( mStruct, odeInput, dependencies, options ); + compileC( 'mymodel2C' ); + + time = [0:.1:10]; + initCond = [3,5]; + params = [2,3,4]; + tols = [ 1e-6 1e-8 10 ]; + input = 1; + + % Stack the parameters and initial condition in a parameter vector + pars = [ params, initCond ]; + + % Compute the sensitivities using the forward sensitivity calculations + tols = [ 1e-8 1e-9 10 ]; + tic + [ t y_odeC, S ] = mymodel2C( time, initCond, params, input, tols, 1 ); + toc + + % Make a routine that computes the model and concatenates the outputs + % (since lsqnonlin only uses vector residuals) + tols = [ 1e-8 1e-9 10 ]; + resids = @( pars ) ( reshape( mymodel2C( time, pars(4 : 5), ... + pars( 1 : 3 ), input, tols ).', ... + length( time ) * 2, 1 ) ); + + % Set the options of the optimiser in such a way that it does not + % perform any fitting. We are simply exploiting it to calculate a + % numerical Jacobian w.r.t. the parameters and initial conditions + tic + options = optimset( 'MaxIter', 0, 'MaxFunEvals', 0 ); + [x,resnorm,residual,exitflag,output,lambda,jacobian] = ... + lsqnonlin( resids, pars, [], [], options ); + toc + + % Reshape the Jacobian + jacobian = reshape( full( jacobian ), length( time ), 10 ); + + % Compare the two! + figure; + subplot( 1, 3, 1 ); + plot( jacobian ); + title( 'Numerical Jacobian' ); + subplot( 1, 3, 2 ); + plot( S.' ); + title( 'Forward sensitivity result' ); + subplot( 1, 3, 3 ); + plot( jacobian - S.' ); + title( 'Difference' ); +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Examples/sens2.m b/odemex/Examples/sens2.m new file mode 100644 index 0000000..89f22ce --- /dev/null +++ b/odemex/Examples/sens2.m @@ -0,0 +1,76 @@ + + clear all; + mStruct.s.x1 = 1; + mStruct.s.x2 = 2; + mStruct.p.k1 = 1; + mStruct.p.k2 = 2; + mStruct.p.k3 = 3; + mStruct.u.u1 = 1; + mStruct.c.c1 = 1; + + %% Custom options + odeInput = 'MATLAB_models/mymodel2.m'; + dependencies = { 'MATLAB_models/addtwo.m' }; + + options = cParserSet( 'blockSize', 5000 ); + convertToC( mStruct, odeInput, dependencies, options ); + compileC( 'mymodel2C' ); + + options = odeset( 'RelTol', 1e-6, 'AbsTol', 1e-8 ); + + time1 = [0:.1:5]; + time2 = [5:.1:10]; + initCond = [3,5]; + params = [2,3,4]; + tols = [ 1e-6 1e-8 10 ]; + input = 1; + + % Compute sensitivity in one step + [ t y_odeC, S ] = mymodel2C( [time1 time2(2:end)], ... + initCond, params, input, tols, 1 ); + + % Compute sensitivity in two steps + [ t y_odeC, S1 ] = mymodel2C( [time1], initCond, params, ... + input, tols, 1 ); + % Propagate the initial conditions for y and the + % sensitivities from the previous simulation + [ t y_odeC, S2 ] = mymodel2C( [time2], y_odeC(:, end), params, ... + input, tols, 1, S1(:,end) ); + + figure; + subplot( 1, 3, 1 ); + plot( S.' ); + title( 'Sensitivities Single Step' ); + subplot( 1, 3, 2 ); + plot( [S1(:,1:end-1) S2].' ); + title( 'Sensitivities Two Step' ); + subplot( 1, 3, 3 ); + plot( S.'-[S1(:,1:end-1) S2].' ); + title( 'Difference' ); +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Examples/sens3.m b/odemex/Examples/sens3.m new file mode 100644 index 0000000..1aa889c --- /dev/null +++ b/odemex/Examples/sens3.m @@ -0,0 +1,131 @@ + + clear all; + mStruct.s.x1 = 1; + mStruct.s.x2 = 2; + mStruct.p.k1 = 1; + mStruct.p.k2 = 2; + mStruct.p.k3 = 3; + mStruct.u.u1 = 1; + mStruct.c.c1 = 1; + + %% Compile without analytical Jacobian + odeInput = 'MATLAB_models/mymodel2.m'; + dependencies = { 'MATLAB_models/addtwo.m' }; + + options = cParserSet( 'blockSize', 5000, 'aJac', 0 ); + convertToC( mStruct, odeInput, dependencies, options ); + compileC( 'mymodel2C' ); + + %% Compile with analytical Jacobian + odeInput = 'MATLAB_models/mymodel2.m'; + dependencies = { 'MATLAB_models/addtwo.m' }; + + options = cParserSet( 'blockSize', 5000, 'aJac', 1 ); + convertToC( mStruct, odeInput, dependencies, options ); + compileC( 'mymodel2D' ); + + options = odeset( 'RelTol', 1e-6, 'AbsTol', 1e-8 ); + + time1 = [0:.1:5]; + time2 = [5:.1:10]; + initCond = [3,5]; + params = [2,3,4]; + tols = [ 1e-6 1e-8 10 ]; + input = 1; + + %% Without analytical Jacobian + % Compute sensitivity in one step + tic; + [ t y_odeC, S ] = mymodel2C( [time1 time2(2:end)], ... + initCond, params, input, tols, 1 ); + t1 = toc; + + % Compute sensitivity in two steps + [ t y_odeC, S1 ] = mymodel2C( [time1], initCond, params, ... + input, tols, 1 ); + + % Propagate the initial conditions for y and the + % sensitivities from the previous simulation + [ t y_odeC, S2 ] = mymodel2C( [time2], y_odeC(:, end), params, ... + input, tols, 1, S1(:,end) ); + + %% With analytical Jacobian + tic; + [ t y_odeC, S_2 ] = mymodel2D( [time1 time2(2:end)], ... + initCond, params, input, tols, 1 ); + t2 = toc; + + % Compute sensitivity in two steps + [ t y_odeC, S1_2 ] = mymodel2D( [time1], initCond, params, ... + input, tols, 1 ); + + % Propagate the initial conditions for y and the + % sensitivities from the previous simulation + [ t y_odeC, S2_2 ] = mymodel2D( [time2], y_odeC(:, end), params, ... + input, tols, 1, S1_2(:,end) ); + + + figure; + subplot( 2, 3, 1 ); + plot( S.' ); + title( 'Sensitivities Single Step' ); + subplot( 2, 3, 2 ); + plot( [S1(:,1:end-1) S2].' ); + title( 'Sensitivities Two Step' ); + subplot( 2, 3, 3 ); + plot( S.'-[S1(:,1:end-1) S2].' ); + title( 'Difference' ); + + subplot( 2, 3, 4 ); + plot( S_2.' ); + title( 'AnalyticalSensitivities Single Step' ); + subplot( 2, 3, 5 ); + plot( [S1_2(:,1:end-1) S2_2].' ); + title( 'AnalyticalSensitivities Two Step' ); + subplot( 2, 3, 6 ); + plot( S_2.'-[S1_2(:,1:end-1) S2_2].' ); + title( 'Difference' ); + + + figure; + title( 'Without analytical Jacobian' ); + subplot(1,3,1); + plot( S.' ); + + subplot(1,3,2); + plot( S_2.' ); + title( 'With analytical Jacobian' ); + + subplot(1,3,3); + plot( S_2.' - S.' ); + title( 'Difference' ); + + disp( sprintf( 'Time taken without analytical derivatives %d', t1 ) ) + disp( sprintf( 'Time taken with analytical derivatives %d', t2 ) ) +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Instructions.pdf b/odemex/Instructions.pdf new file mode 100644 index 0000000000000000000000000000000000000000..846b730f72349df60ac3a5580b585e84254d8344 GIT binary patch literal 339824 zcmeFZbyybP);E45NT(=Wf^>I>iZrNncSv`)NSAaXJT62D)Ynf+?_$rRqeCk7|j#1rYm45vU5kt7#C$I6|g$c55 z7-znsc2&S(JZG(u9(k84gE@`7RjJCT0shVe0=bR$syX?Pj*3w1{V6iu?)BZ*p0~Y7q-hgTN#irzSA)> zKxBMvX<=tzVP{JMSr=JEMp*+}OM4qV16va2Ulq~@`o=o1ES*Tyn1BinW)>1oZWawh zpt}vwkA&-?m4E=rZ}UKU{l2^+z}Ub#1B=PbLBa-U2wbvokg)%D$;?T@@%tq^3FpHl zu-1(4Y%KNU4D3kM03wA&NEqb}oa{(605SMulD|I9??S}R%=)hiQK+(-0` zu7j(kP5JTLkKtOZck2lCIO>xGIqCXYT;vQMv$_%IqBQDB;W^A)JVCzkGeCCAFufU1 ziis3-r|7E;-O#>ca!&No*yG#{-Oy@FoL!p1r(HSM=DR>1ypKPoP_WmNePLncEx}BCgC$UpQJmo5^l=Zw?%zF0a^%B>TWO?L`KdKg$ezNfQYGEIXz3rTz2lkAU1o^Zw1loM{3U=0 z?lkZf#}{uX{@!oBWC;iMeLrB%(QF3;o;IC6=RtOt`SpVyu0>cG$1{|s|fR$PEoTS3ASbN{kU5Fud7Cdh+a>R6klEB$n7=WW+< ze$Y`#nD~@;n)Zu=10|UXx}p7q(u^i!rl_oyHbN8qEL$olioGGnCvSEci22XbwL^8) z-_Y%U$RapbPObTon;FK_%hffuqnl&*JOa9f^M$z)Iy!rS;fCWFw5^byuc=k}JRmA@H(OrUDpqLZ#kLy~$*t@xSw+jvKN97;Z+ z0=ZcQX<$WJKmnz2f8q}Dr6*HSb*N`TY$JyKTx_`nt5vW)3~6|6QO{i-rFb^&fOLgH z@~0`dI-mF&n~V_lT$E)i=;r&4ySmu$IBcuehNEX>>2hQ5=em`UdJX9C(fTGIIA9nu+id z>z;jw^~pNHcP(%cs=KfyHhQli92X-WNm|CcE79q!ZXHP<5_(-ERX+$PS@ZcTyChSR z?mhwOr3c)3wu-lNK2!?L50xx@Fx5B0?El8(bP z1Hn{`BoyGeoUI&<7YjB!WZ9zYTP2Kda44S$s#XqP*5L^UVyh(P(w1n>FgJg@)Fkox zdB@n|RVG~t9TbW`_;Zr6NJ#6j)!`|T`ApsZ`BV(&ZTQ6N0hMo1j+@O|FVWFEX?x(G z!z4LVbaKv6VrK~PbI;pwi;`(X{vbt4uay>J3nAaRb|iA?ip`wP$y0^l$MA1hd!?3Q zK<|~63wf z!hJk*z^mNhanCJ7kfgC(1tw>Q{VAJ^ObNBa5X|*?U)yurU5Q}$=}4s*i6Mfqlh+0( zKDq%LXgCheCS%I{$%ac@a8l?ks4@*3Id4rM>cp+{fDW~tTQ}1zGNym@R`R)TzZvM% zw@OZ8=0$NvK~o+HZoD3ds%G**z&q{>} zTM(KPIdMfsU8?F&g`Av%k-qS~Iy0^cU4?bRI22Qg%UwPTfZ3aG<+)0PQ;nqWSKiIe zQJux{=}s(`<@Yx)ZQ78G$s!2XV5v3O){80G#0#cs=|2**Z(m!^bSp=PuA}KpdQS3Cx*vTtun}!5Nq8{Hu*V}QM8ZRmZnvi02>0#A z4Bq57PGkvqZ}Lhcdn>&n&n+_?8?=sZ3_rKiUrK8zs)dQ8C9b?= zJR03|kjx@A!QX1?g?@~Oe8i8EUwZ3UMWrO};D~IetaH?NXId|W9+CG{6Py1iXxeU< zIPe&{*fb2Al9?@NB0FOvP)(e&UmzQkol1;SH^bPV&vQZiv3Pju>j6<*#2&{`YZ^w1 z;0T^^X=_epk^Ux+z!;_PEO7p;UM=bpCDF3=Z`Ef|W15gSJ2lh;PYmo9_bJFHHq}o9 zG3hUtMyf-MUMWaPVr5U^6JeAH5N+Zw+sY@^UZtry^;d)U)aOx4X1@2w!HC)+@j*|_ zZ#CA-`F?o(qUV@>UMTT|n&LPQ^qS~E-7;oq40?9VEH6rw?a}or4Teb4R_vEVo0sxi zbhEn^c5$5-oW6#JJ`2aTPI78lFCF=g;Vq?7EvOx`Tk$KAz6iAAzg-b0cQfw{RB1&c zAds@&^W8GP*^btGgtMQnqkALdj82A7i_sF4;L%BDh~KnL?Hz#QRs6 z`#ZJ;z%MrmfKq<}VOAy*=3k)rU&Fi*eEj=7zhPcxZYIuu74v>klC+)SLT=trx>)q# zE5?1F@uIMHT%2d#ILTr~z+sx`X$Di4+#dYY&4AP%2oH0-lx)v&xvXAjuGBv@d+zSv5>NdeE_Su(!>2Q@`H9qhSX77g1g#1bAl~r*NRSL zy@gn}a+YoIHSxON=5|)y)EL6;RubVqZP9KVz=LW`j z-@pIm5%kvUuTJ_Fd(56XXz55AeZ(wANAFV_z>j{+tfBG7EOYbnzy6cilR5b*|=#_0z{z9aDT(8b%5n=8+o(vrk&)#PRf9$Q|_) zdRY`IxDA+}qQ!?j4!pNHM3GwykQo zqWv~xWb=?^|9clF=QgzltOh1CrzXzC*E}j>awd)!92KdVyEA%;D^#Ej=DOdI2I6t8Vd2Eu)Xaulp#F*XiT4|(BiC=F*1~kM#Zy56of>1|wcBWMg-Q9nE~L5<*DtoWXRE9jj$k8j z;3+BZvk(lQ>hqCcrBc8O!V{dGnMh08%|6bI_A*0((@vt1#jF*hnkgLZ;pRcLw3)VU zMsn74YO!2o>j+Xjz>LH8m2H)$xQh zDU2`rIie~3L=7jC8pUJv%}<&$kt8IV^H%f?MU9feky6_{3)IIT4GIW${OT}Wx;*Pm0`Ddmlk8H!s}P)xqdtZ42&>pX|GhOu2+{NgzK zz2^s0-sZtoQNY0amiBJkTPnSVswL=s6spw&b;-f7wfrlxS#+YDrTtpcexqSAb={Qs zM=3<#qd28fqGuSUGO)C9zL;2lR_xR~y~Sn9%Y6;~YMw!U>@9urO?-)U+fCO5jdRu$ z)za*QVmbq9=|}JIUUT&v-Spy4ui_aC%4@{Ru(~WGsFUwJNX2m; z<5WUFPGzpKm@l@ZhWSIHKG^9FCaO`{hLZll+891TKkhI=wy4#+qujal z?DNRJPOccLf7VxH`QY2jw^zBQsf@`^ zQo{9BYfgw}lFYq@epxa+VDk#!URG!WW!Gb?xw7zdO7Lya&((i|N+8*;-(C1WMKvh)ip8DvqNN*v)8qINC1kPKV$%vjP-#WEHeieGa{pyfw9pC zI}&boHbll(#&)*v3~XLonp;^~Jf!*{*+Mf*8#yZ-Js^K5Y~Wz5XCN#3>W@4wGcy|( z(D7Fa_ir+|Kx0TI7swf!+w$@K8U{!?LN4shEr47jF#A855Xb}q*+)G)OB)hqCIBV< zB@vvwGxyykLjuq5y=ltqJv}QN-yoNlmvWydSXDGox=Lzi=WI?;9@lRP3IrVAE{4HK zkPFaVxFHvFQ`XBV#*`+{*qA9Ghl^ws%dTZR(-iRxAID~@!V>U_l#ze@bbu#ZWFv+ zyfuhRdKn@-TMJph#xw zM*9%X2o%ourPi-lhTveUToK!ORZYoS9KW=+8`~pHbgyi0cH7RfaA9Umew{MB@m3ih z?dk{GEf|}~b1>E8HrXkl7NB*N)d&vcuF@PsXnA>S)psm0)YKN{qUN!>`Spr|5ou`0 zzrwXO;(Atj(lYkM1jW*~$EUdff9~a0tRZsVDM{K`=rCg`L!nGmGDf8pEZVQXJ(soqHQ?fgf*3+Yz1<}N;yi+$^UT-CKG znAr3r8&i)sct>-tzMH2h1xago|E?PGvJeiW5MK%H1z(6A?(4T(q5nI@ML+x=HQyxW2)5gZKVdkzzw&@%#o|jYGe8B$Ayc?EwZZq zPJ((7{b50CkgDzwDyZcA2k!u;68g23cwzrc9nDlD(zW&Q)eVo!euGJ#Irw1sVzb&- z++ZoH5l^sg_1f)f%VQ~=-8EoE@)1bD2pGYF;%v3l7OAnb@zzJqsc^-${4LXchFR&* z?p)m(KINoLT-D6&`@5rS=Y#Ut%m7hXw77}=84dB%{hL7Vh0U@de_E&yet={w9xerp zQHEa!?5I$hh40gg_Lf|wh~lOsH~Mc>9RK)Ibu!JnHy8MIZl&ecoR9h0wNL(Q&;^RE z1IUVXW1fi7u{C+zWy0NJY#5EWcKFDqeQhBxRB6$8A_a|Ct*a}H7@T@!No4ALSX~tu3 zL2YykY2_Q*vQgXKIkwPE3g*IwQk=l-oweu6sqG#%252@8cn&enrWit0%dEOBaGW5P z!t$J`^SNZoFxs4QZx^&Zy}M&0$SQl@w@`Jkfx zfvEGhz3oeITryYO*<2$Jzee3vmJFX_%>MDwn%zz5!REy9VTs^s?EE6 zHvMOW42%n!YwrcrCyo1aE1Ucni;s^R=bHR6(aMu3YWJ7$B~{&<%xCWqjui_9E(Kan z>2GgNZLdmWwBdyCck*FCBP0`e$AF!+7z9QY@`;^5+78l&1I>N`tnEn7P_V+rTVhZh zFJPe4RQl(jU95D6;Xqz&cP}9(8l*Dtw+8%1qX}eTsE1uMwPq9By+Z_P)7p_tSWQ=I z$=_&j4k?2~)_0sbEDVxFHZ%$AT_38}cet{mE8b7VQVxU>ztyVvRf{Y7Q#Hf>9s*)^hfr~(1;?QJ?q!cUc*kp<8&lBtE zD91+EBcSnLoQ*t_jD;ZD8ZaZ~T;s!-OxFCoCe!?J^Sx(~DH;c+-gn#RS~&FYJvg$E zfvLlk(2<&%Md1fh$o}r}|4aWR3An>8_SXC8Wp)H$?CY;S7D<5Y0LOpa;NQFa%SIOn z!)ui!xNoaFnB>(FK;}$;EIV+^%|uVpf}o963a(Y{-&utJ28ifi03)RlW=C(X=-||# zIoTsamTr9~Pw&Ty1a-e!O$!WA_KM)nihOov!yW*GHMvB%Y(hJxx- zpmKKLkh613bB2w#;QKVBZ-Es*FAY_8-Zi999bcK5DBH(o!b$OUbL>!lDil!KpDJkg z&~>{TKZ(ykU}Fb)D>t;Dn)~cWpjL#tKzNX3BB4FqdD^6a_9+es)BrvZM4b`n6t;PM z@nkT}#Nqzg=$4=yWbmyDxW|z5|3&c3Q;88U7P%7Cxh)PjenGTQsukCb1}mTzHIOpI zHvq?jL35vqH^R-;M*a$-yZ}Q9X#ltYIR0M-puget*p@@RhA((HYUZnsZY3>NL27&w9;(x$=Fdy0=ZW_d+ za1EaBc*e?RG!@whu7XctqUgvCldF&#+im7Rs+_;uJP0*q7QfpePrkV?OD|*_#vVUNGoqvrURx9hn^3IBP_^28>dH?^% z%?HgvlAtcV`+(!8D0#rALCmBv7}pgPSh^-#{R% zL_<*n26@Qk!SjhqvZ1yuqi8fhy3cTYb+V@3%f--61zH1l?Y1wHbnQ#che9Fd{4YUw zp5e;3$-}OV{5cwMg zaQs`2VQqg4m|iGPwr>;KPbaU50F?HJMnFVb*+>x;R2TGrpmhJD93&(PxD_-Uzw|R3 zuXn%e@&maSgq1d}7{6EjZ4zVI#X+cKj(c05d7Jg5A=nSIr(h@ z% z-dfZGO_v805L*C^wJ#N&&tRPtPjbRzAeP*V+}1(<*d!~g@Z_`bj7QkrlO}_end+Mb zSm5Ro8-Us8eLiZL@EQWpPzZvCR4jO&&uEk^5x<;?l8dATYBwOQ=6sd|e5y0R%7CB> z4c{=ji6jz&2WsNEZq-CWfVwob?uDm?uI81NbP&4rnT;ljZ0qMj@PR_>8sO^Ml&?}~ zmx^$jd4xzIcn`o06LrL?uq}yO1%ik`h0qKnW?(|Dd{uk9xkV4ufB+ZCzB5Ovn4M<6 z5GeMboS(QG_o8K!(;z)QOa0*oA+7&jZFcZyimWpO*A$COIV|1n`50?8sAAcPl{tXncvWVuc=ARTsQ!MMsNUA z*kt;^(%A^^Mh4`LcM{auINv~;#uw+WXDYiOY-JO#+-^S!vp6l*DBRaGZnX%REQSocL%N!Ym}1$ zRUl1Zk%GY-l#`IoFhBvr_raHA4NTdmM_0IRLmA4rC0L4@--bsKKa+^u-KPKo_>_JK_Q$CNpuy$lnED09xb$|+EfS7MY5Ks@Q)dm>Q!4%?aF|{cb z2QojHK?ZC7^XM8o+~QS!v4v<2ggp1}5Mu*6GX5RnY`5EdEs55h zhKx@VWjIl!q+n5V{b`U2(rgqG?0e{hI1XQTX*Li*s%rj}K|Ibzzqu{uu7`)sh_5t_ zee%E_IS3OC8mCSlmQXBb%Kl~X1ECm$VLXbAv7Dy9m3q;_z+heqB@iEzIbX=n3>loq zXecbvL3G0~ZW7V~0x4U{W?}Shln|Y6;$_R$80O|W z^JD5ZPFDY6Au-t+HNQ^RRO>1x%_&f?sn_s2Mex2v2il(19r2O@%Q~iYu`$FxuWW!< zVj+OJ0u1x>$FE3h=jHc^DJ@rHU_~G-5q-R3T&7eCagS*jfGy!OY6Rah#KOg&KG0;t z57C>lS&R%_cKrQ&Yi(226(^uAsFAIaK`MI(yjLDIhG5y}P`YRGTXF;#$`3X}Eb~u|O8eV9)q^TF48=T5#A58A5nrOuY2N_WpoWkumIj!k>Oq7DHSoSG z(FC<*jzH#kNM{3QAYpTweRKRPst}?XEWws5NSbr%)rIt)Oaqu;A2)fZH}#-5p@tI} z5cm%1{ajwETCIMkCq*cUc-3wY8zyvR`>`VH9uV)c0JA4FuV&G8x2(8#MCD&;ghe2%BsY zH7aw6IPr7v?-B?hPFo0mu*AA_D9D|Q86qhpF~75>u{r+1AoLh5Olsa-G}vcH8xY&s zFaV7pC?g{IUwv5P;hUT`72x)0|Lg&r1q%_NT-dulwbIl*{C}=Hp;Fa zp-~41@SM?`B61J9U;4q}COT^Ofkwbm5vzoa<35OhvcXW;m1gI^6>0wGMcRK2ZhjXl zh~fX=m1u~;VdD7u&6T>Mw4^J5jqqj3uF_; z8#bUlY98E|DuMnGod$$gzUQ(uOWl9GHi4m(GR&o zFaTF~G9mk5O}z4)pYBB4q*2&I>=*9^#D0g*I+&90=*hZ(J|o2|mO!1 z=2oN+!03Mx_Wb9y?>`To{u|lp|5aUq9IBT?v}}qXq2JORM36yFK$baHC0uR(x3@L` zVwPtD*BaYde9ew#!Ouy0u!gNb2wUJhWLqiEiPf+M)%PGCKpl;h!NaSRpx+@3kmgWM zL4Lq1FM;G-Ga6uigJ%&w0y9;0$1LCiDeJS#PhW5VpZ9ytZ+%wT#6|+*v|52EuK?r0 zs}}${6g}R_&|1N_yNGTOLQ4U|{7j13!kOW=sE>OJlAPBD-rjlWbITg_KwPzU3_uT; z^1}azmplKf*#DnTBK{i=4}#>1sn=R|=e|cKaiKqcCl_;nZ*U~!Yk+}OfpS5bdR)d{ zgDW+v>RUe+=?{Es5w=npXPDFt5uUW+u;8Lcje|yzg455+73D_e*;zHpGKda1iKG&C z1G%3k9Wh9TxuxWekVfPQgrXI19^`zZD0B^H^g+%ufBqJxU+n~p)%AWE5&)WB>1{Yt zu<$O!uK>H#lJH7{~m5!9`7P8`UBym8&}v$ zZ3!fGLXsfB%TR&1!;$&`D$)U|7;LhC^bqwLolIH#Qm3mi_AGW@(X>DR<0n91x>7J+9xGF2=zf( zDk1hU1}3C!BS2n6MYc@TgT~~%w0NXn;dM1Zpm_*yQfFA_Ng{p$0GoYX{S$LyjaO%D|2hoRI(e0!`!K+Kc0n(e?wml2o-2Hi~1h z_--%H#fEX^59izmWG4U(U(E=*H{l8{k+^&!x<+k~rL=<08nQ-Og;NQw@K4QocMe8V z^=RikZnkQioUPW#b&DmmIB1*rM|0@A%-CYrzXsKQ)mVv$k)#>c%hE8b^vNHPR;8(% zBCK~AMUe_}Qi z0tCj#L7leuIBdL)%SjCJY9UpYDp<9nFRFPi%JUY-tE!9EkN7N+>yP9K7}EDFpH4#v zGK8D$+RBZK(_9NfExIt#iZ`llIc=Q0boSZRbSSj6*c^y?##w7uRMfub(s52Rd7*I( z!UTWW+P3#B9a$&+8B<*jI!IkgJ<2}9-Uo#a&=WQmeKe@Eop&wY{@ReL`oR`sHdufc z)KHg5^wE=Ew7Ptae7B|;^y%?k%eDfKy zoHxT&n9?gy9vCQWEVXv~F-c%Y~s77=P7rPgmA4B;2M)LfpIBn&zw(a)ILu>gyZTkO?WqN z;Xya3g}ol3LC_%1>|s>UPdRsglB>*RkkDH|U_mEEQs!0ar_!BJUINO%>%)^GcQuQv zG~hPzZ))1<@we*w7wxrb(81{&W^MX@*^)gWhz&#n34m5mx==e}jzWQ??%b{choL>g z6}Hd}1M=D*0p^t;^U-{_FWn251mTGO*%ar7CA%z`Wo4R&wuS z-Sv+-f4l|X?d^ZD^2phVapg1q;_6^^%hK2KX>J<^)RX&bO#Oo9&$gFady&IOi+u&7 z=kxC8pN5Cz41ISU?w`>4JqBH+0S(h$``5-3I=$Mpe6SW!AgeE6IN=Y$(4fhzU$>2P zx>Mc(@4VhUj7!uv?3?#OYppxiqmK0S0MjDnEPJK6{4t0p2Qn>(s%*jKn9{;^NI;a# z~DWE`^#@=tSltV54$yxK>j!T?Q`&l?HR<)nMoiYjLSaU z`KP-tFg|=N{`zlrVPN^|Pj*c!T!sBh$ z1;e38DP2k%CG7GI?unfJ!YkBZAB!`!Odr4I z=CK`%O?qzAKH!9p7vW0-ycY1iiSGZ75til40Q zmw0(~y*-lPbVx{F5gtxJnItW!Jw<7*rTxeOx&a3_K@T6-l-j&G5iS(aR`Y%aKW35W zVCkg1e9-Y@e0{zOh_o*|csRDG%yZjF=F*E!+^Tj_h}AeC%Tps3U9SfbKzaFi=Y+ z){PfMKIEt{b2`ar92KK=l51>y_6g;?mKF-h5vFd_uCVdN_y$SU0_w?3_C%s99O;uc5iToC$Y6YbomF{$#dy8TJslD0nW*tcXF`;e z6dD-@WXo9!y6s9YA}R|_$c4jfgWrc0&!|_O=+*W&7MtP<9z_V=b)}hZ@E(fLQ|QxU zXV#D01jZn$Pr{*26!4}iNTb462;xEy{#01GDe1@>jT#}to84QaX{GofAs6*i;xW1r z>qiba-zr`qi*Pv4@3UN7YVP;l-CH zt(V3}88NPxYdoXFERx~O_;M&xby!0)ony+uUn3wtM^sk``|p)G=0(SM*Z zN)`Q+YIUxnH0|Y*uDEa}OQj{eEE;2v&vl7HYB5qkAX}caXNB*(BQ}*F{`J9||9!nW67nfS2 zk`qVTrHd8Jip~8kG_)9#fPx8wsP}cw&1b&t%lD}PzRV?uTa``D-+pH3)#_b&zf94g z$BuoXoY@v{8{D&wMbd1f!qC!nH)8t}iL_xMjLi>vT6GrBeHDR}N+I++frQWM4JjY3 zA%-I%kCF|GgVg*U4UFvBY09Vx%k=3pF6hTO)raf6Ow{g zD>KY78ND*@Sk9K>%%qIg^JZR9sNtf>Z6lfQjMZ14aQRSCwEIUWQt7;bCE#@s33uS% z$Q|e=#5(z&FeXFS+`~7(c>;^`rN#C3c>6rqkaaD1|MCC~9@K@6@8Y|;f;p%uh#R>m z-|oJf$aK~YuZxeMut;=ENbPy`xg-j=Vt?Rsh(B(i!DzsF5xb|IvtZxsfoJ+z{S4fF z=}fLx_|Knbx-M?FKi0jnQX+-?tyf)ouasZ1CHtC1qodDQFrvS-8PdsZr2+{3GXBB42-8rQe@#S#82Lm~0 zbD^2cH}o$~%KEfV}EYD^DcYO51@H zPDBYWJFuOe5Q$TyH6O>5{q}?R>q2nByXmK}*cNPWKXf=V4B(zy_`j!I7n4v^v`hLN zVwy6-`Pvi5MQPVudT$gZ(>_f)__LunNcTDa=eNVxmssDgiA$KvB3BMYzV;GGA*Bm` zh(QN)!6?vIex!?)C+QJZ>m>J$tUi_)i|wgd40jT*_?dH?$0}VC4NZg&m$faHqS}T% zqV|*Gx)xQ``?FN~xL;R@SnjY&nSSP@q+Ktkx7R@2tj1TJeLF=JCf6xtS|@m_g3)?3 z>F(eX=ssVY#rfsYQ;~rPv}*d%bQ#MR303H`#11`_n_I{%JC{m>rMo-MO#++@LFv^& zS)ny=g7xTw#o+uql;4tek_NjQ(d==6NJS@}kF!lEzIvs(v@q^9GO?a6OiW{ZeUlj~ z(@#~_R*cQ1a8FhCju7*)-X|_LG|8aN+`Xr7lwltRc~F zbm4Z;Q&Zs;Z>B4uYs0Q|PiI~EO|CYzXu>ExsgvgBO+m!=Sbi{W{Ifj~U$sJX!Ggve zwk9!mPSlLC6Vi#iw?Bl_n>crI)SMOCU$|q~kku$D;#i+LmhmjS-q(S3|1j89Wpy6; z{zH&=*VL!=+-I8H)wrJ&4 zHQgKo9&EbNy`cPQQRmji>zndvRv-PhKRLiI7FuAiCcQKk$7_uc^D5y%Z<%)~wf#sD z@eV~*Qd*-cFRUkwxhTSl75WtxysClZyID*FA{(r2*OLkC6HD zQj(mxD2`HezFxrzhkUkK%|#4#c8BVzH`Qw%$f{r8fuB~61n7CIm32eI)>J(f_#Szt zms_Qf8Z(v2i3PJbDYm@v{i2-7pD5*-&OnW~0Xd^fWAt|3VtZ)6{S33)x2p=hH9|fP zAGV+sIZyG!>jI8gtmV>N@Mr9S>I8Lx=d;L-XxU}NtI;K}v^+fAR{06y2CWx)9}S7L9Rke_7M#W#T$u+Mm z$<08*+!n1*Uz{0wmG%s(>#PMEE8t?LwNh20F@}gff=$0|{8i53{A%^1pa~tkcn5dh zr?(?p=^rapDklSGwUDwdS_X!=#wnSaK0RrX2pH)T38Ew_|2$X{efsnpH~N5t)1Bm- zCvaKl6(B|_I4+0P3q1;(=o%Q@`Q&4dS2X1!^;S{un_jh3=R4OppdMv6YU45r`Mf+Q zM>AR4mOBL-v++Mq<#$z*h1?32pjCH6Q8vvtvZ2f3;ji+18RXBNsL7my4$l z=LwYK`#30JOJ=9Jp%~~SxmEs+*tNa+gn8$=da@B~{ZEPJ@g>C3fm4wUj&bn5kIIQv zL{ex;`~{2+^{Z@DiW^q*4eGm}o2}+x$u-G<7H9Y4K~JbhqwO~T7zMHXb*GJg`uprd zMDn+r*geEG|Mu^*%zyoV_RoOpFVWOrck*EVOC0t`ki{s%%1pxYu*(Q!*E`_)*Tx_J z(qIiP+~7)<^q}mQ|Qa2n}y}h*Ejy`Co+R_Ja$9lem&P-`9o29-38u zi8(9^=wo7ttpppMaZe6oi{si2q1McJC+D?}aw7Rnmo38b#|Jm<*_*~5IAjF zp#I3gYY<3gl$VF~+)MPQTn`#l$#ulX3LA2|APlSPwYp_u93x5g)Nqe~ zQ~4&@FCp@$Qk_U*&P!in`=i%9V(=OGRdd`auqZGcs^^LC{ihZ4@^D`TXEt+Qiztb> zJ*VX2A3x?|qVrT=v?;(J76`KTj;i)Z0!c zo4lCBdHlvt-VN`n9FGr9979BMsr4sj2v?ZOy-eqgRoAM$!&#}eTa;r}Nu&ENv`_e!T+5dU!o$v5Axkmx5?<2ph=TeDl zk!*iGpzos!NxwQgjbtjVZn+k3Ms{&klQUn`83ZG~Fyizh_goQIbJVLmoOG5IW7iMG zVhsH*^Ua*|jPCtod%FEJblE`|=dxnw&}ZBcM}hs?mwZY@+qp>@UXR{plCQk?x_Smz zM-jVO)!M$PA4E$OZ82B3H&B#m5;mGY!W-U({GMkrM+eQ+Me3_o)uM?Jev^fM%#vHE zXwgcU0PJv4W@wo}1T}b#?wKWt`Vt&1|0h`(eCW$|i;l_{$1zw)-HfUEJ7?bPE|uv@ z?>PB9zA=YRT>MNwPOoXrS@DjUvbdj&jRL*wd3j96{oygHg`)=Ae!sAy|Fm{AcT-f@ z*sW|HmewTtb|(9UiwTiTmwPWxlW`9;=$^DZ^7ql+}d<0Xfl{{Ed6!GxG-O3FY)Q{f4mxhN4w&e9>XH!01>1s*tl>v;{Sr$37b<5d$@=bC##?GQ4u$$r{d zfP0)@x_iXJs z&9Rr49K%OK3qg^*vSvqYg!WJK)%-p)Tq0bGp1y%EwCq!(29y7>tUWk+bXI8^eV z>7(`OYoWT~N)W^;x(V%x?ZCywXILMF!_RkE;yf`%9A?_!%QElrMw#L71k0%Mop5jD zT*sX>q1>?C#4ka)3-?S;5@RcyC+9*sDE2mF-`cLf)K5%KtW*uBmiP^)`rp;$ZrPm{ zl%G?EKTAR5Q7J7^D!qfo-YW9=Cobo&iMN05avpXt{p*emEDxJH{o5|*q1(ThT^?kW5j0Q{MlT;^j)p6(5R&60;(`5+sOStDNq$yXhA+dDt%CEmAB^44cNY*b3 z1mDIpTI^xH@6pf0R$bu)FH>mTY~GfKRL6}|)DKp!Nr?1a$3LAq+D}4L5}Z3(UDRpK z3R=hb)KTyV1DV`8jy-95wl;?*wG!Ku_YF@Y;=q{GsXmu4uif{yuh$S0EC;j%lvJRVKaZL^;Oddfm%mh7_o7Xwy+#!dgplBEp?Ku65g6gO)IFj zOvTGHDgKERh22kba()zy3VP+wuI%<68n9(E$L=DfXuNuz3*SwTk)bC|nYDW_o>#8U zJDSxEZ4H&%>j4{G66W^=6?h02w{9s84UjeH^~WqvH%{TM;#_FHk!h_lPYrtc6YiVV zM^>V_I#TMftYQ=N%?KBZ^Ia=dh4nBPG3or%vi`o@aea9y*={WP`bc$e6FC$8arm!4 zo+f01aqU&e{ou$Oyd4#!S3Zco>@cb9d+AVH{tkuZ=x*%EZQE+Sp6*(;)RBy}cv7f% zNS6}9cytb|ef;W4^Ght=@ww(3DUA>2lqHOd6WM~R4jQB43 zXY@rcyFc`K+qDJr8j`;rnJk&!pstoqY$GM!T#IEBXGGw)8LO$^?u&9UC6o=2Xs?#* zkJyEs#J*Ti84c~so{7l80cWV$3_}$(JJx)zRzM`tg_Dv<&<8?#c_Kz6Kx`ZVpH$-D2TBiWEcp{m%f}w0n ztXjP)Hkm?HUGCWHh;k)5ax!VAs6%jerz%=W75)rt5~jDy?nW8=a=0UxHYlO(dRWx< z5%1;c7LQ$0cF{D{i5>2%qz!f4%EZHuwL5~vLM)wLOzyy>3}xy?jV6c@@Vmqjzeyg2 zJ<-RBd#>J=OSBU|E?qLqdbyKx=31+Atv_kO*8J{@qzXj{=Pc&HgPa)V%T%p&Y_`f3 zqSkA)uiphM@iTV!=f3svJ0j#DkseUl7pngdm5+NR)ZZ!Sl3(c%?%g;rim;ku*#u={ z-5?+LtcfN>8C|rp4)Ym8PBnp$Bad;auPfXF)U{6QE6R`P!U3`}s~Mfm!6-SwC_Yw; z%U#T$RR~_Q7&rtRXCDgQz3YFl_ZCo9b2CO+d(}su`2F7JdB68t|8K4DWwF+|=bU|J&z?Oqd-m+v zv$yExL$4PpmRjQ6T*oF>dWXV9-HVOR%aZ5E&naejVPEDWsMGpJc3hYknMGliSG$dC zWJN)Z{flP&L+7UasT-DByaO>UTwRLY*aUDitNC{{T$3DIN-0I2@b-Uo=J#~-i{^@* za1>{~SsUTL0e9Q6I^JMxn6jv-aC_=9&o9LKi+2z4gnh+bgQ!7I$+MwA28cKRAjg)0 z&Fr9Vg~bi{Gwb4yB7)lG-JFG^t1MPKiYvlkh3PN>oj%=r<2=VV6>aalDWidNPwh;< zTXgc!CdOR5ZG)E1j%9G;y1`^fSOg2WG%KAeS5kFVYnq%@^^+ROhpgr=q%_7XHeG`@ zt|$i+OTRrdJLhs1PPLz_DD77@tVp@k9W(4h;8Fnm&Z%t!-j<(VN8#P%T zi%${Ftm4|WNzs~8xNw3Q+->pVNFq?AWZi5@hY*)2mZe`(NU|}yjDFaxNSC$c(?BS9 zYDNf(Psob{HJ;qTmS4y`vONf?cyGxpL>*nSWYaJrzlBO-c zSirKrX-EC2YjX2(KQp)Z))G(DRms{kDk<{Ij>KvQ_#5SSW~OlEy22d1L&$Z_Y?MEJ z3Dp(suu$(xgvZUJ9WLW@4dsX+{oJ>Fnn$CU2FHwMj}pOqG^{TN&RjEyFPYR|=_k6o zepVz?Q6HXL8d2Lk>V~-k*Y9YiuV#Y(DdDjxB@$Wo+S|-E4QDlExT#e#39<0e5yQ;d zv)TEA`5V@;d0rdlTgEA0@eX79JNS$hW%mEVs)H_r{xG%v+N%5RHu#whpXqyMu78*v z6!zJVs(v~Wn3>6e729ulK!5Wd{4J{v`0^+2zgcz6e>)9mC&8%k1pDr!MxvvSU9;|& z$6oHBwO7GBk0K}QZZjj;`0*QO^t)N@KaqQRbs?YkplBd0_my=XRK#Z_rKfFAf$jqNc_aMujkZF5JjSDvPD$ZQeE4!BnR^ujg=L95;i29a zO)pBCK~&dgTe_Dm5Lq0>9OT@_>m`?2rH}ZLKGfFJF`%lmS*aGPJ#{wsW8Ig2r-pXZ zQj!}lT#7a=Flp)_HWbZ6OgYQcrt87ZIQ_;ho-(47ie7^YrNDEgw&zrw&o8m0!}~2u z)Lf4zLAb^z!giXy#f~}z2=T^TPo`DW_7Pt{^WdH5EBPe3w*PGN<4ROYe^#`C;tV~_ zwN^a#2fnnyQL6COxa6~zyu0I-Yt|;t>UA8*ML0;GGuO**+(vnz43_k~t;vsI4KL)t z=R!GkA*oFjX{O3%e*^D*(B_-e(a1YRlA-4Lgo(H;RJXiGbEM65M7o$+7eBu1owk^F zP~FWi@x>Ouhpqa_aQQM1Kkwdky0^L%Upi3r64BrJFfhu|edvpRQso9hOBMdMaWc>gl`LbSAs~_*62bRsgI4?Kg2%|vy!ZEvS{Wgap=;%<9Zbw zSJWrvA(nubc-y9d7FFa_kf+=Cb*4itQeUIfhtS=Bn!DB{YU-${e&@D>hU<~R_Da6B z*s}%h8S$uh>{0gf3^t8ac3|u$zlLXB*dRvC>vZmN`@A36@WvWU2l`TC zxF_RT>fvzT<7#paRftmPBv)cy1}#}{TTDH7LG=6FBxE8lsJkcj;_Neq4WmNzTK zg&kSd&BOK^6t_|ITw>?-rY*#_x&oZ|>d7&=Hzkl>`i}GmfjDQgGn0MWYuhz(+K?%O zN6ubK&`xNW!8P=qt*$gDvneT(-M$eaBCxRfw0DT8ZAqOvAB`9SOmUO;LdG+WQ)P!vZ|BMyoEXr<2U3NC-K%gTDq^f4w5@P zR0zdlD~?Tq=j_R$-)i^cS3JOwH~y^O_JLlnJj)duNi8}?vK6%%Tep;kWQdiSpT~TR z?RJZPqG;#!;M@x2c7w_q$i(qO9C(-U40d zl}y5&R-hIsr53L!`o5{=P&zzSw&#+#;p_Y+^vi1aS2(!%J0AzfA1p|*emJqbr(v+s z8%HmbVS6jFxQe^D7F3!pxLz43itdU1;q@~F9`)j;wxPFR*7UHCyfaK8%_E%rZTsC! zFI32B9=5BZ$7;U{I&OT8?{8aIZmqo}r#V&o@QEj}NP0q{r+zq5hoI01Ml6q6$8aMu z0=wI6PmlRD`h#%)JJJ3iEsa~R+v8-XK@jsA(th~a9&`~NI+_>FH8QFtqzW#@a~&e_ zG55{ZZ#NU-W+D0nCx)tB|1g=#algnhv{r&DNV?7Vq9ZnwJ6ixfJJjAL;i-&!cP8Lw zgjD8AdNJCD;x+hG(;GZeQo(x|Mex+7oB(b3lO6(M{!7og7TG&B9sM0`uZQWXwf0%| z4+3B86v6rVWnjn{YS`h5TZ?#2r_vrfh+5%Gn_LzuUA;B6Xq;7d9V!cGy=benpB-zC zP24Z*+PMXHI@aQ>5mB71Tv}im^2SHl|9y~5)m9&CtMt?`C_*%4F&VQj|bsVJP>)-gTq(eoq5 z6uaK(CKiNBVs0Gl*V6I)r61jcyZ*dnS-17gw2H5A0C&-ohd7;aDq%|IU2aO9HoS7v z!rG2^1)OtxTj8$+r}k_@JdzcwRF;S`^PUd23>dH`*U__3;|d&dpn*l-{v!ozir4_kActKKP9x9>< zo!b?Yyt(m)h-up~H5NUJ66u;5H>L-X_>saqdJXa8#Iwu~t*DoIbsg9Bv%2*8Biq?q z)GxP--l3sTJ9cb`h|UbDhzPsIP5b!CvB?x&5Z;_0dT8rVwFv>Q@qm=h3yY>|;c!8{+ zE8++32W3fo>Q&w_=jw;k&Y+e>1o@)0TCbl{Y@T8sFh{l%lsN=e>Ro)G^CGoj>JM9c zbLojBE;vYeX(xgQhiK^{G|K^Ydt?-goc37pX_&{BwZ~LMYI*yEc+=YtVN>E4bNlAbRKLM1k0Zt8LoKj z9qwnyAX9Hz7?;#84O`21W zcaBx2hQa@5LkDR@iUnBW`nu&kUHv9{Z9}9r@-}U$z$xEBWJi@Np z%AJ9H6nw;rM$D!_Q}p!{{>SGAcI2An4_tzb%4eso*BN#C7ZzqaiOxFlj|OKqZ)(Fy z&oNQ!Kd}-JaOb9e85J%th|Jeo=7gy%DSSJR>Av05uB0z7xbNXJGazp?d+Z8G9jr(M zNQCWc3AYv^9S}xJXP4Np%k}vLB+fq*R`qzBCfhfIG1oYmcA>|YcoiR2teC_ompz;N z^>HBL4IQ&4NBYcmM8Wcy`xe4J^Q%&jl|t2xYbG}wkETnSZhAb>>i2H& zUcP^F?s){~L5Xya+xtSUogT;htKSpv44tUcRW_#qn;0^u*JIRP<`~7eb5&B^X`i`2 zd|g{5Ro6zXBlQ^#3pVORASUuG&b%Mvi}(C)nlNe=dQ-*-DqF946J>@S)v5v!V^X$o z31rLl(Yy5SbCSUvOtH3>BVU&i_RfnhN^5f6mu0PYn<$IydZthcI!yE;bwysJZu?YJ zxe7C<-^Y#EyGzjMOC;}SUxgsjp;XpbCSZFP1tp^YC7EW7`r5=QynkjW&0s;?8uGIM zxwvNi=hZp2H!1riN_3H^M6;D@?=--}7yG~8t5A2j$%T5*{(x#aRZFBaXnq1KZhfhl zP<%){!)%3a6Hl1lTjQ%EQV-8iwsYqNiZN$IqC>9dhK0`JR2EaIX=t5`!cdQC>EiYi zl1upU&4)yPA#wk5>csq~sS_|c`S&F5*Aox^dhP@W7Wmsd>Td}M7%GQ9Wcd5!iTxi4 zh`)l7N&h40vTBgY>@%6W;*w;IoAqdQHhRSGV&C0Iy&t)P%h7G$aIW3y{+QqIoCeI%3f_3j2``N>lTgf4#4&4k@i6uuyp>G}D#ZD|d8E z!z_gFC%h(iI$(J6Nba%xr4wDa%$dtLQQHT}8{wVjG^yH6`q*aT0VxsTQ)6;$E-I!s zsvAXeL!KUbUiUc*-uk4n^7WOcYHHGeFO{CP?(~Ob#JY89G0KVNgeD2sBQ;e^o0EgZ z*E=Wc=ZD+652j4_Do#_7)f&%{hWA50KNB@MbL75Rwa&cyZ~`q)BUlZ+;=;tw^a#m@ zImn+v9UY{BuutQmPWXW5W8ewx`@}_pM3MK9l2FpYwyrmumht)%BJ%?+t){G!ubk*0 z)5N4eSoURBer+gs)f5`jT?lGS`ry?PP*$tmA%UziDH z9KAYeVZMJy*7ZXd6_2PQoI<;14!T%&5gCU>%!fPlheW-`FYXXWb-xY@Pq|B{oFvE7 zZl{_N$*hz3^!i{I0#*9BnIbnlsvrp;M3&aCJnj9&5DFJ@to{9Q`^Cjxe!)f;Jz)+S zVlQK(!E#!?(Fyy7=PEkyd6;9m?qJ2I-oel+Z?BLfke@9?s5?MNcR^8$^`tYFXJzVZUDurFpOu=F`}#q^i~c)Fm{Yd`;E(%tePGtK6HaM@ySo-RM)G7w{vh5 zguX!IHv|QYsg;GE3oX&%LiIm9cG~TMW$| z-L-)2TrC1a;xx@L@*RnwU;FeYlvPpiV{z@BGehtBZ!8JyVb4#{@jz+CfB&agaDTD6 zw?AhC6BBa2y#!k~|KWQBsZf}AAbwfL&+HHqGw=bnMx5~K0k<8K3`khf+b>7tibWn?BoO>d+!82g}^8v z`BNNi$xT4e%3LHPP&zlP)WYSWto6S2cmn%cf-U?oDRiH%3#T$lr;v9S@DuceV(s6R z;*U9Nk|qeRK71g7CNr3M`2lS$>%S`G|Ceg?1mNr$5xMA7tny;oiu+K;3iPu2*TY04 zI{rNvM;`V3eJ;ce9Fw<$?b;?s`JacVz=lVla>I&zRcNvT5QqN1Mh05$e;f3$>5DS1 z5`F_2`JVtu`wip{O2aZt^VI!RCQx)h|Na;Y9Ue?0L;AMOhOLlFUImWDOMe}sf#que zF%@7&dEG`?IdO&&M+DNtEuaxo;oKAt?F`WMK0x8w8s@yhhHcc@SI3qN7)@-w&6qaJ zH~U@Xl%Y!N*g#S6MwYT39*VHUM)yvM;aiw7qAvNH{^;B|*uo&FS#2QV2g-vIa0tQO zL6@sn1xvl%7nbj}lwhcFhaz|0v{YlG?qWfKXge`p84v=qulf z%Ck>Uy4x`P&x{1E{vY+j3x?nEiOxUZleU$y9Q~+))IK6u$GHBP8)jcN*!Vk*L5T>e zjQkH+YKoFjI*jG4he1K|1BLV}VFTe`D0YZ7a`aeWS*ATW#Rq z00CvyU(IdLXTMXqPbmIA7Yk{rjk8Dx1DaF_3UtQqryT{o|IhUQ3xj7@0>f`~N?>Z` z>&M?LI2il>M|-$nIY%-z#n?yO+F{JSnwN)^~c#Dle%KlUNe}Orn^!Z0>eLZY!z`3VLZS*0G)7t)LPV@BHM@aRu?T6N2YW@EO+@YBK)%;y6 z{`Y+)`?IgCR>KvsGP9v=of-PGHvFS1`p-!;6xILD41>P^UpsDa^>>4)o_^2ghMu=) zQn0xzAYlI{>QIBKQc!ZWw&rX3<}Qp0K<4?F-+d%Q0>RyfR-Mg5(y#%dDDRgS4O6XM zlrT+D%dCVVEkS)>8S#ot&RDuW7*Mt`ojLY->O-IGhf4 zLP=6;E39Uwu zFGAMpm6EgS-<7nud#X#L934LtcI{pSiZlWK;oOPcSMPY3O+~EvLw9Dmr}~BT*#zw_ z@LA`Lz}yg@bV$HR9bUQ)r}u!bL8gX;;IiyOT>@Aq1A~65Un>Y>54==fY#2pZR1Qs% z31UnAZCC?dk6=7whd!MNg6e$rw6*eT_U?*;cf`<#+mD6>p4GlI#DnqRj4c#{@mtHY zV=fmd@X!{yJp7ZzTEPB5(}|_NZbR1+3Iaq6rD*6kp9r^~RZoak)wd3I{n^1kI6PRD z?`?zpH^UfV51>_gw=cn1%(n+PKPLV!Nx)^wt1#)<`ek78k+=fWKfMO66DtKkJ1~wa zo-QAj44a=ABWl8Ph?^9B(wR;OMrdfS&bE0#OK&6pRC(!Y2L2DA=*;ARA#D+UPOPYQ zPluzFpj}a0rQfr_D&LKq1yUgN+JTr%6pL*F^7krT2@5HNpic|&k5 z8Ae43p!ZR9PCgFMQ^7o2=`nzaKZ=7hB862~`OBm`(Ll|x4#taYx_BrjrQfG){=f$b zFpHy>OBqF)QpmGi>GxrK$5P-DXBw!A|WfO;TLalBZ zeON<&WgreeMK;wx@(`3$Pq-np-%!s0Lv~LrS?YIgp~3o^3J~5`*LwDbCayH7?|&Du zCT@ti5^B%9tdq(Em}NZ?f-KET+a8nsjZ|WN|3ZC-0P{Z=de;kIU`xo{EdZ}H*bo;o7o#!ELd`&wv9$srC8qU%d&&5pl(al*NxDnEwM5PO!=(<$vFKpqgf&;2E2 z*3c8n5^o0MuMii4lHRfy;&Bl~}NTTahj)=nrRrA%Ce8^1Ql2}XY zY*&^8a2^sEV!oEV*OOq9M|Y~_iH=d(KU}=~PN%oFz=)6A>GXV-b>l4$Xl4}9FSnB{ zrW4kvdl}vpG#sEtU(jZ_s#bg?RK>&KZVlV7H1}cW4dryWyXS1625;6lW3_y@+2s(WcgP@8$=&47U{0feDWV$I zO)b^S=;u2nJ|&Ue@jfp~Jw^>6Hty&`%uUi_oNxx8&6t|baSdk;dC3NI?C>YI?-I+v zmELW?uB>;J;J1JFny1^TG*942Lr%+`)TF6sR>{*-uf6PJmj@&vVPig`#B!N(W_`u* z^YbLQQfiDSD_yfd)u7YL#>bQb3{0eiq;z}sXU=W$=pnAFtro_# z`u;dGo_N`1QwUOmpsv~HE>4K~%CgD%i!FPr8z!R&Lsjp?1XQ^?7E6b-;rwoC(6UJ_ zd?q9uS!{U}e=%8h860!K(%Xo&3j*2e_iTTa=<)UQ@>I?IC=D>zgwEbviPdsNe3JuB zuc!r({tb%P?y5gU{7XXx6B}Z_&X#9hLR3zm8`Y#mOAKXi$t3RK*krCT$ew0%@tyhU z@Wv*8Vpae>@^!ZYEVFSN`sT3iW)s;ZGMnec7^GoS5$$j#pKsr-CS~MxtSbtzdz?6n zmy_FsvQCh-^Jykdz}(Lu?9@qz9%Z5)n_SMI?~2!Hw4R8U7dNeS8H?{+dcnnR zf}XLPJI}=J8i?>uNCDnY)w5JkCXd;<;4|5{M>A;8{?J+>)SU|FTLW+u86Q@qI$3 zQ`?C}j2=F|$DW=b)r!5|q4nIoOu8@#S`wTKA*2WQ$+??Hiu0wAyi!v0QI_5$cgIIw zw)<{w=osN61F?K!dd@RSY!6{nywwBPD);$S5gotCO?YUab zSrebJnf)Es)sJ??*>MlG9yvX@D2La28mt(H87yd1tR}?j^uF9^Vrg6MiX`u$H!{el zjmHV!bD!I|XTF>4GVbP{$zXT%RP~dRxVe6GB4(#ll@wW>uiLC90bMB75<#lw+Li4E zMhZsgH|O0I6ugp`e1;r`ND#W9=cf zBmVZ_-0pJfd+lC+PfuN0yU+2@+zII)f>I`4;zoGgD@hfA8qCHf>M>^`L$qFeVvUe^ z-Irjp^1(>ms^KtO5<8iH@?rWtA`(=?{taiP}C#FFdr`6Gxyao!2NlVf3MXpKhj z{_NzN3;gq_kIcEB)HR4>PjEuIi{;{@RpM=8x_fxs6Emj6C||NI(U<2)tk$62VwD6F zgi3W(yxh^Pka2Y)wTpM4AJ`l3M8GR0SzDl<=^wntK=5T}Bbdvn#o2k4Hp0a$SD9E< zz9QyucUYMIe8a8&=%h3KD`{nHBSEZoC|@%>M@WM(=BE^{JsavsZ0QiGY+Kpq)r}`# zbNkm#d{djbZ8BVyiL(lvP3;N6W|-jVqX_}YeF<4Rt{U{tUwdfjQ^wn@s#MMcwkuiY$#JiBnDWo&rlnf1crDDy8>EqVBr1lPy)r$` z`32Sj7VUZNX@xr-U2aiqv!x92Ug6oQ6ilvG<`_mT9i4s}JnLG=%z0@^gTG6N#POQ% zHOUBtb+-G|!Nr;~3Xjv|_$b1y@<%<>kb8?ovg5`(w7Fabgky3LNo8B|aUxqHw50e> z+x7yIYUjz&7cHESp;5jT0e4;r_f#iEot28hmYsK(Y0{3f`H}=t6@hWH!5RVY`<82o zO(hK9+^ei`uWEl zdk3k%&r23BT;Ahy&7L}foZU4?&1B`g%LS6+ZI$D#`G~u>LnA6NEZO1ruN2;7 z;F)r%CzF@R8pdb4UzXm#ayp%(c`BHlYh6rems>R0T+IXwX8FkTK-#_r0%{2l39_ly{o~~*)#QQ_<89$E5oTbjyS7e-8^{}zC9>r& z?h+xrT_Di=Si z&f2u1%C~hs5?dm&%-GBrXTT$RWb8;hLksAYC4pz22>p1?cG4G37>q@$1P$tEsPDRu z)oAc7pP|JPSWb3pZH&Bz1mrHC?2^7YATWMuV{=LKq(R7rmHCujuXuTw3yZkU#{EFQ zw@MZ(vw|4Ug}G7`IKaS|WPd^Gf|1sUsz%(XW;ha0d3;N*rlDk{h^+_|+wY3}^n{D* zc;Q&bYEZAVEIP;U(rMr{ERG~s^RuJrdD7T>tk>VjC4cYKg~j3O;en((X8y72z+Pso zNsuiv-ms~v+FVDj#h^3=Kafpcs3MxivXmvj+NJU3;-+WCI8Neq%!=`^7ItqU+^pJj z#SiYSHuok#7XVNE^!Q~lrQ&nsu5o0?QW)WJhG>t}>xHZYvmM`OE6P{?5}8O$X^vZR z!EiVi%jGnacDPq##n5n<&TsYj%mR~{SjtK5a>3_lRpao>oRHlc7q^Y3fbiAUs|AYU zsE^G7hCw%t+YE7E<(uEA4`p>cVV!`G>^sEHAmq=tr}Lb{<5J|~`m4p;NQ$Z)5+hEpunP?y zl^1|Thk$WhE4_mc)n-3F_=?t!8Ix^=(%#ca)&27HO0%{cw<`H zC8usGk=S~ASysiF>CJ3>TF=UPJr`z#>iJ&mLs4fE#Qi;;_lkkNr?mWfGBTxYp2>wx zEre$%9Q%p3l?BpaBFm##%?xbT2kGA<+^aBj@v~Ft3_q|-t zEc%7#nXz3GpR?j|oPZCNW4ZfK@*dG9<;>@k_$~DIK$4;ar!~cQEr*}Z$6xFSCVZ?n$^CUL=884ar>Ss=I}4LR2K zs6PR1ta|6fxpU>C)$G9hM!UW26kQ^^uWEsOr4HwdVleL$i z<*w|zHv?|boZMOSM!jnvh8#301p6U94m)Z4$RM=CYK{wu(-JKwk}&ho*Nki1CWV=i zmoctI8D%HFczRhA*WfKX0lP#0**kUHf;Sgo@wZ+-?j{lwH#&8zF`OQf(o4A3jHlU{ ztJp8LOv6WY4&*=>Rqi-u?zVSw%x5PfDn@PwoKcuV0$W8R30u*)N5-~YPa>A}V#~HL zuf`4R4TH|Cvx4iV^+6jUf*4hqu*G*)WEmQQpns*|rqOf2*B2MJc=*o@yA z8g=xrOlPZ3VW=D;eemyQGpNvl11&w5v@D<+bK*FecxK43j%=T7G10fQ6->bbc^=sa z#};fP-l*^%sTutyhYwrRFVr6rzAb_%>Wv7Vvf=`Qb3|Sh~Z3e3i89=2kw?es#om8nj5CMyQmVn_cMu8;R z&iI6=XJN?l)>=>d;iV|n*`9_e$5n%Is~(Zw%F>>}dr4%W?s)CjwoFe3F_j0KKpPJ#0yMkwyX0<6659v?3P@MK7_q3>77d{FIS;bij)HB!Zm=;b}YejB+)lsZ+Ah9MA zOs5cH%S20R-&_dR!!LQ<4FYvDYvA!*bzd4*Q?541wpw2_zH zUtTNDwc^3rlyP6$$iniskTCVTjjpy`yHJ&hGHX_%8W4AKFCRrIk0o_S0-qa#M z{p9rFn~R1}<|adJwvZHo2KXDF1#jfyg+xhK>R7rsVj*iRn}2z~d2*N|wMqb*!Ke@n%K%c^UJPQFZIBgq}h})wuiKQdxCjX>CGd z@ z6FUxa?CJ5d=$iaAbad5IJyuh7A}hbKC}8xQC@EaQ&X%_73=55P)6vOB`zzG7`@&+NcLQZCB*=6&InyRn8H8p2jkIqd9J*QV~FWT*%1K1G@ zyCW0s)oHFomCQ|DvAf|rtXEUmz3**jBssD^*_&#gtIX)$6b3xH4f;K`S~7+iCORw3 zUTO}hU74K1mR&4abZo+W_FgAfTP8ac!0D@|@EC+s%xv!mYmS#3$k08j&9zT$-m@0! za8TIYc5-^6agqmAYZ~P&sR7znT|>bMBYcn-|NQOnEoUID2l(O=dVCy9Pr|G<>)=w9 z#nxnQR_x?^;28)A>EUlUWG>954bkbN2Oc~E9<0S3be;y>;f{oz>6~y4gOHs+L#t=p zaHLON@ii7SqNeMkK*J;XM>ypN2&nC2G7EvqP+u(#;OQJ+lH&G>VXfuq4UMcwmhjLgqFnzB-S20gfEc;+<+SOd-(Z;m+?=SpdM0FLJUGDS{u4V z1XL``?jAc!0Z*8x+qwp5U{A56rvQV36>Nn8Uylr2`}W#C@KJ3m7@}ma<5$ZK)&@Vr zheCY=c#OOrCT)E(#YSN;r=x&^#>61JZb42FYeo*e{S3q!yzm7>9ojJx-xoE3#cfhQpK z#BXl-Kp@`v#c*CT4k65K{93=~Nk;|Bw;(7BFl5HaQ^2}*7fOreV}(=r1kN$o;tz2n zFU+3{0^GL86Wq;-;nDL^jJP3ReHEi!mR3%1yb`)3eMz;s|T_f6xKEz z1|jC>tX5WG3+iuOb_Ry9H-RsTC}2xtw}HDbbZOtEhaK->E^Zv)!N{e}H#9+|&^q+E zVM`PpV2Jl4(kNO}SU+vw#UOOUAvirB(Zg=ObsH7x^Y?)C1Qzj;!T_HFEt)tyt}Dj8 zw;=cWEwm-?0c}bUHlLU%({EHRyI_+dOa$wPN; zqRpN9`Jm93Hq&HcS<_H@NK$04}(H? z+J6qj3XTF(g^NdS^F)}ifKl=~UWiJ5e>f5hR(hag&py8kjL$hoQKa`a?|Ky%c*(=o zsUEcRLTVqu%E_&}r`oc9iw!JV|8plm+X8fkXC|OXpuaf?!C(oP=1M^QDTB~ApkHM2 zMHB)m6j4BQVAS}f%YNJ^8tw7J7Sz&%kuioB`30dM`u^Mx(8s^_Pw9j2Gz10;=qsqO z{_&dA@~v@Qzo;i@8K|22!?j_N9j0nr0Am^Y3iR>kwTGqwCZFl?-xtGv;jUq(sirz& zSm;65pP>rvE$zUt`YrzK7cA*t#f>peruN}Od8t<6XMKOH|Bv^kx8{wAJ+;cEQy8FY zW-e%d7Kk6z{o{2Or)iuWy}>eCQsWvF?C_s){v&0C8e$lsW%(Dukdu;M{I4@`%;kL6&;P=;dA4tW>wxM;R1iu&o%q5-?C;i{z29c#7gLR-UA->4c z!$NuzaFzu6-ziv!B|>#;0uZxxVfrmZXrPG> zlXF%IW}~F{Kq?+&1NPpAzDFjOi57HJBp1+r<)utq`07?rxNON_3E7gatPr#U_DE%z z0SNjyf+GF+^($yYT#A9;drOb1h^w_WVS#G$^}LYNJm!Zmli|V3fz_3!e1WrCSYcqD z_=VfUzU*klo_dz%>|wCR$XXM-UDfahue*&|nyTDNHFna`Qx6!&G6 zcB_h|M$url9-r<_Qu_EJ!=PooiV0(X6{G8W)775b<868yQ8S@>{c#V;SkBD+vnW*o zGq`Mn4=b`}gJT3y17tFJIFw8gmSq(eZ<@a$y(};WmhD}#SsVq&7nHob3bsV@Bq0Pp z;mRdf1srQ{4Z|1LTo_ON^G!*V9>!A{Bv1H(xVTAAT$G9VtIoYJ+RWL}L*_OOqZZfP ziwwKWcRi)UvFAoxngKI)2L146QP;9LhFL{XSK=G#0tb@M2A#^Wnt8DdQWs%IvG&;I zugJh4Gasd7;`RPJC8{XT+n1m8EZNw=R~kp9p7rPN7l8y01rP#Lysc_?i|RLqI1Ajl zX5I9EEY8Q`Ovrr%qU^J+WIXkI3-cW8M-At#HmgN> z>_;VpD(zN1D{?t_^|svM8!!vlORwh&&PW|`8QZVfUOcVQqiRs%61O-ysN1b;UGho` zkM%dF)C&Jb_L>b^tXvV$p{=8 z>9ewkApYqeGl@oSV30i?GH2Vl7$0|S=eirA_$+ODGU9wa&7_25955|vTcKrL=8a^T zUR3FvOp;C8Ua_4nr6GX$qX5!^u=6JTD#skpAMx{@_gXvWb~|x`Knt)@xp^G3VuZ{& z@4R1ip&wo!Us@VQ*#FA2 zbvJQ&v+|<1I~Uk)!^>nx0C=u2Y;T9to(uv84-70I=yDyl-*|_{x@W0RhO9v>!{3|}VLXqt@iT;a}62E4I`k6E4*VIgp$Qgg6V*+xn zgMZ{;`ZZ0{&wNbKv@*XxDv^mCmP+Cuo|OpxHE+&unP)i2zy1A45b-}B=;1HVVG+%b zyLmx7fP{l)agC()qc_!?pgZ(Q^b&b)p^dlSMDoz>Z|#L04dF1ofAOet&;DpCC)aqh zfAHSBWQ9se%C(JGky3a&OprQ2n1lpN5>IwH{iC+GPMbR&@#4ptgY~0CZ9gQR z4EfZ{%X##3ce>{{Tq&Njc!_d;N4^@ExH(h#d)#=gf;2kH#!og>)@0dSdAD zkOnio)G3>K?6p$OT0xEDHKWMOQ(x8f)pE3Z^IGuvdEfCK5pRV=$K2I27a7-d1Nqmy z+Y7X_Xc=Gh?M0Ef5aFBaUe(67x%f?YZDtjk9u3~lru*5^4i(gr zU%O+N@zB0%cq-n*zq9;lAwnEiMsJkvm>NS2yFj}MA-HT)cF@kGvE+r>Q`76Jk~^+1 z5K%I8KYhY_U_;%b!z?Gp=W{am3U^PZhYBPp1-iCzol&Ze^fq|adJU5Au_vy};$^Tq z%3XSYb_z*PavR5Xq%`DX%##0g8bT0SCT>w`Zla)e9bmAu;N0zF=bZZp#OJU{jo zz@sOECotEXO4ZLSH@RhsHN6#B+f+UoM>SBMClF`El!Z$Qro*-83}V7HP7L5l#4ssR ztyd;>xcMMi51C~9R;#+MR|HPza|@hxZJV$I zlIl|wwsCubzfc#yrkMKc3^Y)|{e1?S?KY(z+%LN6HM!& zIY9?ok6S8u^5%}s9nzWyQywJ@`m*ujSF(!^ce*rix9T@JG?w6>c{KXY$(*eXf2mq2 zd`dNz*(9#8#-S%q?erwL6`I3ek*%Uw6US{FCJT^Q4-;3GPal8#2b zFFeV|p#N5d@#wnchn|{(1a6nSp}CUE!K5l&U3on($y+7iyC!+ucO?l$dZiZqFX-hR zsZTc&+MX(egq?@qmO8J6nw;|x zi`)0y_^a=s9S@v(|A7G}}j-%Cn>B~YHTz*-5fb)Jic8#&I;?bBf zRe_G_xj{?ceAXkq%TsEaTywuq83XCp9U?Jtnxu~mp!gRGvWPgc@8WF z9m3VJ=n$E&$PK+!%C>Dnu&|6q9=`=oT4)&-H6)omw8Q$q{H|nkhJL4+1pFik{~a{R zQJ?zsL)X%;o+DMRH>usw+fHeNNY(1RBa+#q3~?qNEC+R&cqqGGr<$_du*>l$G8EHy z#i%78<9_FEU+Eop4}Jaf$3bMQ8@!&v_r+Y@OzsBJAt$iotubaPX=*D-j3|R^iF;n# zV&@FC>fU?-U&962(WCl$3$axmD?r|0oK)>GP0&l%29-j1chW8`?ixn;h7TXrpY<8y z2vf1>gYJ5>s%dKn`M-pF;S=^?p|e3)!^c+F)zN<2Lm-nltxMK8d^m+Uha0ttA!DEU zwouT9n?{J)`=qyJJG7s!BPQKz8E0*V@bv8TEFqOU7+$b?(@JKb-__9k97*`bnl=N2 zv$kK;8CRueveL?0r3L+C_W65Z2PIboEoS-jR}C6fswqUJ40}R4@%UYL&>?soFZ1gH zthsh^*ifdQ;N7Txo6eSB#CoF;W0W%~i6t#1BoKpMMe&*Nz2;9{Y9*0%{!Vhv;#MXk z@ZPN0?MYuH(eNWbS-dec<2zFjltpa1#UEpchZoq;aDG_rz>`IZ1|9lFPDiV6R6N+ijnB4h(sD*-XiL)wHU; z*6u;p)e__vpIl{DD70hcRVaK>SQLt~gC?*yWuHh}K-{ zA_rxO>3F3lCaB$dX&4R2!xV)->@)hxbt!m5+LX2pH{_F(i||XdVT@IV|*jr;7aiMv-3wjSvCK`rMS^DyPTiO3SE zcMW*f!A<5O0hR_2N6=ZksTOe$UlXBB_@$V#2jj9L$@#oMV+a?uMVOaXY6pMFs_DaQ zoF`_*Pt-P!4SgeM)|KekvxSKzu|3FZ#ZSV66!oCkqil;gFgA?Gn&-M7#na;xO^s>A zts~%wq3Xh;+&>RNz=1qJhlRf!f?&G+_e0S49E<;W2>LZa=+7bO|G}{H7YP*^{||d_ z0TuVM?2Qfml!7b0^ zCKEqdT`lx{7QRz;y=Khy3MMW&cl6}t1sN)&5Hi3w^7ip)xG9oHqp%MtTdeHp@{4TA z1ku^+MvbM-FDuQio+WV+E$RDC1ZfqS|duU!p)4y0BT9Xi*3hJ8gZd71a@AGMYUpz>O$RkZ;L5bnqP4o5h*BN zDU(q0dqkE1qNyDEhcq*KL=wgE!}+&^U%45ryI*K>wxEP1* z;>*3{)7h8Xb%)CiLX2b|WWfYbeE1G_aYTAoR9<>cPikA=AlqkaKMZ>1~bcttOjl zt@(UxpD$M0tv2gTpcH~i-p~jJBb6KS&B<7C=;9*_M5Doi5+b}~$m*3?F57 zKQQ~E#LSJXeY)qe)M7FgPdK5UJXqEpQXwSQnT2?^<+o)E zaMzaEo0~EZAis8i4vaKC-08xSHZmy{SF*vb%&~xFBjsvZ2Wkd!ZVQ>)uTQQ*B;Rr> zuz7DNi;q^JQcpx_jf-M)kEeDT35FamGAP{(0sZ^y9J!j&v2I3=m?#i*iN+yc75P-l z6ScvOtVT?5IxB@r9Q*tAGMDupmUPZ!BoH$J5F zGFMEzfE?n0RE;Vp%d<{85@kH>x{7cjg_*u(9{f zUpejIPJ}sV#E={7WYAcb6*E-0q1fYZhOXR+W$|B2ydd2OJ`wK;NZGId3M3$DoFE;d z8$JzFLlN1rc~{5S@L->4*OmNzX9}LLfPPs>)ABm(B0vUqWR9mA-b7W_w%jV?WjPi( z8!X%;Y5XkrCb%uy9XuO6De9sNrmIB=B03o~ZH$`I;A*y!V!RW0GvdzTPF;V^Ewr#a zHS%jao{&~KA$4z7%-KRhON^`O?Yp8K3GpX46VFyw>8$JODV;f&o2T30r%1q(r4p3pTk@9z6ORrV7h*op-G&!Y3O9+5xr zOYs<+z_t26$FiC!hhF!fb7f69DEWSo5}}uos;SdK3eM?Ko8rq1gtGc*tY?~x8!t%T z$4up7Z-Pi|9-tObOwmzhdiJe0u7%3o$yd12u_vZ)_WjL=HR&6aW`dEJ_SY zZ*C8I#cj@8qh(7~@75<5KZ?j8-BH`D5CS-~iCqV-!FR|mjgc|()h|P|RmDTXUr+`H zNBfT`Vw8-YJW=jLMuxsG$R#yUBst)E#48U$K|=eHS+p@MhXdbg?7q+86uJY}rYdDz z5-`-?ypTrIFw&RKM^C?j80L$;p-ID5(hb0Mgw68lxDi8xoU1qL2Q_5Wf0! znH6DK|2_5oRA2TSSlYY5yZ2yB$`+%p-%)0}mrVm9KH!~_vjK3h&5BgnI?w{-xfKa4 zDR&A)dR*7DUr>)S-8slLWm@G+LZ0vfUtFSnRL;Xw}Z0 zuAy@;KB>Zh-y39%Ts1<}iZ@M^HOt#W{c%$_Q>Z=OUN{&+~)Vj&^qb{mphkCV~Dk@ayKo7(1 z3NLz4`DOivVmKHzx8b*whi|!FRUDE$*B+ zy}}1NYPp|2=Ne^x7#bWmzd7@P?_o>nLJ1uVSlJTKEm@7cWW9H+x!>IDOn`Tu{NWoI zePeXzhA&^ahU8gcB6SxnSE5&hI^yWLwtsvBvCe>wLdBwuf1gVAoSL6nJ>@& zVLO%UB-4hQnYbQWxq4mJ(y7eou`6D8U_U$UK>mw)iBix@yacQ52kV(zgoc7y7Fw|Z zE$2W6rP)r_PW5wk$1O z0I&FL{Vh-Y@J{U0^9U`H*lgx^g-qkl&;&me8fa*RG=HH-Ygkds)i!s~$7u%| z)5(h}gu%b3Q=p4x8a^;q3Stzuj>(pZQ&~I`aW5fmTof~{6GEQO4lY+Qa#fIk*0U)5 zn4SQZb3cVUmWo4gfldZ<9!eQ2k#^)BR4ea~jj53f8`IM_@<#4cy&fe}YrG-4Y{f^5 zQt75;sSh!{aqYnkU*UybWlA0rYUOPc|X^7o_~^D z<`!K7*9cuec%4ajQ+4UfQ*gtXi=L77^=Pk2PPWEOHsuC(w^uJwB+g<}p?n`y0JCx49+b9De5s3ZEnOg$k>4XPD|4udadpebt&ii0+IFmSt?=P_+y+*?px&lvmrC#sRUMR zV?pI`t~a55cUS>v_~W1xV&MX9@Jpk{Sa1paG0;=|n8)An-D_bj;%3t|d0A1dsWsZj zLK@dEpI6%w&B}MiDgprw<>_(TS}pEMIoW%fRr?@T4*I@fWNk$=n3Ay!* z)(rx6_Y%8cd1gs&rVERd^FlF~1U9bbWzzM&6*iOmNi@ab5a;A^a&P0uH@x!50O`5KHA-? z>k@}Je9Hc4PuER{qi4apcZuYyhpG-=R+gX(d1^yIg2934VlZH_IK7D{fv+=5cL zZeUao-l#lAoM-P{27in*E|waKy1gUS?iq@fUx?f6pYlAx#r?{3WPC$#$xeW)<2fOq^d=)6CO0u1@X|I)kr2~NOy)`>cI<+$!#&HtVwnG=w~ zgVGC(UEa|9)(i$R@SAX@C?BF#J$1@8-cTu zQqkV$8$YJwA-C1uq^{b`tdA^xu7tQw%8)}P^Fa!o%ef%hG$Dn>62kq8uYmJ5R>5r~ zjZa3VxuPIK5Bn;VOMX7C4ZfKPfTL)i!iF1@>V!hsOQuFE<=RnP3Q`YEn z`7ke2Uh?j&(Z>4Y#kQEVa;7g%UoTK1)p?~;a_H|qUiBS6Wrk~i0~q;DvhDi#H6`&k zZT6Si8o|-7n8{nGtW4jg(k-o?zo1*%&RDr144py4<^Gn#p9}`o?cJ6Gl37W+T!;h76y{A{ga~oYBSy9q(@jU0m`(dFwOSxZ^&jRo7Qx z1eE(n^&RhoyCz9P9B3DHm!*R9Li3yLCM5YQBun2idbfEUxUuPxn4@#0=>}C~7lQq3|Sli{HG)7LdL3?=X1EZjqk*wP7t~hVS)w+U=?&Jw8?e|5U z*6eT1Q{iDN#Z-^5FOjU;4?N`szzv_)byuVmWC&ibLo1{xTBcOr*e~7N`lhA}2*n2K z-MZ4Tcr#C+{0ZgD3(-k9I}g1cL{yWl;@hUb@fD8EQKDc>{c@XHH=CL}KcE?u%CUey$>GgzUwK1{&HM|ugM>Pj{(dyRJ z7AAgvb#;kEFSu8Go}I@3BU;U1^D>r^;SZi;oXIrhuZTX0Vx+4`HllY``N4TjoBcU= zynPGdN6_Gt>syE){Eu#cACZ*lvZ=!u``;ywOsvT2uIE_`Htt%#VIFQ_MtaTaKee$v zF06gS-#Iv+O~Wl)@!Ce9s5@Ay2iyMvt<#pikK174{>B>niCcoYE;8yzol11Ndw66l z$H7f#MitU{q4a1zys2# zFaJKom1XweWE}@Xshs8#{F-1KSgGnQj+Gm4ZMffy#Xb=w3z7AIZ+e_IFd)d6rH?ulybrm{Bj?t60@-5MHhbLBn;p6))VGzgd|S8S&D)TE zPkVEf_9!WL_8) z#M4-y)g5{JpgfyfnoOY3xWCK0JX(4%mX1rZ=rp>{g%4su6U(mbEPNrHFV7uVR8%>S7T@-|rhr!D6ic+-+cS|}ie!S7V-@RK5m>yIy2qG9^!$+ci3>~RK z0kw1NdKAK|+vMR^u_(X4()5&;fU$%>U(3&#rlU)xs*O%B^}5Wo&rJCxhszj>a`o8) z<*>Tors?IfSDRjIfz9Q}8kMkH5(T^UrN>+{S!Dnxzqi(`Y;kByDe%?1L( zo=0cF2pS#W6C}Jct3_+VwXC2Iwx4Q%9cnva7JY>bed&$vTM(BK3e(8M0v?H_x<5BT zT#HuYm8gIMl7B>>&m4)w%o{L`E#2dF0VYA@mw(F9oUk+d*d8(p6ZqteJLIS_|k zYlgf1&VRRwP2c43z3r~~!cwoC?_Lei-Wu3zwi9`-k>$Jsap2BGn_{-Fc zi$&BL58;l1o)p)5KKr0RAHS(Y(=(_3xTTa}x%m{QLL<$s1h0pz!2Z*mCO@`kzLZGU zn)I0Ek6d>&<*{CB7)HyX_<#_DBNt#X@%XwSKi_Cs&9+3R)pf0uaCX;Spl;Iph%iPl zl!#p-iUze5*z!&EWs66dovG%Q(L+?h^$l?J;hpZ|XF|7nhi@;h>Atg362I=f0oq*W z>OHMITzQK(hx_6#i>KWHNPP1O>$sSD4eJEp{?J9mZ-6DkFu zAKqUAU(G0RC$-eA949dDCAXY;uyWJ|g^DFtqUG>^W#8Rd4sfd4?mSA_8)|cThzvU7 zwt5If;@9@dJ2_CBsS7m@C{aSqpbAii#Y}zCsAX_+XJJCVB9$A;@Gh2cctRL;;GF#Nn_L z$!xGxbn~Hs?*>Zo1z1;P6 z0W~irv3NGH-906si^svGT?W)(oQ_Zruzg)*c$S?->-7rAo#jP}f+@gULY)C1Hvc|Jw#otKzrnNOG)}fkFz&YjP!4B< zfNx5`*)5) z+!i9QZ)YucXPYrAfO?TADw3VWB{J@P@015P+aw|-=`K5E!bFg*^HlM>t+Uz~Y90q! zC=L?k@AWCDlh7@$y^Z|BAVa>BM8qo35C?^=nw|Qe_r8Ep&i3P=wkoj$SgVRh72iDi z**dti42vVQ(>KaT!H^wsnK^`a61>nV|GtyVFLPk7I_rL$A(upF!1cg7O{}gwenJI1 z0aZ2F^%af>L`vzXVCo$Zfu(fLoPbdR6pLKcg5OLpSwwCSWG6fFX#AeroapVsr?k=? zXSgn=5>t_hlKtkX(M7RInt6||IjjHS!MsqZa_jDlgrl%74I9NT6*45W%L>(2hhCUP zPf{T^L#}3u3Ko@gZDt8<78W(0Mc!{_3YCnKIC_%Iv^V68l%yB~mFz_lWO#v*>lCX| zFP)s<-ZVR(GU*%jb$}BZnI;JAYl^-|0HfwWlTkz_#n#USyQea1A4n#3kOx$ZbqkUN zeJ327fw(P@oO=ypMkIBR2~_mm3zX!az1gCY^BbeVC*bz!;!c9Jd(F=$?bl_O1c~yR z=lK(R66D&H!1E`KBuHO2rsq#kNsz>DVHY1uEpGHAW%l4E z2-$IN$QkS4AXk`iD20Je(^T}(u-2e9C7jr$wS@PSO$xfilOSz))w18Yc0rq>HW#(5 zp)5+pu9CAOMovT%eXd{Uk@M?)t(pBUpbMl>rM+H%r*o_r1s?-q&<>S7d;)S6XY?%K z2}~y`mvHQ=@x=^?hPh^_i+Owfjbu`g89>{}qUUi3gT5`Aw}^ubVS1!#0aN4@_QS=d z>;NK6QE8mXF(pBosNSA#7zRp0<^XMnW8r0ofN^c6ie_?=< z)FGbP3*67e?ve283fIITAQ#T!uw1>?(WsG!-_1QdO|rfXVhMF+Kgo5iIKKm$NzU{%mQtXxtQ#yAAZj5seW(UFH*q zq-6MS-?+1bCdjYfn#ncmEqh^|<85@i?Mq=)vag|YWUj#=fFr3@m(y$v9NVx2<#y`9 z#A6A4izKW}`aNtqN7QdL6jd@7RD)R9cimnCaRD+Gskb3Spgt3fgZf;7Ld;R9q!3jg z6~9h4M<&HDoW%etw^jYZF1@vX4Ok~jB6%)U?g6rigun0;0~v9qzC;L+Aw}4fN_Ce4 zW^ac)@b$8Rs>N&1LlywW7R2C$!=et`@`c>OOe7MGqpp+DIIu~*ng&rnJs+r=eYmD% z4}fJ0p{Z`EFQt@v8Zc0xvY9yF#Ys*UZrX$VnABE@NOBz)u)42Y%q zHc3JBg1j0hBRGvFN-Y2lOFa*`cmOI5lso~*eU~SMjaftC6N{}6!YNTCodd?!ONYNH zK*9UYgQ!g+MGFZV0cwMcU6WGE){nw25vN3jluIs_YgId3*$Olf z86&GL9Oq&81Bo$fXU%yVcg9VT*mx*seh;6x>JRjId&p{}2;=FxER)Q|fZo)Kj$_Z>=Z zX6F++IlEsLjj6JLMz5I~1()IDiz8_zWl|U-w^)W3W*$+%Y0w&2O3ccUU@Iv#Jj_gX z^bE)mGv@F-I;1c50gl>}t#wo1&P<#gY_A)l(dfBgIqbQP(irsq$-3iVMNb z<$(64GArCH-bEl{y__XOEUcDLh8&v6(VTYOkqY&3N>WYVGd~v#jlmHPV=JU^ng$hS zvlSxNOzmVMl2iNHjOFYU6-1+h)s5xUf1d??>u#njhFPX~>KK&+;~GrSjan-)>O=)Z zIboCwB{2>skOK{URUt`Lw;E>`SuvC%9z9<|!3Fd{xj#ibN)D*`fGnU5t!_3ZPh1WR zmw4>5O1Z?bBj^F!aEg{psc_wW#Tb%R3XrXmV38v#G|je4eLS@@408c$FM?v};BDwc z1gPpU8o9<{2X;3>5q@fL-8>+tYnB8Lq(>Bmj=f>Hv^do+GIAhAs$-2rn|EuQYOo^= zj8tp{cY2myg~6D2a)zjoWm5HQ1r8L|m{6#Xrs+iOA&xkWA}Vo)W>U2&vv>#G)Fg2R zSQ6WM8_tKJQK2B89#duM8=ixLCN~uD`O6ZDSA5Vrcqrfkx!))*Za^D=p=@(GjXY!` z0RI=s=qWH@bY>;M@fSci$Z|akIT{&XK*SubXu~ZWmkqo){d9kLqHkmk$u2?x+Z-+ced=O zct21-tC!2UTHY$Oo*?}6RAuzzEm(n+ryO|3>p%7_UzOR-k?Lhi+IksHpVF>N&~x_N z6ZteIHbD@<$$=Av-X_JRhsUK?KnjJ^2&8TF(Fhst;Zo){5JwB63PH>_znPwR-5Fx$ z+_ztcF*d;0fT<%Z(^gr|*hm8s3&v$Qy6Hg8+~THjiPI2$chZ9z3J~GimJ|O!|t;zoR1>*KCaAk zd(?P*(vx&@ejEUA-T4>`W56=1xLXaOO12d?!WDu{aXfze?S#l?F$2h~=a?jB(5(k? z!XB;XxOD^w7Kx=QUKanNSlGwdIFqzdv=%?$Z8Y^YtW+8F>@a~s=ozW;((%>4w+2Jv z8(zjnO);80;BU@J ze)YHfH+&%f`SuSh5&KWyOQQeMMS&4$Wnf|?N~H5k?s$&pW4u3(<9ge2EOG@_Y> zx_Nly+T5TiP5wUBvWQofK5?L4Q$5itA1DVMVju(0gvPLZgX4y$Yw+C# zFV$LnZ|#|ZI-iYVH5F14$}LpK2_-_*w`l%I8dND-$!M;0vR<6_gtb6ok5N?FXvoLk z?v67-=}Q73aP&s72ix?GZ)m4*S>B5O!?!j3ez3}1gY2n^m<1$+1OAFrLJ2=EYQJ$+)6y`(Xa~1Oge{O z*%e6Y1ZReH2E@LbQjSS$WgUqA6jAGmsVTW#{T|vcU;N%hNk-jVy_`Sry?RzH{RBtR z6@K@${LI6~DZ>$@=C^B6`r`+~Pb1rwx6AY*?ZgO3>+x;8-y<{a+j$S<(hK79wQts= zbwy3SyxGTCt359kie@CV2BKbWZw6%C#%-@Xh)<|0M4GNiBUn4Z$5}GlByeQS-p;)733u5)50@* zV@P#cMa7R9=@)ytYk9!UV$&bYe6+bqim4mBX6do+OT)Muq#`)!pf0T?u7PyNdq{)J zEF&IwcE6H%n*X`QR`>MtW0#WqlZ@nLT*OJ8+of%_QueH=0PWFaI4n!Q!4p5+T(0}1Q{g*@apTGNK75|AGEdLYEOdNl6 zKaiQ5>EFJ;GmNDZxgd7(;Pv7CSCnDrHY@*IK(4r|h|dv$P_Br3|8n=&3YCQhi|dP_ zgJOKjZQj@BP<-!QoQ*;M1Rj>AyU%7PC`4FuOJqx}W3O`et- z<2wSZcI!=^75+}AXmFEjxb{RMZAK8|RcqXpS}r+l!dBRj#2Pm(T%qKzbWIk)=FqB* z3%jVU_O&*I6mvv-$f#Nn79I_HiBgpuJCh9+NqQ;?XC{u1D+(tKNxaecbfmps+j?as z30cu<}6JC#&lvs)>Gf!M?e1bg|sgJ{%a)jJi5H&27l-(Uc_7G$xC4U2vV1SyFEn z!s?D)D+5LA;|fU>jv)3ps1rA&-jF9?w&{8V**Uu%_J!dZ|9ESEsO)>moaLinAj}n~ z!b0sx0ySvKks-sKuRQWm`V+?G?Z;yS2IUX>d@#6n2Se-F2*c=I`m6A2-w-l&m@(2&HnhHfy81%+kM;UYMMN|i{y67S60 zdirTlEpB7TPcgk)D~=7GD7{l-WZ1w7QI}L~<953ECDjSaO@#memKu{Vm#aBhQ6cYh z^f!}P?d<%tf{5jez+Tx;ni@SNFjhXPwP20yw@^9|#g*H&Z8uuRR1?4AexK$Hn9gIHD?PV$OE|YQ?`cP-z&S0X=a{(D%DkZ;b2~R;@IZ1 zU_{-ue+%zVtcVQ2#e)zw21<3mgy)1ky?B>3UhC5Z=O|hNrZ%7=0Ga$&vEmbnp>u)u zH5O7yFhaoXy#%^8s@~Acd9N50sNNw1wCoI~)V_1IV@=o=0T)R%J5WwaEMmk)C0`kjYu9a zjezCsC(oo~Ulb_r_GbE}BelhRCeB$AdGC+im_NEUYJ8|CkUdQ9x!gfzsGsE}yl`mn zk}KW=n}?2sp-x~z|Ai-P2&=Wfq2oF>722$)3WB~cq2rkiLGp~!YGNe=?g?8x)5lWo z@U81`cc#hV)-3knmiM+19tFmbSq5yqAvRsu66*qdd>?(7RZr>{%Emf4RLl!Lxxjpk zCCA6NT{{%sQAi-nLfy*uc%-oTZpwCPjqV)(flC7mNBKC^KvAZQ$hUsz@}G zBps~1*A8sJ-Xsm=DC`&eFg{z&d>BzP>);NsLxAQem6M)x@=lH%{Jp_er1ia!SZ?7c zm{aW&v2P8%Z;E!4sb24>TlVPuF7=r{r|63CqqC!K2x7$u zUp7sb)R5KD9dNxnZBw05{Mb#oMSQwKmgS(}B`tQt7{ZkV$?f$pG`l}`HuRD}&iy^j z)Pk?N2f~Jo-8)k@qi~g5W3!@|;PT#)O$JimSp{KGb^`S(!CW?-j~a_bLOb=W zCkPxU-%b*B+d1>3*tMAzg_h<%`347!E{|u-{5}@OV=^1s%C;7K<7fbcO>FF9=r{+w1;D z6ZzF0`R_H6zg#8e`1h_7|5X$D)s^sHY9h=;EI-}1LD2=6iCF(|yk-Fv|5SvYi@Atc z{}B^`g^1%f69-hzO~m=rMGW-JufBtS-dX-H&7fb+AI@Jr&VM(5xH;JVZRf$0YWti)5R&EoTXtAh|Ih=c({_R%B63tX;V6Hs6XLl2 z2coz8BoqhnGjA)T-34PP@qR>~Hsn`ny)d!dtUa);&VS zMUBG(#3NOH;JWZ%kOd&8q3Cw)yx4x*L%|-krR|Rub6)wmzy$3;fSL_D7aM51o>;o( z_Uq+e%2dJ$n-~B&}@6#<=WzB^h_~XtZ?^-wTx5w)eqKB@S9YxPiL1Q7*7Hn z)M)(3n_orDkR7!Z7SmeoT1JW&ZE)hGqSel)z@hWgs1#SQT#g(1I_Q9@Qt0B4BS4aC zGRGh(&-5RdZDRy#THBJTdj-(A9EFOO323}(m-kE`pBpeGaZ-X=90)NSFsjDAVSP}w z6;Y$FBOgpxB&b{Ywi~B}`U;k3$1650Lc8wiNI29k3oUW4&)rk7SVjf57Q>Eu_{~IG zY*eGa^o{AHAgRajIKErgn+E$gFe0=QQB3U14*gnmhyK=Pq65St;3|$g3>D;|7P`7` z)DmXKL#1S7?w}Ac3O)NC;y28erjZh=%WL5eegOpdd^kW-RcObW8c|7QN3@ zJR93ujeis)r1?@(;T0cd(XK!KNz|dSD%X&cd=Vaz6kJ!#LZ(8&boLGH_!BcLOQtNI znogj@x1+-Gia;$?VqOENsl6t%*u^1~7-NYD*JSdK!RDcfXHZqW;?tmj={xGC(ce?V zjBC9lP_&S99K6A~kyoDrs~vP37{J{h8=Mg8MHdu)5M@*EOpgj;oI8_hmCf@y@Yb)m zRc06DEU{YcuhF9nLYDBcQ#M29hGD%IWQTU3ZH_%uK|uWCZFJ1psFHkjR%^F0F^*cN zQ)^?+Q!TCXdQ`Yw;Y;Ol1pH^CXtIj|uY6{Jd|idf3g(C>+Q6|f`56u7`(%$b(@b)W zSKQ8@5;0$X!$5dQ6!IfoDF|Em)-Bi@V8;Jfxa9oRq4;m%@+WHile;SCvy1D0V7UGK z-Cqs2KN0QUL$O~0{&y5(=lu6WxTLB8ZBm%fK`zks;n8p%90VEs>~fOki19_X7H%g@ z#yzhFA(Lg#j_;b8Wa6mgx;t!cmapEFepxjapG3|Fe*VN&jDuVl-N{Ffnv!5p1M8jT z$-8qGm#Z`cBiisfoPMCaPzx^_VozZlN;swu!}JMKH-dAgkH)hLePvy~#Q-L^t6U)eE#9l`ITg z{x+*5Yft7V2Im<3k*YXf$O+vLa)lmq>CaHd_^GAy*}3oe^)KDkU7o6Q!T_ZuQS z9qvy3_UYe?>y%o@!XeRWR6adiewbY4*T%?2FU<60Lsn!dc)=AAi(4-kJH4DCPGDop z@IvvsL8VS1H*|k2`6*B!nMEel+<~>4%vt_}93T|6)F{7y*+7m~i#UG|AH=T)s-mMajZ$hnv8LO&U*{<^ctb01%s->`HzEkXty>El(dd#!6NA8s)E zz-LR$6LXc1_$#Xwng{&G8|_SPixGFhnODVI3gf)H9Tx|J;fQg-5M%RHk2zQ*-*E1= zDT+Z)wK8qr6*~0o1c8g1-Ie>8{(G56s2wlozw!Cz{8bP5`$hDZD+QeY;gtf;zwWgB z3!iUhZk9itzL}Ys*!~l*Zx$|Q7LNbO?fbd;|EAyf!IFV}vQ*Ox#rk+pgsRH^V$16{ zJrBNeOhk}b$<~ddg@x3;(MIy@{GMc5e#R08pv(LoJC%;-x9{GL z{}%WRIqdgT(CUsq1IGfovOtm2KrbSU-!lq zmSlh>|1k3)ayWE)xOnqp#jB+Fkc3*{O#--@OL0p}r?n!8noW0Hd_gdP_Z&-a zit6lrwBJoFL=7`Ef*2cor)%`Vmn-$MH~h(EE*#eHT8E8YsH?lh&69EUyvuLSFRYI( z??WGkbysrLwC22T&Q|7cssJ!M*UTPgV7x)~{=Id>y@cAY-*2B{>dl^R695}igV>=_ zFQ>mOJQ1|c&p+oIB3fwOuXB;C(DJQ#ZXWJot~>0HIzRNVlP->Q>;xpAEb5OCPU6404yzR|*rw82a` zXtpnoK;e&0ahpbR(@~7MTsW6`wU!OVjahGBd(qM3YYrk3f&QcDT`J+a0%6-N@spds zLs-6oQ_p<|ufLgE^ZdahLyKF>{$xlUl4}!X83&Z@!0lLtKoK5aUMfGFr>zICQgq)EQyOba1h=}Zl2u++nRXR(cMb~pKj zerQGO7W!I|a6=|%GS?p$y2uC-hf1#5g*&=7Wpts^;}VkUbxwpKb8Zdm4rV7?axH7D z`zCaS4JSdro6l|W!xruIzTfwfr`^wX40F&osO)H|ihwfEq#P->kG7Kzn{Tp$e;Q2# z1UPk`(ofW|WO4{7tc~)lV9D7{+2Eib9}0dR#-2`v4w|C|xc1|**~Xfs>;*E$P4_6! zXMENca0fq`VUt-H`n058CfRT^D0Mf9SDz|$65i{;+!T56E@l=gvi3>A{$b?omK{M1 zb)(mvkdMD^k{lFZHpBNLq*=kNg(!{5 z_tQ6py?TqW-O)FFns~icyL~;8iE1r%uONBLZm0H9fpJ!6J|~w{nY-?dijuWRKgjoX zC%VHSpje?17EJ`wI577-``_C2-)swlGS@W_9`8MVzWg$LbUbl7>wb^>ou4FXpxf|T zt2ff7?DE~yX@11UaK9zb9aNPnV0*NlCGKxf zXr9d7$Aum+mZJg%`z8;^TGYP{a=zDF+#-$iMg<(bdzK+{d5wPVWE$1@0Bb{jkdV>u z*OUdN%Xs_zool}o#iG6d*de75AWrgGj?f{jC?CVver@coZG{GKk3CBxA(pcwt|=Qh5gzQV$vd9?NAc$am!P~|6Q8kJIiu4Z8 z(hGS)RcJKfO&usH!t{i&3Zl&}07fJOfE>_a0>FBZZh=7dsRZ~CLBauqP1C{jNATD- zPXv&D7Gw?`1F7@?1)sQ0rB{dX0KzcnfbV7tZ^i(Mls^Tb7<2r{I@Nh&U@bhlBD|on zVGv?csH;0Pdgnq@H6)xOysv$-0hVsJB(pahIf7flxn@$OZp3U1{c+T{eE&R#PA0ZV zgVX-r+nCCtoY{%E3;X6zmhasYAbevoV{~OyW(H3+E6EiBKJN9D#GtVRuq_2415AHP zW#rE0z&Ah$MOKUFd?!LulY66Kdkr}?+JIHA-v&O{X#GYA;tw*UO<)5gcuYe+SL`*ZiRROkZcg9_qmfREh&rVi+pyZp>)t0}d|y-0zjG7W?PTOaQK zhSJHFiVK85_7eitqW&l2B^6zGrn_MRsC=Kla21D^iw`8eAOI*rKF`s~NZAxGU}3&C z^~v7VCC2;m6rc)P_@ERbMuom|H zab{oJLtvZ$>_iG2l)H!Mg~QlX?gPhz{VA9b#r&-DF^(LmqR%#nONH!tObKk>p_NLtH_DN9W;rX8;>GluyP?CJ_Z-mB?Xi!(y9$saXsw z(BLeMMgksy1*(c6X@yn)@pG-!m7z#5K*$g=iLYd(Al1`wyMzD`E(AtIbp;Rb8Qsa~ zpL*nPnoYmICRp)Y(Oc01JflIpK4)>t!*LbB7G0@jSLqI07dX;eq{P*>ng3ti4z=9 zng2gwSq0{qCAA)_{7x4D;N_o-xf4leHg_2cAWih#dyoKl?lj=PW$CTStX%yG6d*4A zSp~@KDV%1?S%v_F{;b-0_pfwQ-}`0!V}C&LPgxIID1T>mKJMHJ{8tqFN$a0&{~zs9 z+{RK+*hoN}PzLDPKiUM@se-@G64u}J7WBAlOzm-U9`@o5hELGnO!QwGx7=S`f$%|o zUiXT>5XPYJ`0gKqP$>KNDJJ-nazEwn-x<%HGQUihPtsp{*`|C9u(VikejEf@ef*n! z>tF>x!A}abvbZ(Rp_0?TdABe09`D~h4orge1v~?z6iBDJNs<^vyo3ttt+TRlMevb$ zrVSYg2M_2*p7JC0UP14VTEGEJe*zeR;~4r|B{cX>KP;@~Rk zH>bYT%?rBuPPY^RepEO(PEd$}!0jtY01>k?cw`a+3@;RDS&0j|Agk>6h*+_ZgUhSZVLR~spdTYz=YdYg?}&? z`=oHE`=9ewH1Qbc<^mwX{yEQ(wG64#V*u6PHd%<}oX$?HPTvCxLVxb9e8n~9EWuxF z$M6Y#)IGK>u$xy*gq4QZEudn-gx}lsiBO<++{qUqJbJzMnORe@Kw$ zzn|GJP{9$TW&WYjgy#DPI{eCT@qf(4-~AM+Aq@RD%|65OZ%8e_{|mBC3H?=n?cDwq zIHCSjvwrX8vl7>*zVLXx$@Kql_11AwZEw8r9=btA1tb*-Q9u~F22cqFMiCK7lalTp zS`Vp!Gz@~25`uJtN+=9SN+TW8NDK^j?eU!7z3=NkeB80tv!3`qIWxS&j1Z?b7SMbe zB(x%z4+1vCC(>8>-qWFC>LQXEL6R_P_G0iUMBif0YW!gruUqMz{nq1@6jL`B!~ z)i10SWC<{`m?>D?A6_HL9zZ<>tt3`<3Mv;Tmg%?{S8N!##ge$Q5n(mO>*S_;&Ot!uMa6mA;E>_>U-TuuP^82W(%g4W z2%uhp(?_SsSfu@4X&f$|?O=F5aoy_APBur~rXGgIhO?-UtIYj67J3ID5#>0C6>RdX zys-bJ&yTJ}-_*>Vp4*E^3rGr?(x)W;rG+#xkWa2f^pnj<`ER6ixp-hX;mHkBYp33I zHpq<#pfaMATJ^(rMZU`f<6&gsT1V=l?<35W9-bS5+7`>~r{z*$qm11bbarU%&u_ zNhiu0xXLWih&CYVN}@mb*{iI2{sHM<;$hHQ@640?H;n~w8{}+Dt`lPo)xsKvd9;A# z5iCIbz0IvJYeAK{hG$IAlK?xx;tcLlR;9=u0KfYNiv{KD+>SuE`2jm)KAn>4e$Ufc##-BV&o71qWwCH&4{Fycx?^k^O_yq#tIw><~+du!~eS_uuz_z zjMWRe33ena(=e!j;m80%O4kZF^Fe6sazmtGKkn<$dW~7uH35kO0Mn!?ttKVzo zN2$HZH`kmIoBU{K$=?3W{$x@Qgr?r*4GO0RO3_^&v0DUr-@-yhe+)9@xl-Xe0uax7 z3$pmn#>|7_)ADM)_`5CEP}F%ebpONHLqSFeuJV;g(H9{aPm_>OnuImYJ6vDfL2heH z**LScg>q#%fGYCdg_ZnNKv~(OJ>xnP2|3oWMU=fLDs=GeDsQ8p9HmgJ&^WOFAM5z# z?!=ymEcQ+WCkPQB2q|kZge;>-r>+f{PidFHr~w^xVT&JAuR9Ax({dmW?LS_A(N>oQ zabCwlqD2{cKcK!_l=NO=)t=QoY><2c3L!A={m0`0TiH?ho;-9HV6>n1mw9n(<+;J; ziR(0&6p-iC7c4&moC0;AmhS`7L*_BoAMdRrt0>k1u49c_M4y+pFXI@M#>xVrXbukK zX|Dr=-QHa;EQ^j3x025>0>acTVy7(UNST2yD)Pa~W(d6IJ4f@!0ha*)*u1X#bhu-H&ud|AtSGekiN@>fhj!DyQHZgf@xTIN;n}Z2q80 z-1Gq{hM%aMWzOA9w?|LQBXWs2l?I}T&?i0~Wq?I+>Ik81oV(FX|Ii;22juE_F+;6usil97P?#b8=q|%A~y}}2)u9yUqdgKAvq2> zJxnYp0F$BBHCRueeP?>LiXu7|W($bAGc1#`kLDwb9GClhf!#Dl!1mr4z`*tx@y3J9{K^F4g$XZOo(5D(%w%tqsu2=7fb>pR=)--OgKopkP{J&^e2rJfQeMT zg4e&_t*qKxo1i8%L$U;pZ_foEzZe^s?YcWEe@USLfqFs&oEQeSKV&IJ$@kW8+3##y zR4#7XLjy$Mxx#_$Yn@^Hiye~?VCPk>!noq39NJvO4;U9wsm|T@>D&4`Qb0z;(#fQ< zb9dj;cWNhUfS&^!WK=|jUIF5b`#R7F);bF(>ytpAyhk|Z*!TwvlMBMV2eD_uFfqn1*81zQ@mCsuwuavM0!S!8tluKJC`PO`w274hlH8 zzt0acQ=-PnG>Ia=t4i59&B1CDmh<*~4*%9#`2ZyF0#yYd7sALcU^518W)vj|XW9a) z{itGliDyAkYWWYGHElg|Jgr?A@reSpNYm5I-TFV9e`fsl$_X=%RPm-3)x(~L*zxwVS9ncj zvKH$+w*nfHi}d~^Cx|%`2Xa?u?FTqVpGW*N51ct21Dd+Ad zR>x^$TRIfAy}O5>|NPciy??4$%^G@w!V+`v#u$Jc?*jR&26Or~=j!i3Bo~RA67?=H zL?kTc=l;o9wMtLVsC@}6AIZh@uo5w51%_}93>wO{(6=12p;`S;hQZ><0jARHy-N~S zZ{{0PWBD<_Jh#2<_C3bF3guFKxu^x6`JyNA4tW?UOPq4tb-j@g%1n|7jxHkev|igezR3ZqdTkhnB+as8c8~6_mP@a6^<%6b zK0iabM9M8rGK+vo<$VY6t5ruytMJ{&%GN%0H)uu;J40OVysU+^jl)}6hP*4oh#2ds zMFz|-s#qla)+q24h9=>;iALX=`#36#+1k=k?TIiKfyc_QR9qq%x9go5rvF}oNIW5+ z14BGF8wXOa+Fnd1EhTLj(_SXGf-6B>JCE*wE1}#-4&+L;Yq_Q4m53wS_d8UmlO(e* z;hlo8fg!yEG1kd$uad;8-h7=4?mxAIh)zOz(801i3!*XM7;A%}+G5Wx^tosS|JUU3 z^?5k&T~}{epRX1B`a9=^#TMi9u@leBDG0^>-DDksFmI&4vLn4MWIep)rndhyFX`SY zy#7(CPx2$30FysT@E`azAbYEo);Y952`-7j@by`uq3u933X8^EqGl$*PGnt+l76jL zaap|TUKpciP`hsi)(DeN#SGJ~2O@!sy@`)=4X^(Ow7=@)oO+%i>Q-yiErxnYrddZu z!=$~u&VYIY-0;_p_A>4kYvVyylWz~!RUY$<|I_^E495wO(FeXA1X;>ZAJzr&Ol2bN*H8FFCO!LCRGL= z?*JROHF#o@sF`2GemM*15ou)9l|%g8=;gMV2anw&N>%h2rH(0QPYB2xZ(1-3$VY(8 z9W;cPI@Y&Hmg>|f>VC$yOK4_?V>L<0n@UgCOj|5k9|T%D7E}$uM7dMI+R_J# zh9B8iSmz3wP6Nk#hv-s!z`4I|TtzOslN7_Y3q=8jKJGG7IBJSfp)Uf!4DG{pBGgmx z;P}DevAZ?X6UPD&z%T=mF`I!JIMqI>3giyLCJC$Ksx@n^HOVpx2yhoHW(QbMyrr)b z#ebahAdnj*3>bEJTP&Zf#fwJ{JKGxr+-)<%pJ&(_d%^Wc7WQ03TLJ@H*WSX7J6k!N ze&rx$&?E+lRv<`Jq%;h)oYAs|8u{P@$-iJ=)2Qh^kfZ~jzy zqBFnbhh*p)Lb-2xSb-3X=#JkmV)KTZcuG(@hPIP!3%~E-`g|wN)Kt?NLUY3OFavM^ zH!q75rp@=v?Jo5bYy-a+fjnFqY6}MT3jG6g8WlOgWaW15f>azyE-~Bc0NECnVH{i} zwY@}+AwHK87}9;O)ST;brOd=vZ3j_1`a)*PtpSt+$Oni7D^t>+AgjykBRtDa)|43h zCvY+QPQ)*Wn~NCYDuUG8!G3*ZOfnKzB*^funuUVQ30W#mn3}kmoXBp}U0PM1J>SQM z9M~pnBi2#VK$zl_ttSzB)Jnc-%uaXg>w9tMt%P(5*4)X%*XCg8kgZYD-w}{lX&@)J zPJ-eCh#vNh)>D`!GO$3|>7j4I@&2412)&6QCl3Nx+aCmRpY5rDw5@*mbFv= zh-hMHDt}XM)OlYZYq0#cD4o_wr1_e%c0TTRL_mURKGh<^})^8Zd1%kI6NBU)H~^@Ffb;=QT+$7fK_#e#hZzUWu%mja85YFK3O z3+YpNHs3|CguP&q!n6Sn)TQz9i~Q(%PC+!Ne`zu}ccWOJ(BR?XPVSFK61a_He#U|6 zmYiQ^e&-%*iJqbKOA3qm8fkWk;VUCEB}5E3xV?ODC|`daRUlEMJs4$5RaZK@bynAI zrTyWJA#R=v6z$Zp`-6mvwc=bWdJfqGy~+}Is0^Lz z_Gqo))JP&H-mPM2{QQZz z3(rlX4s-7qd{~h=zV8M_6ZNcQ%AENwZ_LNCxi2#hYFw-o4v%)f_UiOgX0EMHh91|~ z|MEsRbDx{Ry-;=}d8&bhBdh<8G`~i9y1iU%=rZjY$(q1Up|=yyZ7SsUGA8!^;qvYs z7*ozv#8}tX-PFb+fxJ!vc`ac5#oCzv?BkWM``)EE<|EV`mz^8?3Jv2c!k1@dl6B4; zjE;W4;e(aKe0TSXPeI9)u=KPf$lN;C>P)~?e&MwAHFkX7C`n32m?LkAJ zaZ{b&xZhqsX91&YO#ywXX3_VIGE<865IBHnMXBuP_Ph6-ZJ4dzP;O|K3FXnp!Mw9t{R`MvR zGh|^6?L~?n$3w#e(Poa!ZnbLy2E)&GPy2{YmM<3(invE^3$Ih%pgZs3j73U?t8nq4 z>#3PJm9aC8>_{|4VzVNsvh|F(`S*f}l^U&|Y%BAh)q{W=a_U7@&|<*2n+JGC9yH% z{I!wbNz-L_(`fhKUA&4Gtc8b^jGyGyzsQ?xApBngI9>a%1rz^}<)A)QF>>Rg$r#U* z33r6cuj}%(u3pyblRTdvA6^GvOnFt)I-1n~j-da^q=sB65MjanYpTW4dQ6V`eKP6m zp~FW9y4HY*2ET7VI#pKuo%7OZ=ShjsUi=RkoV1VVe@S#7fevt^B?wvT#TculLEp4o_{ zIhx;Lx1fZ`Gyy}nE6dmHw9i08ps5h5ai6`mjxshInpB3vV0+N3C|e$>KUdx7Z5od_o_za#ojDx%cA1)B`MsSP)y(5v&QeNym5Au8V?OeH4fxel&wE6X@rFVoX>2 zO!XqimhMsN0qO!24GQ+$;pH|Ip^u;v5Yg#8aU9z=^h9936N4D{<9JWXNsY~P1Jb|Y z4;oMpLMI3UE$NKK5klW|y5krUl7dwSvK|P`wi@f^Sfe$P>Qp!&%tka&y<7h9{H7U6 zFdcR5IiUEM3!n*>BlDh;SiwNi1CJiLoc&FAe!rpWin=xyNDY*z_&AX0`k;3haVN}c zxWKiCVPIqU=xRRqD~_aV-@lkla}H)D8EEKp&S}a`9&%ye`VPhm#C~MfZsRL~t|&oB zJ^)ok%))};`juAiUln<4HH^U0kzAC4xm5+1-v(C0=goAn98d>0`WGBmMT5!|`)u`M zSR`Y%AQh&BIyMa6P9AiEURXB>b~8Zs(eQSmpbA`LyKqphQ+M{=?NboY^sAtzqSZ3t z2l`%gs=a9@WL(fHpfaF`8BD>U5bj?J$RYRh97y~2XIfy#$;&Vm??7gBZW`;4SG!_C z^UqzJ7|B>Sm?N;_MN3l0f^ih}rwg)yKcFY-l=P+t{W-8~YzepY{IREOZVZZA8%xE!+C!*COp2~>)DIWbkgqCT#Fnoadyt|Oox2;) zEx*r-Be$FFCYL@(=?Fp{ZZtR7vUZit$cXGy$Q>l1#Z5~o__vZI+B^QQsbYOd$T`g~ zrAoD?xN$NtCXZy-daI{^_Gb+Sv}c=V8sv21SBE zJ8dKTN8E?3XD(fH50tUYkSkRzs9olcR+m!1t#^N}r^*UiO_aYecObKLl#DtSr7(BX z^;%w5XolrTw#_*oDToyWl)d!E3{r<0Z_7(2_qaZ}0?k0NQpW;WN*I1%wV7go@j-B+wG7fc2tL5I{j5u@qZ)vzCj8`RCc%RCF&hl*lBI zcuD|eKP_+e8Zn=-{B;z8@dgHBKO0BR*9X035G$!iz-S(|}o+}>)qbjz=As0~EOtcc9?IVL=_|MF{m*&Se zIgP-Yfikj|##8@nh?~csqT_r zU^{B_XJGSP7$Ibs=RDme2f;vw-x)A-q@e{eG`}Jei1QjH{Rpuls3u4YIr5=x;gpJ7 z3N#F2_9sz@r~dD={57d!hhTGf0=j(tM5HlKvplPR#)1Z;c1nO6#*MZV2DY^MMW3eH z%iYWnFEQ&p2W<0UcKxISk!B$ha_n8zL4^fdG6-&vnpS5Rid;-g4*f&kL4v(Ra*>!Q z=>X`b_t2&f_h~Ba2)JPi^=V#XGiY>{m^{M3ly(E$+ zsJnls3H&hInV?&n0sDu#4-xjyXgaf7r*Fc28B%`}08EzsCI!7o2FM1acieX*|4EZ$U(kw9llH~8Jyebs*)Qejr z4-t^v9W5%_*xX8PMUZjm@es>o}L83d{AMJ6#sLUkw*mDlP8}= z!3!{@#6%;t2n5sGxzzvfo$eUrn8MZ8gGZ{eq6UP{KC``VGBh5DMt|m5oGuzVdAsa) z&wEhdv-r__oTsEsbMS5XM5Fh7m5g@$)M`m(zZgOK|t~wgX{wXK& z=S`--+^ zhpAMf(6SuZ3b1Bwi904H}}WFT1Z zYYV3_d4-Q|6mJau|#he1e2qg2? zgLL?|s*KcXC7p+I$qad;jG#b|pa2xQEF90IaxN)TpV#HJ1;)7ztI>Dx1h*0AfZIM& z$!U}pQ7?r#3bX!I014_$pCG0WaR16C3G^0?hK6u?T}(rRg8ekyf?^ggR81fhGdNxC zGT)-{i%X8 zexJaoisr?@5K2y8o3v*pqS0p|UKM2oM#r<<@yd;skLRc3A}ulE(aKJ)T9rZZ^>5d_ z23~j49%O-i*RO(oL)|?FKKq(TUtOE}YG6NTe4NZu=r`4{6DnCxDlqP+Rs_(i)%cx^ z+AUIcZDqtHi{1|R+Ndtg?ApmC(GL4$CKW21er>Ctbt!I}GcIFmuk93zgrrQL*ZUry zK)im-$Y%2DIW7q>TLf%YqsentvHN0QjPe5E^U1eYNHzF8R;BliqY{*QqvTmfubL=mAkh#jQa)`= z=4XZmk?HoZK}NdRF*&7ANoLrn$Z4eWpKuy!-O@{L#{S-@ewpF_p&ctz)JK@}3$2AF zVGHd^XjsqMC@s5Rdmx10u4IONO6EUh4dn&a|>L@ce!7eEMCt zo#aHz{_=f>a9_y?j(o%8texX@BN>yDs4U&wm(#izD9kUDZDujD4P5qnm3H4m^rr_2 zw=#GYmzU3^vQs8wu3*3`^Q2_A>!S2Mx1GxBh+`SXjkW%!$CS?BrF3k^S^j46f^T#N<$Y;D1c7DF>`N*5B- z%BF6*0|34OVB2KKy!TEwC*e! zICTkNRsg!zUT9_Uj0#!y(paVqe(o4^MXP&?|0So|P%B^0V-en-P3uYV@4qnoyx&loq+WP|UgI&`F5b=LCJ zzg)f_Y*PSTbHh`-T4(S3wZ%x_GUN9H~D zoLd(CFh0-kBA?Rmkp+cIe`1H?J_B@Ypj?ke!5T1j&%YhWhIogUqZ2kRbGyTzhn z7lWc3E1JV}7QK;b^*H%xhAr%re|bUkQEG_J2TU!P{{k8#m{4(Lt*33Y-z64rz=++- zw>TPFm};0hc=&v~)s^u~>kV8HyKqtZcP2AhpYCYnzdmx`fIZ2cZ?~KfUF4W)n9}#^ zL0wuc<<2!ykzVjgi~gOfPbJHa7@_ejz&+y~Jv~4C%|Yg3yywTr&r6zwtbO-iceIAz zdZpV%)|>xe_gO8vju~vnKGgCXbzW;x(*Y)``4$T`y3SK$DR=o?g3{#=68aCWYQO!` z-AMbSJNj+Qt|%lB7(fzTV=d(D=Mmb}`O=UY`;B1ha`mO+Grb$1yBog&dmr4Hxy_|y z>sf1e`;YJGMh&2V&j&-h#`Jf$XClnmLhy_1mR$??l^Cb;vVJm+IlWPt1fW?dqv$yn z8kP3uEHrZ+V3O8!;rzNdLG)D2h>(4>~F)Q*%oAhNzuv$kc}-ovWO+ zV(xV!%T95t0oGFI<$F=DYMviGUYPA#5V+DmB8SD@8yk4Mpqds@SW|DZJ7Eho0A+iA zRJmAgl^O5x5P^CHtZKaHh_-(M?W31rtGI5jH^QliRmJXi&tUR1HIJo37)+$i;tbf= zQ!;YZ71 z$@nUzyN{5wg-C|2iq}g*Te?pA{Mf*`9Q)@w`k^t%aK`JhOP8B!*v=k#m^<&anJ6FU z)0+$SG0}f-$MOU*4VNdaC5`I3xtR7$C}Dt`MYE8TW8&%OIahS9v*_y&+NHVMSMDb# z?s!X-NBOT7=vQlOqz?W%AG0w2>-N2^N#Ah=g@#S?E$W{0mS$#WC`Zel=FFsKrT|0b z&%i?KvGwWO!+OJ%?nj~v97))-oJV!J2S3$3BrzsExQqpnK^Li_hH0Tz+M-dN?1QTu zTMs$v9-6ee+pER$a86gTw+P8KJh!4ui3U;Ua7o2g=fdFlq`@F^$Q+A>n2dM(gZ;e7 z-G%CYcv1EOiB!yFsdkT=Ca}Ll8nNC`=n4D%BZgV7mtyHl;k^Akeyu%DWW|_ntea=l zSyjhz-XZLhtEDt4E7IHzNPDY8adfYbYebh6h%OI^;161F>ZOIPBK<=yk(`e)m+?Q> z9p0gZ88G#3T9uut`fP7oE@yC>b_qu@RLF5M;-U{X6CyXPt67k^KuZl|tQG~m!*kGd zB8TLG=`iupXK9HWnfmDY+;E$mKfYXTbMK7F?J^rGm(lMVd1&`hraE{2X_Lk4VM-n6 z6Vht^1_Bq&8T%i2Yw_zxPE0*MVO}afo7)<^6|LM75hsE>s~{h8FtyJG3A_f-6h?4S zrE#^fuJ6mRR2>VSSJpS}=gbi{`lR?GlREy}9lAQPpO5!?bUh|Im?Pc3N)_E*`f{6- zk*lK3%+q~yde!&)1T@{=BNX<)RO-`XsNqe_w94mQi)7n1{^NlzTSFGv!*SL6Ng_%tMapZ#_;^ai+2RqUU}h zYc(i3^TtLLyj&S4r66TsQpB4DttcgI~TEOu4i^m04uoy;z~G<9gfGDvUEZw8xG?#+3Ti+3C42 zp)uE509r8hW{HMTL+%j)B=(a16KXe&mI{~ii}0l{LvL#r%@5cm$p5;7sgO^azFp!@ zj}>W%4;_*%yRmY53+3Up>>TiL`>?H`u4Q3ghOSk~_^RLIkP*{Y`wHLv{3UB^{3)Mw zuM7R!oo^<=h{F!)r%HMMr>Q%kid2UGL(Bf=a;D^0H?Ot1m=7MWL&7qq0CZ8s-yB5# z^!8&wmB8w_c}jKd_wKcTW!913>H)r})@HHJ9iw0yC*zfqN%na)wvwwAHLS~5d3&b$ z7QQvVWOSm(u2p@a)tB5E)*4TlzUn*>rQ`6^bbmc7e!9{FFLULLU42jVWs%4TPD7=4 zQ*sw17-YUfG~9t9=YoGXLG~b3z~~fFxTup6l92|*QBX`kLV_Epbq_20BFZ{af<&QBawrJ6dKbcJ91 zFyX$#maD309p?>^YQ>6kw$d*fDz?=`(xo;d%sg+_Z2!77FGW8w{e2BBgseqT(1X1; z^eV3ERVWVsnv$W$zdZAMF4VNWU2@)haFI3BFGTV9_v0q|-QJ0;^!%%KFF1!?L^2ln zdQS;=x=^S&?Hfqb(b^duE7Y<|DY4scdc>&6B|SfgjZWvR%`{H}vHd zQhV&9=-5=$2`s{pBY?{8_s{m9>*-lvb*AD8n)CfSYTIT!l5b44cwqT0Ov=~?jH(J-Hp%Bg(OQMHkvgOguLv3Pt@Qg+SZ=T4s$cgv+h6E2|*))A-q zg%ew?oDTS{TFzUH%i_L228wDA>%JEm(Pf*mNY*KCO!sgMY^kl;$$5Vf-@oo>{)32H zfDtt;D)Sz^b+$5EzJw`1r;>TY&{oo`k`dAMsplOtEn5Tz88SbYuHw)`W9LDvX+o8~*t*nnJZfs>W83gA2acg?r#ln0S8M z@1c6z(?zW^g#?qzmh>|#O25Lh)lksA^Hj3)@ob7UPf+^!Oz^q! ze6_sEO)I0NdPdpNkjX)c`FH*G-d2-aw3!jCD<^Ih8AcW?4>n}%Z%IU?QJVVIAFxz6 z92)yg93s6XT&Rx0w>yt49h}qED`R1!AZ{;ha_Z6diOT5>>BW4uGc~Nxm~r4*=+8$D zn@7i?PdqpoO^O!JkSsWCd#BR-@V6{49sG1)XAFJ*A}#Yp|3^-RZ}mpL`X4Owi;9$h zpzwIY6_um;<>h7kkC0VUs$TMjmf7mY!NK$|cuSSik`sBUrYHXJ!JnbP%zTInA`onk z53BIK=Zw$hTUnUbQwN9o_bBlh<9wP&On)99ukKS1ay8VM*uMW${bR7zrdc}NP^M+d zU4cs?-Zp*FyRN}02N%=3pdeFyXl329Hs@7jY7i!2%%ZS;@lz?qGPMm-s!Z?+(5yadR5aW|*4TaU3ak0iO>Yi+np0H{+S1 z?Bd1kUPWl2jn6l@Usui=9HJ*-5UBXg_Py)tj{d2VgqkB)DUrgd)Y~;V3aOL-#Ob?l zl7C)9zX`T?{&u0x@xtcjN|oNjTYtA(ykRhD|FwBPcE;@n`?m4-=>^vp;YCVp# z4~w?m@UXOSgzV34zwfcz$)&AGFW#v6t~sfvXH2EnyKOC|k=}Y@Ydw?1asDhxV;QRI z!SZ_N@E&h^!&1*kbzQwgjo)rf)cgE~_dtvO;JrLP<}Wq8HrR8?%|F037cZ`@{qbB} z+kU5UJbPdM-4aTrQ&W*PY{U_9LeuPflbGmqG*UXx&ixVb&LE7g0si ziS-~Qxf8QKe#1&iXA1|t{d~rBV+8+sda3<@Mi= zy?u-a=jNO5`24npmYz+@*qq&t_el<1lY?m@093R*8 zMjq6DDH{@z8NFyrFjza7YKu*G>pI%r*UNlTg^N5JI9)8=_A4!}^qw#q&Wjq?kg`nr z&}8~^U`iYv{1Ft_jdnzyi@wfRVMc_rPgSCXT==9rHouwIhx2^ZP2*su8#z3O#!p`7 zYTv2liEW^lEjm7Y8TY<{$6IgrL2~PbwD*3QY9I0!E<{dvAf`jVB~O0~?Qtry87X+V zHFt0Jy6VBfs zpN8c(KF=J#eC|AT(uSgSx#q-(VVYOJei=JT2(BTj$pJ z3%9mo39;bm7ai<<6s#wAeBWPk&alMG;Eo=}JnW9Yd6qy> z{H#)PShTDpKo)!vIe6{+e9yq;{8-oRov8b|7FB> zWv54PP(=E6l}-vi=W53Ge((#^Uv$*($CWOU%sleejP8jWr1d?GF}m!Vw4p&mgQg(A zNZwG?tizLcd`Qjn$;K=7OOH{rbYNk=sAdcv>Dnd``lv7Hk7tV_!)mpIz|TW#6(@rZ zte>r%Solt*B0;}Douc@_OM%O*D80eKDLwOp$3{f?JLj&_zArpI{W^!95gCJP&YSDY z_qrZc%opMQRC=sSyQP)M-%NR_uJtfgk?5enM>A~(6(vp{$O>iB+PJ`B-(ejxKASP@ zD`QVAVM9|~p$OGQW5fgm1QT|Z z^)v8WIjbUmK7PS-n>#MQ!#U5q_wDMDs>Qe%`}tK&<#l_wtzF=);FQF9c|D^AnR88irD^T z!{00Um6oxBBQ#CVDYe!}0=St^y=lwe>dK5t3*9M@;Ga=haT8p*(Yro zN$m<`&Yb7=3DJ!qs=OoLJl4xyv$|VnokivQP4VzPs!a8Y{XrvwiLjrDaivCLYe;Y? ztyF5?O_{}ab>%9Ih;3c1?&<#f^-~tbH+J;2-YhP8J}j8~I7d*PPY#rzn4Reg^g?{v zX6;f=m*@Z0ZHc90aFR<2Ac<90)@brRqqa~z(cY!R(fMtj_t4F$*EgVbaL}z`vXZrG z-;JZAN5_xTyw^$Srvn#3yLbGi!Y#jXNB%ARsOS5h@`-b;4tE)ZJWa|I-s6pO6fHVE$k)ebFy8W>oJ`$R?ezoMWe-(X z?-*s%C8lQH!10S1hGemYVn4nbPN^cb??MAV=3_(UcE1{I{d&pOs`M6ZMYH_<7eGVI z%v~F=2u=~&u_7U18!8_(UL>f9k`~u$E01LL?s4G>vh@m5a2LjKzBxRb-#|Mp{ipn0 z?|vENDdWRgCZBU!K}mjMT0V;6FVd_Yd{|pv_F`$;$T>RIyj$ET`XaMoG+0BRbQE&7YFr``ffkH zgO%~1s$=!W9HX8d748=0%QuP>z7ulKr;Gjl>g!dgb{5X;-kJU_o{GO%CLdb7FGtDI z-FR}VS>}}&>1L?7FZ85oQIR1B3q3`n@7Ql$3a8P~3-0~|3hhiw)p(A~6T%OjwVS7W z3+MfpL&c71d4d3u?T_nNvj~Nco$AuBOf51s+_3cEESX+AkURY3rPOD)H*V8)im@h5 zH$07Ui*DGQJStc411Q=7DXHvI}wA1}{#c>{7beRV+rzxv0nb zclPdasi*s?-L8la=E_mBdHmcxG4!ib)A@DDzhOs?T>xAF9o6w)lNcv-{YrS3KCQvA zd@w@TKULo_;_#2>?^=_H1XEgU#WkFeP(w-ovQ!F-%I_WWGnw;Q*~Ur*xYTzz6z{=| z#$6XYJzm$Y4v`Bqrd4H}w8S>Rqk zrIshC@cnRkI;Bt5XuW3C0alf2tf8k&g!TON@=(NW|8wT`VeOl4M+!zJjCrQ=rzR^6 zz58CulQoUBI)uxm;*)iT--dEs`955je1-8<_5LDdpfRgS7LidiwP#rAXr+Nj(#C2c zn3*vy02UrS?QTG9>q}ie^)sp({;Vz z^$Hrlvo}n#o}WC0)16LE?5arZI`Z3HEl+_w%_=DOs92Fdy)KF5zBxR!XpJLtANV!j zzo#3v0MJgIMsq+ozCVAvBI#~HHlgYhGXIf+S=}y^&SmfD#Sh`_I%;_vYcDCyog~kc z?p!9>J-bf^DSo@m5Q+S`;ghkp@-w6?ZX*@a@Q^M}xJphw$w_|E`sn4a{G~XP{$=Os zbiq@&@k7;?RJY##9rwK($2j|WWJru(B(COu?0!)#pT(r^lkQlv`rQ>XE64;?FYU7m zz5d|8hfZxuzf7Z39Cxlb7Ay2uh3ZDRe2!TKM12_QFHth^fyOE8S{D?364YW|-?bSz zH1f?k?J1fjy&+m&FT7qvJ6qoVCQ+=2g=FE5>1}S0IpvrXMKu<;w*}i+7xC$3rILDx zR}(b(yvF7AA6nfLn|*k5P)#ZR7DUgB;zBMyNYt5cvw+G$6|3#$DdA~9Lb*!lrJ!y} zo=-&+`*rsgl7)0_1AOzuYjLSM@rslPWHb#cQgEqy^{DhF0t0GztTsZfZiX4U3|Owj z@M_@?V|Ysv3vSkD4$-+^NZ;}+8COjags4!QpoFFUHm^e1qr7+Hbk*&s9fb2BHP#=r z{E4|{-;SO05H9_N#fzu>)2~BE#pJeFFU;En3=rtD)QH(x-g2mNYs1LK%s(f^M|vfc zX|eviiC;i_8Zy_v@9gn|Z=u=bI+mN5G`Fdqc5Od%^B>{X#jTe~*!TIl`X>Y;iP5?y z+H}0yW3^}2yKToHymx-o^g0$jM|ANjOE)c&N8Ue*vPzpU)##b68cz4RSm%p+`J@}{ z5*?Gx5dUW<`7ApsUBHI{9FqST@f)t#e49Vtw7BO-*utf^mE~0^27IIsWgpY6q_-l zplf_^Q8sp}#qOC`gJ?Du4K#+qfm-XVaL=0S=DFWe!Z(N0{Zrbp2*(n&^Je^KCWDxn z+i>q29#2oWHRM!*U(regfe!Cdr*q@DAf!M}zWL{HZQWhFWTAv?&JNlKH?wAgvl>?g zASW7{nT5H#K_Yo7XXz#cUP5dFp#SWf`lq&o{i&DiWGc1CZS#4Wv|x+ZOH5bIr)ObPNx#y)X((AGaUD6Sbi7|%Uj@QzsSk8 zmm(zZr&D;GLXkdwrA+!c=PEr$fSFlZ!ih!uCPdE+^nxig0fMhJqUX0>E0PAkRwk{z zeuvm5U(Y^p+-6&6n2?381LA8fE?zF~rD_C235~r6_ck7B*9u@LH2DK5+=n0CH#0qf zF&7kQG;Wb*;G)U-HA_KrF_22? zN7mga1BA1h6h!Vyi-0T6D>->lCZr~O7z%Aw3i{$k4Q247U&;uxM2JoL6f3e(#K#J{ z28w>gHz4|y@5hlQ2n_Gt{!e{*5M}zX3nKjzl0EU(m4$#MBZ6!cDs~ z3x1xgW4$M(&tF}mfDT0hdU!2`Dy(2UVv0EyBo2_gjR5B*%0|X5tpATTa7w_VI|F?@ zLFhr_k%M7zR&b9)%mT~qx=+04c$FUO^Ni#AEOZ~phGy!86mdwxJ+cF_4t8!!Ggkb2 zA@vu+KHcdgiAT&?hzX3eGzz7Ju$X~HPxRG)d!D0Zuf^VTK_hKgf1{rhL}lZ)tMT=w z#UdVoxYMAd0k949{h|tZdzL60DY`VMW^yJ-Kb2B8CIc^7>b3t~{V^7imchu@rlALV z%P)X7l-x6oGzmmr#|5{#Rl3jTQ#DG8S#Y0Yh^HWmDK976#v*{i{WTyp@Gp~~!nBCj z_}SAZG4nuJbVHp)N-+9#Pam_)WJN>rKz;OGd0vCroy}h@mkaLy`tpz1%Oi&*{B;0Ieuc+Wq1<19!o za>V(oVWjFW(nw*EVXlRrdw2audt&W*W48jXd@9uQ1MI^N!q?mENP6ZQ$};~1knlbd z%WIj8q|0T8@ZFU3ykN$PsKb#O(@t<1sIw+Rzr?bjx94vEz)Mhbn4a}#3K03>4$AD( zU>pMmiAkTB=-D#ny*xweq+N+xY|MR+Bg@^ljo%MKFYRWH6E3-)IM`;-1_7m6ASbWjm+C=Dy;eM4#?fizqN4onC^+_YjAlPv$v3qjlt z;D4DZIc)H8A=^FeliUx%73dEm0=6y)vkmkN*HcPC)NY;ih>MLq1UXM~GXocV>+BnG z%_zHHbbZv0a{`l0G@2ej)jz@@3N>Chz-ruN{HgB|&(EYD5%5}2hZ|bkl;A_L z0Uo{GH^nde9pj>EUAh0jy3c!Exji19$@|hxsr8og85wSz4C4f|2Z{s=_TmPPjX396 z`$d``^BJI7+rOsx!6G?x5R8&gqr^Z~{;S*S@8sAT@R7VXxR6XSsS1Cw^3_R_Xi(B+ zQl2P%X3mI_0_a|Qof@GIPzr1!#_vT=)F5Ne0it0*nDZcn0C%9FFgiB(urvwcG7$DI zG46t(KOl29$uTE7YA_0#KwJjG)U{zB8calg0fRA+p@0A**akv_JaZikF%nMzp=^M zHB#KwA!ef1L(t>xNQN=-4W6{%`GPU~T{Z=m)cKA7r*nyMS2F z19cjD74-o60oKayVvmKGz$_y8zyLUn`UUd8(!qeGGXCQl7Q_&+3YduiY|)=6ovXC` zdn^dB6TSg?fw%?!TYQ!kX+H~Y!_$lq=IZ~w-BMEOVz+2OI@JDC@xf_e!)72ZgkNbi z0nK&P#Q$OMt;4G7qJGhZq(~_tAf+H7C9&y7B$O7B7G(p{N`t^A1hD`K1*D{;k!}za zkd{Uoq>+YA2;8|g>id4@`|dsGJkP!7{`2|I`?B_0bImp8s5!=Oj?syW0sMk0jli*a z6^qA20wYe}Vq$S8&`|tO|8CG~inE58F{*o*k6Il8^M#SGSoc}dO zWs%cwc6k>~MBCB)@Wgh4^Z#E#rIaI58^|pjCegdlf4#wpPM8>@R-ybSn9Dm_Iyy*d za%c{dPCFr&$oVE!Y*^ptKOwP%2rm9|-2$8g$vjBugsuX!W=&|l+Fgj}5K%AXNlAfv zDV7ikC6dCQ@&3SYpKBJ6$$dX@lI!osNGLGE6sI#sJ}S~=kP&-PJ_lST5!~P0fAgkX z^m(oOvI3z`wn;fpBS44_rTRGP6g&ek{g+af=eBKxKOKzX>*(m8gJAR-RF?#6`6JS! zb(4d`neB7l;h z{ob~MGl7K1k}(7u+3MV-K=-)tB~tz5fGzc4i&J;c;36>-ueyoXUY_k#6ikgunXgj? zA=4kQ9>Cy?HEG)e#cAxMoIbX%YVbfm?#*nf#9U3sM4LcHQGgV@37s=@N)jvt@ZqDu z&KE+t&V!BiQ3?JD%AH9MSUa@@<`<+y%e?lT=Uv1;bR|85z@`R}S}Tz>#wq95j5NvF zirlPBtD3d1o>O4yuWD$F!TJWW@5Wbs7B9KoGnW2rBS=^#4OpmWsUM(FQm-zS#laV# z4iqp+5Y*I-PmKEr$T|#Ehw2V6n@k8=R`^E_G-!Ww3j|#Q$_PA!kvaBff4TO~zn+TS zdU@AN`%b|*6G_O=@01LeR5n&~5D~4)^j`sFH|x?Muq8XujL^fciAn5#6gzb9Uosm} z_m}0rft%=H0mK{tc&hZz>_TA@o^aAK*d!Qiy`VL>z7sVh~59nc|O=v zNhBQ~NIdcWNYRgldV^s%_vXZl_y2y}4l}4>^;b{s0`>Pp<&S2p%Y|JaFkuwi9^qMV z7R5iX?eFv^1OP-hz?mUqd`C9wDho{vsBeWEa6O9(DvXwc9@BI-5-hM0lb4TfX?)udG`4dfEr z*;ugi0YQYU{((dyMwGw#2kam&lK%Z(DUi|5_)8%N5E`qRYEU%;zpJDsf){-O-(j#7 z@%uX>06mq-l`)$opiBS4}!eh>i3ND>{^3QICbtY zBg=&SizV}h^U{HJtINRr^66i{oc$a(QQjk=0d)h>grJ!)S^4*W7vF&k%=hv>;|`c_ z2W$y3xOEC(E>5^m1X#AIr`>kIjzcin*O&0~$jOEEuJ> zhCXiSg|Bg9ZlVS^Et_7@*AaE3fI=`|LIZ9yVZ`AQN_*Mh=epsSnOIW#y5w?1v1kb{ z$R|jorr4fF+P<>&4QF3CpYrFAn*f1(Uf$|zE=NTlihqf?)V@gw)oB9f{?vgBMtmGPtr7P| zBy(CI2mO86i)5<#x=Yd{0g2?a2!D()I}8;*cr3#gv04oxF#zAoJIHTw|6z0_Cl+C1 zT7Eqj$s_(DY0sUW_VkNzfC|Jkv(I*psiE)^5`B|7@$#g{km^o6|ppGF{yjCi5k1Zk=y1@YxuP$(nY)Hb6N(S3OKk`a5&5vQP zHHUVA(V|TK-L5 z@Opj2>-YnQGRK7N?ZF@i)7XZ&1^=|in_sQV+wOUm%|_dOpHeX|asE!^HzdRb`b7`$A(=1Kq*de8$a0(dUz%C5BSVf!pu0 z_kOkRRSDU8U3MIb`YK$vS0jk5YG=spZirO3T3X4Gr{TR#Q{WkR!)ueBU72IrHZ9R? z>mDU@C0ltfIwaeYKOq>o05wkslAOWFpmpx>~L zm+I;0a9VFT%xDi+Y_~7W9NeR1LR*yO3y1g>9DlFAG+r9*$6vlTbt<^(4zl@BnP>Sh zIc>StC9fH6o0fLduBJ@p5_kzvd)J(ebO&Fgxc~h6{nw4rdqUjePb4?dLQS48-bA8j zH8lp6O*^an>KR%*0Tq{1@-2*2C%wSlyvp)dyKTR->*IH~j7=0R4vRVg)j&9}WwOBg z`yAmg-2{i#-~T58Cn^fUwsp5a$JqB@?KF%%75vwYM|Y{SUK?llMWU_0G?^XFe)X6+ z&%sWYTV=v2#j%7|@8_&lQk`^|In+N3b~hWL+jDN<())vN#{xZ)68t)gd6bNy+p%m* zktRur4vAVmIlC{i$ECqL2oX=PBloQpDEKX#W%?7Q!KG)Bg*;|vBieU$5zMJa`s-MF zweAJRdz6HP_*b?Eo^>|wABJzY$+()ULv`9Ry?u&?Jx2ed4lLlQeEwB8F@lyXKzLnag*vwRpxL`3tTkO zlWxGgD0Bz&1EI=PY+Pn}<_{gHhUm)$vezEBvoZD$ z*?xakRf2q|Zi)28*~TxHd>rzGt_1m|A+qz{QU_>loVFZ4=~&~w@tq3y@_9nSZ%8yt z!scQ4K*n-9PXA-9%Ct^!Gja_ovStXt!%)>V&+8yl-!YBn0nvbb5p|wIy`>o^#vCKK3ew z*J|EG>iaN1i&zc0G|8eNR@?6>R%=n$DOKO~U%88uW+3#lwzF4=F_=6igH#h@Oz>P4 z9XOwxT`ilTO*F6PyP9I(ZRK1i zs%GR)&Z8=#`*F(t{Z7h7-b_mT%ezllw)}rx2$*J|V|+31tjDUoM);@QgM^P=-QI0JI-JxOz;kkJWrq&PeQ1M`}e;-b(9HixU$=I!8ujJ37|kj0m>nEVpWEpFDYy zQcIYrzBk5vDEVMqFYv9pc>RU~KIEnhsT!fY%!E`-Q%Ua|-SA|$`sD2Sb0@0j>T#*z zz3WAfBGVV2sFB+Y^}3e1aMSLP5u6(D;?FzVSY~kAQ9ED4`)RS@udpJ$Zz7u78Yzn6 z$)*j2mr=i-FEOW;UbrPb-d9aC7AsdP8Pn`88_$tNk(lxz^0V`@_Rl)DA>U&9*D1zv z8ElzhA^ZN=P9ldnnsC>aRYK?_I65zLD$M@pOGWB9tzz#C6y8IB#OGPuvs>z?V>S>H%HC;8l{lu z!WfX3(18WRR58p|FZ8TM$Z0Y^Vr|r zw^fm54@~9k-IxquQ553iXA&0WHzMTKFnxryb7B%X=`kxM#e}po1Fs+yhM)WMu77%M z|8F*r75TTW`7QS%{D}W$xwq9(wI9ApR6VEbmi}Glr+!KAAic|A1(gA5L*Q)5O5%5w zOLZk$%60=j(pnJ*z938W?D6|%MJ;pX)6!9bT$9cQMO+JweGQo(^gm_Z^<>5)pRVHS zzr-GssYhfnt{CZMcto}|+=S@2dHCz{{L8dppp zxgDiObAz6c7AKFfc%UWh483~G(}5m44KscrvFGRWw8>?S=?!-*9K(NPD{ojCz0>vE z*jv6j==}Zb=_lr=w(|AEdrXqEF#&@TsPk z4UaZfeXmYz^Ldg+-QKn@oZ?n^#kaoMMf~d>Hf5!IXq3}^Cc&S5GM?#*%fapte?y-_ zlyI?<4|N{FB)U61`HsddyBr#2Wm&!R)UxE9IUdoz(gM>wuVR7XHN%_#CnZ$PY?1!K2DOAo}6remp3}WQkszhXvKLS51 zHAM05?xj&ahQ&DMq#I9XP7zxSIPdMOH}ai-!Y(@5?BB3Mw!o%ekU(}(!?%9%?(aaT)O4CowCebL_yaDed1cI=H_G>xoheuy>4vU|g3 z)JXbtpR=hUv7WP};(PWHmLd0#Gyhq2i2Ua^wi>`n6Y|R2+c^OR;K+m#)&HP6MBx7Q z;L885>Ja(QJ+A+cw9FMoi2fgJnQQ$hx%nJk*VOgZR!d~Ear8puLm#I5pKnwV5{j_V zku&IBM^^s4mhd_|o2wP}+#%@fuhn@tYze9v>HSV#{E6X`{c-RA#D_osj>W496=RbEwLwef&C_)rs$7`EdJI0`LM?ucWP&5qk!5`%MZ3cr(H9OQAxZK-By+3)gdALGn}WWllr&3 z$(+){|o;wz{w=Ny@lu zk!;0ZO?veb_`QpqRJcQ#yt?WvwmB!aML%~vpOnwb6(&VE1@&{T=~=LjDh=Cb1t&@! zZ86_Gz9N-dh&~%s<1C-hXH>UkzcC`NZunD)^vg)X!LBfI8C$V=znHLaQ9c5xHi_yj z^2Ybfn`FWrtxdRaq+qneF{*BV=w-ZvgHs0bM0G4PA&WkqvGMxq;tg##KE}A(N%eO~ zc~d$Lh|U-Y7oj*>W1Z(h*!&!I#b-3lb7;y0iqlH^#47RaQ-`acFVsjMkrCp*Q&>7L zM7RGYRF#YUIVa}>0jkxb1HCoyiqqf~5;<(qqv-{$uZEW2i|t6b{m8mg-VtVR#A2H&;>hSmLpdzA7N+(cdWX&gW0?TJ=iTAJt>aZ^>fcPjeEm zy=QkuXZ39TK}suidT-A_`EaQn`J6tt1D};DTJv_UBmP$&qWL4cS8WE(-UP{5PgNKN z^P{&da&zW(g5D9TyLVCai++(hb7Q9!pGP@IZ|#oruUj?hsJOD%?HqLZV_QkW)@gNT z`&jdkJiA*TKpmL(sEYsuz_(345hfZbFRZp2YBlN@p7G{6DgTB}oBmw3{b<3AmqhPY zLUT-?_v46_n7G(es#fh&`h~k^J?&3BX1=J$QlvSq95{^R3l~;3IJ`y`@#RZo(e{Ef z`C%YFKF>`?!K*sx<)m^(h0zavoV=1poq`b2Di4Egn zKApYQ5_Z9JRbWXo?eTuo{eE2R4OU5;okR>RGebDcQ%OJRi;v-|imVK2!GEsp;*hHO(nqcD5P`NGsXF z!C+hZXrUIj=fa0Wb1VlD5bvJLx0z)H)}ZcVn?IgNxa##A*idN1ESH;wD`XfVWr=d6 zrmb{uz6To&R*nzrXNYcS@pgxJ7`8X?-3-Bc1218j&W8w7D=v6EkLQI~= z;jQ`25#q4(jD?lS2so+Ko+{FQ>Ml7*pA6Gp;T)BkiR3GyzXmCVx?@7`-;@$ZE|94! zzf@ddcEV#q>?f9!5L-hwAhUZ{zJ(A1DO$pJeOURYLFC^yg9{?tl6AbCD}s#~F?PPg z0}tidjo(fwl67(ks+$G83BImTP!?MTs5#+#R2Lj*;=34b$YSxx%LbcyKsjm9o20a> za(M045lEWF@G61hhiwJR{5~UjTg3s^UZOQoX6^+sr*JRJ>h9~;7uV34+$f-kP?~j- zF_~rTi}aSw{d->q#|sQPp{}vw;fn=2Xe0{rU2yv>Ouj*==ciLY7I9rW=ExFAe*87X zZ@+v>Evq0#se-(ajglVL#L2`#I^thu+(AXRB4$;^J~r_O@=~`N{#^Oz9k0r1273Z;eQhr{u}!L&_C)1-yRT(RLsM^ z3$nwQxBdS7bK1ocx<5N1HuT(yBiBV;e9;3h_XN`cmkq_FkCna_RO1(GVrKvmgdhLE zbJdtGbK;BfUSK08dr1^i*}C~_{xal%3)5955B4#@Ka?w{K@yhM2}Ax}HZ}`9!O*M! zac(fPz;AOn?ZS`qnguhFGOFn$--!R(aYSWZJx8nb2XXU1;|CtLR)Bi0J7I4ocO*@H zky&{Kn+*T&3^7=az|gt9Z#SR`LXa4ppl-B-9-Lr*SQ=P}Cmxw~jp%DqDDq;VIN@|H z6xf_temU<7Hmn^$#lvv;d-sv6J=rbl>Kk)ojHp=5Z2&YELxGI@Nl{UnT`mm?V{i&| zY5>2OY0$|!i<@&`p_k_VJ10yBOw`wm_%-2#pSr6d`1qp-*bV^t4#;_;;Gns=8Am1^ zeoLPBL%rrMY|wMSY;}BT32q_^SRIWLmTGxitsce}OFRCzaq2kWA0OOG=j_lzg?Hh% zSDQ&M9@|!9hd#9#{C0yG2Nzd_6c?8#mCM9FQm?jIZ^r|BFpemuC#y5Ql`&^HRv(=) zzPG>stX2y}(_*T~`x6uenRrb>QI@gjYB)udB8%6qAlR7{r;eTf76$j^gOhLYl0$&m zl-2s2`m5H;J$yU_VuoBG@G__@e|GPM02PzF&nshyh}L~}oak&z!Sbl~7u;Ux7EJU4 zfNZA$SRaK^i-YOT|m-!IMT6Mi+yO zTh5unH`-AbZ?;CvbjX0OEWm6^+=;h(1Gp`-QQxwb+|Qiwudp5=N5@>)Z}5p z(4ZD1bIU} z-t>@Hmj=hPsegp~M2e;|S!I_(X0P9r#-{~HD^{TY-avJfz@+pxV$a(Q*0kd6){S#g z31E!Ty}d!K98p@4=V7(F_beMvPSLWzn3%XJ^egDfE1WUR65RDXWf?U%$N1s}_23%} z5rn{@22>2ju;r(E@L0LZWZsHd>M9 zLo6`Ik;q2`b*wO_-6L|sD>*^Ql?mp>U*0bJ_G@wHk`?EiE0FA2tEX^Obnd$s?27a9Bm3$z7EDmwi z$>~W4dmXDP3zv7uJmCqve^e3%fCcl?R`Wl~)q%Mc&ziakOZcw396XV0eY_9OD?I!m z2HggDK6?shNC=~40Jao<(;rJC5)s{8mwLkJS`-g`?q>++GoMVa>Fm>nzLQ_Nb$&Y2 zePp9$;y?LGk-ZgQIAF9D7|G#+_Pz1J20o&3R4f3vNb8DXoFh<|^Q3}`%%e=*f-KXn zfq}&r9R&jy98U9FT2|ih#b<&GrA`PiCr$qTxQw!IOuP#MBaI2k=ixcZG}qSDcVHEn zp0DG}<9be4o#YAKo?b6SjKpII&%~|6xus@67u!m74d9VvbG=VIJO}1;KS8-i zSc{#k5Ys~)`K?A?oAjuV{-unujDqD}s?%I2Q3)lbt+R9)#aGfx817ob>S(KV%w&;^ zjUr_>{U%V;uCP|HDC%LcL>a;QNN-L*c7=P|b=U3q;WNoP1PrISaCMma4h%&9&x+hB zGW90SAiz4l?(sM>sgwECQ!e=1`Pm9@q_L9DV8gZOe?aZk-&~3PzZ(~3? zhAh(Wl;I1%Q*GK&XJX@o_rhNz({43fj{frLr|2dg#>35*JK9Eg2W3{ew_I;JZ5zm? zfhR|BA_#>y*j@4FLjn47(dyIe6W^hEM29@u+R<~s1gR#U)J ztteoWXQZt?zU?Sl{g%i9oQQ%P$PH?Cy>4|FNZL7{x_wycdik}b2+%|vi&DdkK1U`| z$R!e?z*9_s)OAL2t6x?Z*o<1$It4WvlFYhTG9M2dd<#<_vW|vQ)MT+BJLI(J-GzXX z_DB(B|H2bo;k)bcbBZORjIk;qDV<_*7s0s%z-cIQ_Gj09bPIeJFj-4cpdmXK`o1zwHP{L z*AsRui@1_BmZsnlp6?be;yI-vs3`C8NApi*Zq9cS_afc>sL>S9al8RmkgtUD_X?Fi zWur!l_B(O?!Zkn9VDAh*OL!cAE~oLa7x77UW>*$lZssBZlYqor#)P`uh|72|xFbmU zX>UhW`)okvkaX~?wWs3vyKph#n~w_oh-ETi6?v!Q`c6j~Y(Is~sbFkF9mlBU`1BXA zFZCu$CvG^Crk-ZN)Y*+ye)Ho;qjYhGAGl=$Z(MzjEv1wTVLPaSWzIKTe|t!ya8@Xx z%Cwm;ADo&3BQfc0_ROWE_78CB1R0%3xK;!rH@W3?McNgu2*aqn(l7%mMjDZm1C&h4 zUzh_lq+0h6aWfy%DQLbWDv>{D^knm#z2(VDkLWs@Z`JR8%TOIu3ST`Z4D>>V(AZZj zR3$)~qi8l(feOoy0)>$stIwUt*4g6?pCN(P_&mFz#kfZuSpyH+UyL;s%--Yvn$L^T ze05%o}9xZLD5(q;_&XUesO@ zq4xN!;j`uI)dMt`KLDS?y9SmYl#;F$Nfurn_C&TpW)oy5W1IbQlIgVd8(UtNmRh;o z#MAUZna5wv0zNlKu9HV;;=Xzpa)C{N^_GiptsNJ`P+^=Km4arRx0!-wb@9qX5zgR= zOEhs8(1CnaG=jBOYQL?1UgT9+gIeuo=iCd#-mH84+#Vt}%{ThQj%08qAPFu~gzQI^ z_LjMOre6@Nw`zPnqr3ljo>r})Bw)nHnY_9HQA6Ir`HAsFg z3zaze?uvqCNhCJ|v#2wrypPS3R}mBgLEKa~cLoi&jjW4rq<2Yj3(k3;yft|7C1;^U zKV8lG&e8763kY%HsMpH3EY_;0a!+n(ihg$^s zjOfzIecE;F$Z`{~fu;X#`+DhEzrBzgpOqrr5N?O8DHuY0H!h1Dy9#sk`r>^2Hbr0eMgLEI?aGF-&Q*0F@nd&g1xYr9Y?9I%qiG* zf|pim{%lHWKiXBzXvNYyBw(!?mWw@~Y3i115-_kymGoP$q4R>%iYVfUTJ^bN_4s zNm~kf7Dk%ImgsjgT??`WH23ua$qMFrTT3=1^6;+d4VqT8CocOOjPu|nMEnqD%UkYba=wk%5R6OhGP-6qeV;%e4Fe=#p(U=&Ao^G*ZX!QYBo)e5X_MzFPF=<=Z7|P94pm6DEiHI@;O=C zHwEvn9Ph5KAEG@QWhc5%5UWaq^B;oNKa%HkS|8feH@gHmQz-EDzLw}`G?LiIo>!mr zSeIH#-XEV;nqTqnprw@T-HJmrzJS)jd8*(@T^1}EP}COkJ~R@x+#OwucfUwfd_|Zl z^f0BaPuwy6PEp#8Iro~cN1n`IcLz525Z^P5yqw&pB!1$r(?27tpRRRr-DAZM+63rl z3FhPs=&l%We&#iwbkuG>ktdLTxKZ(TqtvJ(*2za~rvR$hU#G{zJ_mtBfYZps*<8_~{jrQ19D_kOFJF%xCHzgU%iC%s#q?F<1Kgt*q z$kLj)-T8kT=F!Jl6YM=bCY}046H+I|k=uMek*k!H`Sw(mw z6n*x$a6M|W9Pa;C=)JPGOL6NZBj%*rb?e4QQSAXmV?lX7+3 z_dM2nwY3=KZe0Cjc5QxYeRWz5C_NqQr5j4F-8M&t__m z4!zie?X9ohwo$K=;)s@BEnHb^e|G8mhIn_aVZdra{$%sqYXJ`s4gvKkaH9)-S{0d z%kS0LH;np8Lto65b%b^{*fhS_D!1qOWjYsI!?fYck_8`4=j3ZQV-C!%%{sX#LijsdCGyf7 z1ISvs1bULA=G<400`jH@@a=8F?~LD(YRwegciycSx~LFU z_Xrh~;w^Sjqxp&|@5ZC6gu3>(7UOgoOKZ;=f=EPEY#HuV=mqfWbAi!+o+R4XHH*r@ z>gw~#oSk3Wu`i}KIp#J{-dY`;uVL|GH?~jh%kdYE+N|&z;?>Zk*mek+EihpImMKxu z;M(at&M*Zw@3+3D20&tC1y53=8Zh-;chA|4mteU>`D)hH~GZAYL- zQ!u`}&zA3P{gi?BaAXMa@q&EqXt$`FW60+Mn<6>V)#f{wt90_54r}ePoT`@>`40RR z^5z7N_pOfXmtuS9u8ziBmPD30(#!iuCg@z@emg6Lk;DAd%$af;$>X-ZK0;Mm566*x z`QmJWJIt-d>rR$tWqk~R35~&m%mbxJCz7$vr^sacidX5!H6+6oj)x98XX*0%YZd2^ zG!;!5-)p9pbF<3=)#G6%gO`|`fN{Q&O>*u16J)8 zq>v|#s}{7gf4Mv_J<*xeQhV`Wb*`iqJE7aFYd^|&z&^8~1kXx$RhJa)cyLf~9LN=c zY?f=z4C!sPCXM8&S#)pDSr)m~-n%#K5#O0Nw`t-?)>P}G&|EnCdLo{G0Ouj2UO$?& zrn;g2;HQx^I@{cJr)v2$nclI9fJ;guG?1A1x#y=pL-{v#-!LOA^6iB!^S!vNgHkEM zL$0if&Ru2_lUHjD2I$9@^U3X%UURh#iJKC{>U9 z97~mjeQaiO;t`?MjoLoa)WW`Np|%Q+i(uYV$l@=Q=HGKDr54f=R6q5h)lzD{X~mbi z7S%4ba=LbQ2wh4Pa|Q&8#1^%By{t#^q3dAZcQX_jE&2_(&{H_K^7_C|x2w~fbk z*S%g+pg6$+r?=PVnC5OIXlqgE?UE!l$7sJjzuO@n7DPr%9`EBV94nnD@#1T3jebK$ z;jx@R%!+$NLa4{D=3weQ&&z@4??C64luGTZ5EmRFV6o}v#Oa)?&70yp;O(_H`J!7@ z{3*COF{#r}4JQK&G6F86%tnl?W9LE0>e}v#x6?cUxXFHN4-eA6Gg? zEM;I>g2}DqR2WvfBRy6F17!3W?8)P@oOU(a#2bO)8sDVxemxKV>lYNb6eb(~0a5tV zl|e3IuDloS6+#H%7Z{uuq*N%e9kx$lo$`otH}*b0R1Ql2{5fQGW1ZmQEk37BltJEE zwd;7Q&nnU_d(^)RiBuc($7-yaFa0{lL<7c9Tqu#S_M7d9S#YeHaPv>D!fzkibZ%>^ zi}LLo=<}H8U#)dqm9J9;0bbp``}^s1<0cyEctLqMC`Ryf5c@cNHJ!*!`fsy)-n9fv z%nOQVK~2nqR}vd!$oK(y(d+Xeu;j6%i?ip5-?aTfJ|M9+(zzQqG4zAq3MB|fRTc)N zQDavo4{iPIimnQi#?K)g$LrDR3?pqCP>m`%vk$y4c zLlfs}nyamRD+BGmgxOUT!vo}p@9$rNddOy7hO%g@rMQ{u3nYV@gcCOKmKd75$r4Mm z62VeIBV*4WIE7|f9j{y55o0o5yVFiGU)A=8hivz<|Lm6e46dH;W*WI?|1|$d_!P`On?`CpeNYa*@h0V;8YoE~4tnAz0wPtZz zWqK8sJ6BGgItdnsETQ)|h4@+Vx^#GcvC9>oy*q+H+?&6`!Jz*m=E1k($Ip*_qiQYc z`GL-8(J8s`Agk_*dLHSR^p6Vn%$>t|$yaz*b|Aj=tb*R+!FD1yD*_sXs~6;_hh3lM zz;eeIt6Ap`2f={CS!IAkP6@;Gm?t#V_kY zb1a>ekM`^NkaYb6qVm8qyN+8Rw*d}XzP#;W@TF_qeFUHTna#c9N7_4Wi??U`U7jSB z&o-q*Q-_551ie2R_jrBXc=rB-?IQn%;swyVy%JHmV2E8N1l(MaS`UIojfRcco+txm zk@{!G3#+x`?V7D;>X#n2=XtG%S~nz?gAka_-9;WPZY^wR49?(8nzx(qBp{E|9v_J0 zekoH4mB#A|S(_vwU&Xcn9a5NkxgUXB`$5ET;@9h!Oq*5NVoxiLzQzj6`WPxZVojgj zOLnW){_;5|)q6SEyQ*g8@sO5$KKI2f;5^BKZ->*}(51Khwf9W%o%lDyOfDXzZ$FJN zm822;wbo0Ik(N4VVq}jqdY#|d+7Z3m$L-9yHFfb@q`ASCn=rarG)}YQDsUQ01nvFO zI}i{a5M&vx3V)GTbl9Uy>xb<7%p1$m)w9+%6{3?X_%jftocdVb+E!WJ#N8X0ta`3t)#TjXBP+bD_ z?||s$r&FGrlRJe`D%}3;nVoCS>uCR!&a?1y#>Ik0b2mU99Co#nFPwcVZoHSHzQ^We z_ob^HyJqaTXu-sqxLr|iXfoS=Z4gcn}4NU=ToXb-+` zTjf;2*BXk=$G0MMH*4iJtHZyaKNTD|G_Pa3eSY?Hmw0Sh z{!cc<8zg%xmx!=GnH4d62AXDbD%cJ zHZ1%dMh293-40&k*K}pZ(E=6yx%BIdVT$yq(^p3QxpDx4NdQ3s5= zGHG~lfQT)QWivNGJS?4$47|v1sdUGv25@pVP;zz3%hF-)LtL{-L}<;MlJ&_1?#3jN z9;;g+^vhJ2q>W9yYI>$WeFHJuv|NYhH%86LB{;RPF%?cw6ch?V!UOT~%mX`LwFa(r zw|*}b4o(3EMM#7YE^YC8?jFNQZbjS!IUXWu?kXWCHDlLAbZ&2nj>xR5EB_}_>caA+ zzW0vAn4T&V{4EwVCF0e3F0@)XNe?7c$J`sgeCD;fr$O=toJ%aJD7jn|7SVw~k;8$F zYekI@x719>%qX_e!9^58^OMGYD1JP=zy0c+@%>G^`7g>_ zfxJ^o_!GdcbakQUe1SXEjW6{=tm99^1D*nkLr!b=?(JL~pO-wZDuz z)I$#qkUG#<9Q!}s*~YFzNU*l2-N_!pG5S&#Hp?X}FtuLg)~`75VtRM}?8eGVp$-%= zD3oCngVX>THg5JbS*JK(L8$hb8AV+b`8m}HjzDtt z;dI`qREnNH?Qj9S>S_vm!J_RCDdu5p7v|9`Nw36q?-5G2I`DzA7~F*!&|m#+#^5;E4D&3RhU} zVRQc?Yjgf^xHPqMEsThkRe68ID$e@E5g1;KE8#2U_E0|)^9KDQaxR|mbfPJ!vS|49 zx9tzDvelkdJiAf#m?B}d+?}p!f^vUsh-o}&uF*CpI5y7sp(99HPvDSC$S0q>Vto>r zYgZk4lwUI(5h02sXVVU`p?uqM{dq?TysP_MJdUHDfmN3Z8#Iq`_iX08HkaCCZ~LN9 znhpNEu^k`FGSK|c@G0LdjJ8IRFUEC*NfxG*CeMr9xKuUye7mEn%pVRY4&KtM;StmN z4BY`G>QJ}(^fsGh>D-M2Up8J>r}H~2-;%M_M4q}BK?t-{f)2Ta`eye-9c&#@)E1mc zqE!e}9eS3Jmg?&b#@$RzzFybU`CLowy>AF;r4%m7>edfvJ&+3Y$d{W{^B;ze46FMX zW6A_fkCW3YY&W{<1H}p$O=BlJkb553La+?Crz3SLL2gbMa6*1vgxVaaoI2z_)jDr% z8$=Jvz^Kwwy_=O=xF|LNk$`cbAOi=vjYG8f_eXf!B@#aGWF$F3L3{dyb&k3~;C;yv z4EcCUwB+il4}h77!+HUi;o|rY5gpR)rf+n?ZR2laT?bAV2-2v5VuZFcg%U&Yn(~W# zIzWjr!(TX?_QE^r5_fznRvVc!$GJmc4M_ud^O`!3)y7;>3DFfKYXiA2=?sV zE!r0Mx!GEs^v&BwV+#&)IF6tWK>$7PHL;1s2Vluw!R9$|;Q}R(o!{7EOAao1s`M*w zybd)y;)_JR-=7=G(1VE{z*>Wxqu_n>Gx?p1bf(|&3_}1UXxL)&!?ZFnbO{6xP}qnI z38e3Eszu!e4MDD;(Ppsxw)&dH#NvXAdt4zIss|pUp;%2p>n-ZzFkNAaNc0pSiGwsC z9Y%(}0sV}`bJ}UkEagCt+%pm|G$k8i*W|wmY#!-iM=|HkO(!fw-9y-_z8CX~uc0&@ z*!|j=%?dp8tkN&fvFyO44@8d^7nl$yc(j!VkGmX?$SGG#;sp_%s_)WeE&-H4-#a;{ zCxOMR181;cryVL0;!`w!tfh&NHA%~JU*S-Wsvg^!TMixul;zfO?&Pe8vcZ;GhHm|P zG+=5)u?>|sUqAcu00)ZNOY~7zwZ~FcdI%c=dI~qUjPjtE)T|oif5@_>q`q}Kow0D) zVe(BOsmNL25KT9qjxQENXjEXS0n8w(^+HHe6Z5Pj_B`@sTcL}h#5+^ke2{-KH`se* zCl_b^>6I3w2=mAnp$CFON2dls@s%{O9~-HXO2p6(%x(svzpCDsE;H6-CYsWmWA?`b zi)90*f%;iga`{E+jYB+3qi?;X<9zUGj0C+Vegu*(~3qPmP2V z(TW8wSr878E8JRT$35{J#6fza=E*mKXR2umd3@d_n*@8tXMz>pk`#ivV0d8viwR1K zb`*%eFT8N)Iv(+jY#(LOFInlF&Q^&|-+H)ueZ?=M>kWndmR(Q#ZG=A+B=|T39(~tb@>KP zXG|}2mj*W#1h-LwMC~T#?+YGRV}TDTFJ1;!EJCG#DBuvbSO6)%CeSg2ZqU2w_ONx`e@ z<6svDl6?2hCXuP^RU@-6Zn}?LZ`5H6pT@~u1n3vk%a?PwwFjzCLJx%(w5fZ(-)cdV zm5|#rO0a5axTGe^2oe&GsK)6rb}Prd+50R@$M<@L%kdmmFo4>oK7PDmax_0SDAu)$ z-B(=YF;^33O?jXqi!+m-{Kn-BVGADx1zZ^uQ<+JOWI@V+k;*W@D;0G{Q{xqo(K<@^ zp{y^$0hJ)fe>QdocQYi>@n>prUc>|>!iGEJ21u1n|&YQ&ngXT5ez8wz^9jsQ~Z^37acluwfm$-SVc=TbrJQ-133dQa5L{PY z*|#g^bfiI`{0d-5;-%ONchbxK108XcfbbgYKgrBY>&bePmEJUOg1vH0HW+BOiAFy@4*_be9aXZs}?btouIC@NL!9aDnrP1`c>w2Vfh8;yQ!xd|O9X-NbO|o)wa@>?-c% zD}W3)#P3@>8qa=md0HngHssa{r#5J>)918SqI24%&!2T5>YqY0$?;L49g@{ zza?!fLr+Wd>2{u`i6e7{ar^TOf3RS}xHC#%!Jrfsy!O#P^$o?`*TxQ5#T~^%6`y>U zArVU4%b@lJw03`fxizXWUw}rit;>sK_@{PHdC9Y-3|~(TjrYJXCEgFGY1h7Dg*Zo> z2#^EHPPso-z(n5o6@X=fSjlKs^AHL|JnDGus>oy2a_!EZUJi95=Um%lVG%M$C|FZN z4R9PP=d`-79d61FyavEaopmN+Eu)L56G4XlG@9#=$j~Xi9{))(@^W)YgB+ zNGDvMlfJ9GL~;nrK@`Kgch8S@=@GR*aW=UpJdSM%iu@$_QX%53l|K|>pTCX0psk^m zmI!_8edxHC>@4m;0LG%A5ey)+h=}YcmYhdopG!`B2giprgpM*J_^#ljaPw}CRwQX3 z5#MmP%?CbKY0=bIGaU(YdYQTJ42_;c&?QZcT+o-eq-)tLFtWu$ue$y4b1W$e?=>L3 z=2E=vqM>->?vuVpIG{jh3k}c^P(Cg^{hx+QqY9bIbKm(qc(ZeZNm0oh?CHSo%+d)@ zL@0*)i7!*l>k(imL78tgi9kua?fYt6t7Y^d7A1r-&d24M521)oTow@Y)&0!D|{+ z4JTZ^eym1P$2@Rv z&pZnF?v}`8h%(UB(9oDr!|56cm&4ftKERc2j+xsA3NL%gqe92%Ozjf81SJha`Rgb- z*wJ7_%05R;+hK)U(*|d6Zy~TbfN%(``-XQh(y+V9y6-kjjcU ze~OiLW;6TLn)-k}`p=%817zxhdpBah?sN%;JI-niOrJE~5`fR=u)$ypZvUHO^WV zjCvZ3+O<@r$?u>J$i#kNU)yxWryCo%65Fui`(-&(!f{=501u}ZRW-2#{cS6 zAr{h1#{=ESfgQUYir~E;gHH#l;As}+#>dCg+H{xS?g0daL3A3N1#+OGH*j@k?-YgI z+SE?>DLL~2D;Ms8jz^T*cBXr-KmXO|1?|8yp!}LQYZ{(&Yb@B~8G~m>^o(cwhDky$ zpT`rr=pPt;8}vH;dVwDJP`PlR#idB3oJv0LR#cvF8PJ?u+ZiOJ#8dCyibixk3fF}9 z5WVnbF0CYnhT99TcAWK!fP*~0Qjo(@WZBc-?53t%KPyk6JS>nQ|l`x631>`As~Ue;Y~d>2R1t*tU~c#VvSp{hgXMyRWkW}a9{-3 zxWzOI9Br&-HuSQRY!NM)d-P|>UhN@gg3n|)T>RK@&s2~_39tRIR~v!mxFP*XcF%P$ zvNxyqZi`H3euYntx5+WBj5ID1KC46W@FVf*FD(u(fE-^IedBYUiSr={IQIu)GGu{U z6M7;Rz@jX(9OQZ1Ps()83U*#~H_1Tg199Yl)d0#dOtwL-#bPg(Ho(@;KltGPV(+b^ zs_MQ*;Y~LJ(v8xfbk_ky5JV4xw1m<~N=qC<6ln#NK7t@92+~RjBAtp7(jY0_l6UQ6 zJkLAc-yQG0-+$j2*MA)A?7ilibFSHIv!>>d9`S@G(DexfUsRK!p8~z>(}K&Bu>?zJ zI!a0eRg3+j@N3E6n}A_SY~ z1^RjY)nLsVG4E9=_j6_FjC5+nMCaeu_3VvupU;(m3IvBMcLViz$!jwu+;0^Mj>ilg zCXBT(8Y6ZmMu%(yNd`6tqJZ0&B)q;l^l_*3)2%Pu6~*^xZrtvotw2YTVc2G>Cx*nA zmMhY6J$t{h@Se@ww}bY;ar1ovnIn4R!HK0ZdSGAeUr%~o1?>aCrNP0O*on?;9Q@0nIyZ)?93e))Q(!7x<`VNYqbmz>MvO>8F||tDg8qkD_O0J5CE`s^=6@KA80x zj5~)FXs9(ZLLOl&;qezL&T|L!POk=;*0-u}E4#Fsi-8aB!xKEbFYfvB92{r3rR~?n z)_B(FtJzfmoAs9WT0VA&jVtoKkQ^ipdTc-jWum4rFPCm7ks>!4@uVJU3>(wWn|ADH z7(a;cB4;IOxhj~9IPsY!fDop*UDl(h#PyBxX_ zI90%Ox2W#nC_z{Fp~S7UAhr>Wl6Yko!`{!SEL*far_`Cc$j7J^Vyh;=rD5bDdr-fd zpSLs~7x<%**N9&nJ*o8e9*RD*K#O>$-~DPPesnS3NI`T3Cs~t}km3SG(A}cIR`(7` zjglDYeQb|j+4;}D61P(42*`fwFdRy)-#OW}k=MuX4KKg7lsR5gQNOTxWMs}$UU15T zAdbOh_0efw^}r}Z@F7tGvkx_Wm+ZXtYC&kfvTgS(hGBUnI}OFehJF5p(Oioeg5`9l zAA?s`4xidb6zj7c9y#5=8}@a7VpZtV*?MjaD4rkys*?}{s!;N|lUHw_`SZ~84-CXA zd;@#qnE69}jn)o{D?;ubRGqAiu@;_^tPXvBAQxYG{o@AL7m^1 zG9RxVy)REaUZ6g%ar7&_;_sd*_ygxvVekPFbucz0xO_eZdvHRG*rB)R-sHwx1s0R) zpZhwcB@?Ryw_G|SDv1PkhbLEWER$ChZWEsT+#SCf6vY~xOE2<39bI$MgpJ3~iFBXP zu}C;!-inm5(}x)^W4E~O_r}DDg351zZp4xSs`l=l!dD9XI4 z6NTeL$7{T|cL|d$aIlCHXt1phxv+t|Rh$zeeketYTWY&eEi|T7v9m}rmWX$$d7hSu zvd(Iux=TS;WTIk0spkaur%XHELyM2>RKZjz#7|W;5;yn}PAqozvdsJw&O5!MJz-J= zUHnBhx5Ws^D3^Eef?R&OWR^$_c1P&m`_StYI1qH|DDL@aCRmdwp%NG57*#nm&B4 zH0VgKxrpAjUs1t+x(X$`eo0=y>#iemjbch9BTs73C;BtvcLZ8o6CE}i;fE89t=FtY zm!LsF#*zMmgjemunR*V{vWw_1+Gxo2<1HWg1KY*Iszfz)qyURJ?wvP6!f%s8eR5Fu zX{4{9^$@`C)JKx1Op!GTXY{O;ceo`(~-6g}utEF^n!``qu-e-g$5O0kpPsvp{n7ifk zeC%PRu^m}OYKZYJV_q!c5+D*nRDg+QHOb{qQjBpz?V(k|gjjeQZzMURyMdphg)kZW zX&}xIH|be>j+6Zaj`z2sIs<}ct5N&&=*j0yHvMJ~9m&4nLM=oIWU$=xqeH_*FPns( zAINsr#zGte(JSuwE=rL^o-!-X+PLYvCI4u3M5c5{l-1q#8nYb%gsVvbCe9btBgq6bw@jgIcK{w~`-uhCXMxN6Dhle% zFdrY?9Y}Uz9?<5IN;gkEo^BU8T(S7JREg6|lpp~Uu_j9t-e%3t&mx}YvH4bR+?VB@ zP<80Udu$XvtRYA#7V+i%mAZE;a@+d2rAy>0M+m5bC?Qmd0-AVWDU2p7|D@b#D{3TF zYw4HwUWd&N7y3*ELP$4}^KzdE%rlE}f;=T@Uz=W8LvEP&~H;hBLFKK;>SKO8jY z&z=G-pxYo3C{z9OXQ{Gw^BG5**~3ptz~#=VM1b`uuDQ@$``Agh8lht6l)LhouSuy! zrzblraJiAKafr9U2(0#*kg)o6k6wuFj@~H*%smt>*bT9M?SU6v(?NGk;?fZLv4DA~ z>#}y}Kq4(H^;t-Qk{2qok5j3akhPQk_*PDgu87*T^HdlYQj`aDvg(2*1Q+$nqZeWM zx(p}g1j`3Z5bwYv3Qk=>PvUfs`j(zvMqPt=LlAG1Vc20Fy}h0{c9$~yrE+puphb2h za6;hrekK<2r8_I#KID>k->}f+*j%vQLqngH8+H1%%{}~uwUr^Dwx*m&i2Z@3>rJ}} zZdp6_*UPyGIjCM45EIfXhqK$K-1n|!&1a|Qi-``C1XeG5FjXkLD)Brz*g_l+)-7;D zFqk><=xYi*^95kHxHH88QV6U+pV`yBolPr_cimx596NS0-tV+sJi>?z`4X%OJq5V9 z^c*knPCYO(LUUIc$*FH6&j-85AueeFrEmolxF(daOShc($=W?e5M4n7oq!EpFiXdE z@QuX{84s+O=HL;+gwtTruRki!tC8xd5RetPdUZSLFk#)_M`+`=O9HYHBp$tG^Xv5b zry>?e^UsAj5Kv+ z#mZ=4xOj#V>u{|9eEMk z8rTg8Mb3Eax6|WAPMyk60uH|#zvcy+Kg2K=6 z-Jg{E%8q{)+~QwOZ{H7zE*jya2EGPFVtNLoLlH^(k=R)k@CyE|NLfP$b2m$1UxAT<{?`y$c zYRF0r4Sn3y!K!u3C8v>GUb7Mk5hHO+A!iH(TQ-x=c}LgI94!c?oIy@e@*=`*qC0;q z^|buBr6z`a7(F1cEk5kgTbvc7sO$3K;Ts{|SAz3fc!*(KO$0U`Z%0Xtn-_V>qc*Yi z8!pLhvsll7BtW@eAwm^2g!@7lA9X|4t~I?5Lb2l#*DE9ymJ!)$PTnR)aLU>}y}Q%1 zQvKtdvyVKLOWUT)G2JIR!JeR(f{-yc@(R#l@mH(q;n;a`6&n&2f z3*P9<^JtE)gQ}Ob^LTmSsoKfFDXml%*c$wsyGXX*exBU^o7S#_d z;{Br4gFpkffM9zG)HH58KfEfLyS9qPttApoJ`&kJ2k0#@;J{V`H&{89`&Bjo3z3BJ z1-LBYBQF!`5CAtBcv^xAfp+eGUFPwe@Dj5{klz9479O;FnwJRH1N0qjl?`#ZWAmf- z#9^LiLQqvE;u7%c;B<&Z{3qk_VBOFwmZzh~Hyzhx-N{wVp*Ud3Ghv>ZdGuP@%74j} z#G8I!DS(<;?m1k96|QLY&iGMM9mGx){OBQgF{Wdq(-vXTO`yHLA+I~9WfTxx0@)=a zh`@G3keIApm1;MJ%n+CNFV21!zN z?lk#xr2}-3!PaWdSeZUy!Za@N_sala+XDI$-(Kp(XmGjZ)b5kI_d$oYz%;cqb@5Im zr0-+5j;xt2YInrLL}L709B|NnRwXx$%^{?0uzMOzn%7%y4n92jnp4Ac^5HFSJ^S#s z@!GM`+}K=1FhiN2g>uU^3P%a#o41@)dm`fM&_Rkt{&x*j%q@(`>>eT_)M3(E7SL@2 z%|r?>SQ@r&B1=<8-$sE&;?4zA!7^E~9q?qozy@KKb}EJW+^KEd^n}d`>_r3fxN`wm zz1+c67)%tc$x|*ndE@q-NZn2qmS@cj>?jjzy#09mSow-Mh(N8gu4D7MAlYTKJwRGR3QD! zIGn%_Llwyt;ki#k!^KL{jr!=I1U0|}iBEz!z%j4syQzYohY)`mk2X&$nf_hm&XH@Y8a8jh zV=LY1EuQ|lRISvqSfsjZB832QhzH2D`XG}6$1fa!Ld@3omaK1}pnMqQbo{K?O+cnK zhD>(g6Bq`xW1YX z2w&;B0WG9=3G6Zy4f4B8UzQ#MQ^e6yCIHiq;VPx9okk~K_HSe83ykog*q^I-Pn7qI1>vc#K1be#&m+LDyk}2c?rU*46FU z_UUV%+K#QnZ^uR%!#f5CjD*t~juwUDP&EKiW-tBIO%j0xr|GR7j-y-gcf7rB?9#Iq zotYR?dZJceqKTx1$`CO6Q9we6H;32?h-_>M8&;yP9uh;u!0|&+F5rR_{kyL8)(dWR!{1&mZS6JfwE8@MVr?2}MgO(PHo}Qa~SBKRxuC-m0@@6^n3lp>u5a64L%MM`# z{W>NPc1cS@enq@eqFxCfb-_R ztt@MYnQ`-9px(Xyv9GvI`%8Es;q3pq@=QTLHr40<{8U6a8>3Zk%iq z*ERAO_$?kBXAk2bMF7)7Et;HGa{$KYUe`oe(;%% zUKq+Oyhebw2HRdCZHf(;qLM1vO-p9EU3;n-Yj#NLl9UKl8g@Q z0$^sP&FZi?9+Y+#o|#O}Xwg)L0S$5!2qY%;=CfaZNiV2NF`|DYfQ%Nll@=EX$Sj_T zLzXZ~hCtV~b!j0CB`9x@nnwyI;Qtazuu%vTcoxWmTZ19&hv-mzW6MPGU&QP^AZN_W zEWt$oplKPX$-MsY&hlwdUJiLX_Jqx!9Poe#xY3UwX!!-x0OZ!Pf5Ps1HQ>z~uoq?L zNl@Q$HCce3BvRTUs6a(Q^0zb9Q;oy22T>mKl=W{W5`qGq-qcq*UJ|GZj!Y4T;B}w& zU%ppdYX?h5hD{tP8Swk{2OxB!zHAO*Y8cQIU}er{(0>-T)Tlf_VEooE0(n0Pymvmh zh!OyD&fBwBamfg(SA!MR8Bncx)0pg+$r@>XD~-DOJ7z=PH;R+#!H)yVi^Tu4U=`R2 zUevFw2!cjHN%Xx8Z5N2Mc_Zmw-G&ufbg(<9 zDMT6S)C=?X^w{#E5SP@@P`w53< zMI8d_4xWMzR2Vag_s3mKxJwJqiXSDNt(>!Y&5Xy%fn0>O1T8p=Zqs@H)Y&-D`T)Ng zJlw|y>CZJb*akO=5NOw#W!n-QgbXbo)JfGOF`Xie3j<{?0$db7S?H!VmZvCzwwF!I zNm0;y0rDjC0qXC~)x3WJaDk^>HWI=8>}<5!IM$TBL$F;z^0J6;yAtJ-E|8$8h!RL) z3E+Kl#|=sJB(6Ofh{Xd$8>ZMrl?gPGib-12-kX&)WG00OqO~w0meE>25s`|&r zn9JB@-f&+WHF2t~KN^{F?QZ^&C~0{KT~>dC91d{UW#*<(G-J``bBeh0HT2;Vinu5~ zwsve7JI(M`hnaSr`Yv3}LRj$h>S5n_H*DcU{rdRo{ypzX9+?2FxFke=IIJI8$)Vil zOzOw4xK!dE2a|_Nyf=7@1J|Tf-r@l3MGlzxX~Qn)U@wS1e27f2{Yq1oJ-YyQjw!4+ zFD*evwCshO8At*-0Y)I?_QzT(5ivkk8vbsW1klIeKjr|z0wjkXY}YSQszt{!yiQ!@Z z1pXle!2|g}4-!PKW0m}hs4yW+!RDv+^Wfp1!tY`(XwCgsHx?Jrmfe=Zzf2(N3ISP~ z#h-P{KsM*!9HISNQ_gyTd)ofQ4~T6rBKRw{UO$%Yu8 zh2oR{897gsn!%QT0%xq{w+RD~CeMW$3#|~N1Zp1ERS5tgR|aqJ{w5ECYfLcF5F7)_ zHGB2}l&WBdh)De>(81sNyF3|i2qxgQ-z)|m*76=-A>S^3y}g;rixDP}u5q)7uO%f* zV3Hk*)E>WJ5JUx^`->8o672bx@M%D}$=^{2Y(Ci4e~-`o2&y9_SB#%NT?9V;B}Za` z6f0-utgVX&gbgI7aDh(fsG|tM`GF3cF)%*e9HWN~V{d`MsQjVGfh;5r!o`BMH!|>U zpso8JyGT3@%Lk+4F|o&o)C}K7BWcKPs0f7bR#yJEZYQ%tbVSr> zH&7zT*(~t$x=0R}`N4f+C@aZ}&prDQ`hp7+;+PmUtxR^|aDVF6g}`VvAxCR9u@>Kw zxPG8|eko3%l5}V@igAmmPh|x<;yAsccX|QKT_3qKKwinA;hu%HkHt&zDK0q*6=LIA zBwk;H$~u|F!7Cu9Rvq8%7#ji|>6}DCmftCW*;%`Xj;FBe!BJuTJA3E@C>ZE!+FoJ8 z&osliE`pKbxQsD|yhL(FW7|LSR}4%)fCzm~4NUmq!Hm%ER95Z#BXZCf*napa1&9T{ z{neFX<$qMdF5&l{LiH8q`BL!9D9?bPtx_{KBAg+Bn@gJuX3rr+2dK-R`H}le(&2!v z*hRh`|CclC1!*ok7fu77$@GI>l$fk21_(L)E4)7ZKgtlmp#2Mj;9seW2|v>+(EB(| z>!Mnq`YYnxLI`mB1kZwVpK$%Z=EEO2clcLWqwPZeqW=Pv+8$^jeyIp#ya_V-`gg~3 zBKyTsuG3gb>n{+Q8Ny!{)lTJJ|B*Ak8=HemUB32)p{r`iJIH z_3ifi1;+y=<{?brf_3cmxM@K@FsQF z{UwA1OnLO#6Z;5ZjC3+dDW0|+6|av(yv5W4>40BQ&otZT+sVmd_Q9cs4+0=gTVU^V zmIU%ZmnNVq$F+JE-y#{jqzfVlbllJ3{_Tei#iwOJLZk zK!m`6Zx@4OF-(bv0#u`6++fi}%KsHj5ny8T+$`NITIPT>Ctx@L8|gn}v?ndovp~Sz z133hx@4Vo@2u=KJ(Ga6Qi#`AaiKf!Oi-wXjYW~$n3ZT*LHh(ml0;JlC!mOEd!a_-n zl8`GVu>S@kxRAf*`XdmxjlcQ;7Zh{;xJ=B^2|zOLEE^4uCpe3-ECBstF>%re@Puj` zmeRl67`r4mt+eza{lx{O0*kmm_j1kCm)K}Vm`QeF0H?oOHG%)nPO6Ih%b!5r;K=Jz zH)x)UVQpUOKg?Wv!x{OcFclvh2?NP61_3q9JGfqu=Do=v-&KJ11tUT<;Lroh^fmD> zL|m0v#1k4i8Gj);VFMpF{84c@N06SL|k9Zl0|v z2M~$>i-)fyC+UpFjqJ=L=sc%BZkoMDf9o^*~z4XC(ex zGg`qhGq#*aIH-qOU{;3(NH~-Ar-?XOJ?4<(3$VSD0blT7_$(LzK=?RnV@|wHaKNtI z#xPI9qnBcEh2D6)+MOCYfJ06s0r&zziWcitsC{3_gr<3~f%uMoU!8~Na!f$*cieV$ zhi^|_zaD)f)cYXi81ZKS2hkVS9msN%;Y{o*Y=_YvaE&ueJn*5kmDdHu13R(OLL3WF z@|i$Kw>~A4nWY8yk%42@k0mu}3A<^S5{YJ+srC47Eh8gJ5*TFliWk>56i=fCL8cVy zb$0r?tS!@d$Q6f0Tw*Pd93zATPU_7YxGasrTLCWAU>3+kx7TcbKZ_uB7AAdvLV!Gf zr}s;}oDxR%m^nqE32BV`2i|JRR8P;^_gneQ2?-KwoduMq899)zO`@Z&z9&RtC4a!5 zn?iGz?%HP7z4Mj8wE)Ki((^a1mLBmzW%a+jIrN~3S)5DcEGB_PgimrNWr{ zW5HLxq6m0fPf*qcBBN9FogMP{RimkzX)WcjgHpa~DH~H9-0WXpa`t^z-M=d!q}a6F z;Sm}+mQI{u!xU+vHB#N~^+I%Jtg&3t7gtlC-zVkz4zcOb%9j@-a&Pq0+0UjsUww zpOj_i&nwNg<=(3m&teE(kvEP0MiV?DN(f;saG>_)8Q4FJ=QGNmw&&I*_A9QsFJs3q z6*)QZUd#8ZiStjbi0X=Tlbodv_g9)hcI^Qv+X3(2a8)y94v#slcIS-{yu!{IZ%kAG z#2*&QWskf_MkEIuERu=(7B3?A(@lo})*r{;iGi7I2}6}dW9*L!B7sBa&}|gf^NM+H zy+iHv^O>_mwSHRr%1`g=X_;pGZ2*lpUeBwCg!*RQ>d&*f51yCYHOqBPzvBj_i64Eh zm>)@h{h0s9^nBLpPENZQ0r*CT(_m|~PH$)hVvFZ%qY0=Kx?Um2364-6>TIcRskt1! z92!QKfPTuC$G>V17=GQ-xL#1FB;c&O_4vhnv^f`2<24wr=xuFchPs%c$|q%2hKGSH zLVnXyq(M<9M)Pv=#Mggh(n#^{x9M&*yHN0Q>Ve@d@BUAC7{`YhD#IteYVTv{YS)=0 zU%x}fEnE(+e2JI8-Sd!%`sh0!fJR77^%4y4QXd_{!`5FzWZEh4QBTW{y^UoRmV@i} zhfJ=oE{o2&-0xfT*&s|vBT6XQ8=ib9o1rAiWh&g6dBcupl70TfL^PWIgkhdE3X8 zT-q`rEzi}_Yu43|pFLci#JoYt>sHB^_HNfXzhtycx5?XGyIQ}$t~H@*nEJ}--AW(^ zuEwju1VE`FcB((t4T{NSHL`@e!D%!7Z|`{5tphz9fE_tC+BsMY^J5dV*zzhW|s zp#1MoWd0TT{{KR>4wXD6+LZo7uQa&t*?(_+__ryl(8YhcAPQX+m0=gbG)nsq%~B=U zF}=|KZ=0q5yY=Glrir4`QljjbfB$o{)Mz6uml0{Ix;cYATF>Uf2UOehq&pK>lJ$aK zk|ZDNSw)*woZpO^zRHQ=)gGqr3>x>-Iah9dmS+p?v9o$J69S0LjCz#`)4@bt7_pM{hLsEZ%*UZR?xZbjS{UHndaWG_ts| z!^WocYD-gXlKUI470r#pTNY`}oeR0ap2c+q{E?3BDF-d?)ej>l+!Ae+e_Hssn#($m z6!i<+cly4`uX^h!=X`s((QV#ovwk#*tLeH*F;h<3`KXYFHfQ}R18Z~lAG;b089pBx z);RfzbkE7kc%8dcF7dUOf$nv`S_W?AftSx1Q?s9@g&YZX`!t@_S20!$gTH^=ao-JrqKKs>AT9#GdpstLJAD@ognfJ%O@1>2? z&PHB0hJ2DQ_7i`F=t2iRuy9%`e30ayKNW7!;9FWlcwE||rTn=)K_Z{+ZTju^AqUgs z0@U{1#5vC68wTeEv?odZRi*uS1t{~Kx<${YwJ21NF(cI4xHFmbpEVS}+pzHKJ-6G@ z?b;~tKsNoS;$Tb^vEO@j`!B0bo2{c>_s7LuO=LL8SK6J%y{>pUOG@RzUa8`1WY=a)Ygk_#(Awvowe2ghKh+dNonsPX@E$4zk@d^0#zql5grfnz76h zC%mdsspXRxZlB>x9KUw4Lgebqq~YCo!j;z$-gNPxsp0oJH69ttEIV1^g4dS9r>Cno6VhE_y-I*q4*GT*I$%p(FV+y9BItJhRBu66AG-Zo`;c-x4u!z;o{ns3 z+iYs|A7`j@PUEw_y2?~l5nBH7JEI6Ts?@hhu_q5*Ug^3bUVnLsOGkH^*UomL>?WDl zrBGkOdiiV8v-6XjR#tVR2N6Sc+2yKtvka4&&lx3U>?Emt&!|4=7qXtdAMV6oEpanR zQ~9ua<1J%-1iM}Y89sfx@1`V}A7s@g>EAiu5 ztkL`j9JUD8MW6CL>PhZ`Z*67*B3Ksn%iU2~=kGy^kB7dogqzk92~W+R8T4#ktCxAL ze7}j4A%Zxk!7V1ln3|nLfXFxL{PQWU-T9855mtj6ab8*%6Q5IZ>bIwM_C3b%_~<}_4<(B;NF|>Gn_(M5s;95*GjV#sXku6n=F*=xjKZ zGPTl-#iF(=<>do|;nN6vFvkITEeKqia(W=cu=tsU!LN39)YV70LTKu8t~CDiouzbP-+mg8`H9>iMsB=Ir{vvY^?F1dPT`-X%SgUSdYS6> z2UqJ+FIWGTvW(YeOVXxPhGzVGDfH7ZoI$dh*m0UAR4yJgR|mu2a|Ko8zP5%otSOnQ zm#@@iZKsvRoSl}#5&N!puw|oZTEn@M`t+X1x}cx{`wW86Tq6f+8z1X0yPA{8Y2f&}J|b0Fop?hiHyhzk+_r3**5%{K zI=hJH&)`Cp6Dg+eQjilETzI-s);dijx02lS(Qw&Wf2Q`0fvOfLx;c<73TbN0W)>3@ zTBO(#b@VFDP^&Ypuo>B~F&LAY=(c5QE^OLNpkZ--9ZNub4S`zHeVn+s8A&cykcD14 ztn;((4Z$N-!6A|pnR!r=VJ$jvn90&X)QM?uXSWyi zKv~-?=(n)>=B2$c=R< zogI<%U2$O~Dp0at#8@!h;zc~2Z*)UIe&O74Iedg;nb1v7!juBb% zq%uDj#&w%ZR*y@aEbd!tC5m)N`{43HTws=N<9%?=4I1Vv0)1|`4HEdL2+oM#x4r&A zhl^s2lZGOjD%i5-_8wQTlh%i!bGCOKrpt4?chn9%K0mFizQ}i&)D%MCz=CIPNm3Ad zgSzGLXSXGJgG>sp!^%}E?K*1C6X$+Wq4Pn;sSIArTbD3`Qe~b0J)2SZ(T)Ox&L)guVD` z+!@YHITe-zf&Q=$kwrFAH2=^n#I@_@+fqj$WGKiwCq<+;27R*t3b^vCux zU%x!-zG&3S`=sPD%}b9?QKGRY)HKbqfx6nI8ft4PXXYo=g&g=pmLvmobz84p<N3+-?FTJqg} zmZonV9)IN@zc9&s?r}$Z>(*jUUL%)6jopb|m3P?cIOX*BT2rMSO~sND1!kw^SIRjD z@k;#Td-e4E$J*}~iV5C;m@B0NB2-{2Hd(l{>zrFFZ0e4yShb*dFzxdA4< zz;?kSeg%oKe3g~eVQMmUq{JNMZy9fq5Oj?3;ce$l&?ZIxs zE`+>rkzGj7+Q)JzIZO*B2!_)?E{(Fhk7lc<%4FPfRmUgaJ^)f+pAl5^=Ftu4Acmrp!U$mGOLAoCaE-^{~RAIa!MJ7%$^ zn=$XTi%$d^Wiu0+Gvrt|8-L$A?#aDh>Ps3Z8^M}S|2Zf799e#Y`Eum4^{s(=E;*md z^tXoP2-YLHb}9+}2vfBS@(%M?UWN1d-?3v?&UP*Bs!TZ9Ye14eBNC|+jU?Wgcu_p4 zvctcgm$Us=&|D^TJf0{2_~n=@Q3{Xor6B46{L=P%-t(N_{1x+wfA)zY-`-JWSet2R z|2Dv{Rs2#Jd|5g`Y%p4sYGh}afvYEVn|`fZ*zmfE0Gs*TsC+nuXL^|}of6JC%hURy zvEFa=wx?9a^V_|6A+Uc^&5iKW}N&`RM6Do*lJSlXM+ak7qRXI|EW#r)JPUljn|S9kKB${qA?$PiYcLQ_+-V z;##Pk8P4V_GJ{%5xYrArQwdaL2B)VijReeM3;g7gL|jMA74|;%8GekCGx>Zxlbt`a zJDIByIbmX)@&td!V;@JK(21k?@Y~smGv1k>h%-ujE?)Qk&S{l0p4J@yQ1J!Ztpey! zVeKpL!`F#XK}7xQ`C+S73#f%LJ1uHfpS$OVXz|C&>1PzYL&`?t*+dK{bff43tg+`p zx_3UBULz@r&Q}{3EPPDJE@0eu}&%SMWD z_L*Lq7UiExSLd$!p;tDr!GA7GyyNhbR{3llnc#SL2XDs{q49f64`vAYv^bh1za<@i zmTs1jNymM+jS$|x*O*I+$QOL{mY_{pn3I8!^85IzSXt;%TNycX&qi*eeCv+w!Q445T6xPDoXow6$WYZjf@g_^4aL+?!IeoRd+OPpI-pf{PGzdwXiTXysy zH|*^X$_vRC-s*N95FqXwA1Ho2>dqiM8s5&jNV_~n*S+V`r5)(y)?rY16*@1L5^5CI z>*wYud3!RV!t9WYlc(Bcr(JrP+2TfN)z5X;O}bUDzM=o_3S@-;Wgh>dE5I1gYs5nT zas@K5DJB-uwzjgjRB`cPH-UjjiiomH$%x({7D8IOTRVHOOT(7;+P_S(G(7K*DZc0e zUXhpoulD~R+y1|^|B8wL{{Lw6#s9U?Z<{Y8_1omL|Ic-%fa_W=!_pLRok;_$LQ^w~ zYx(A>famqJ)lR{CN%(l@K8avm+Ir}5^W=bB=6PY&2i7o-xh9v4{o=QGcV$e3=(QZX zOPg#e^9Hk?UvF>sdt*-*iyPDS@J-ZX7n8FsPdIHa#I*4X$%wcMx4)#bX4y@XcdDy7 z=-dnWRF*4oXJ!6o;-`cGJih};4dFr=%4Mw&!K9b;DFrfcOjen1JkHi>6f0RWJ9BmV z0KGa+@M%R_Tz>&;Cd=vcMSWBfd*o^BtW%ac3&cik?EcriVn67lsFt*Ao=HVJZ`0sj znEPPq+b(nQPAKm!x(oP4(XI$l&58-yGHiq0``L+3DFqKh9^F0R)nMX!w-SXf$0DB+ zO0O+^c!sg|`WZihxu`Pbu9s{HGn4L;`a8-UD_?QDI3JwRqt8$wW{IP5csT_eR1ggjW?S} z=H++LS1#6@zFOvHEe+K5&j!YF6IsT1Ja=zWKE{f54$#8em0<8d4b1l*DlVL^i9^zf zovpn_?aFcNz2YW#93f^OmXSFl#=lOjdzH^X|TRRXeAJ$x~s7bfJzaG_T zHmIY_mOk~__2+g`qm$I)adTVQqp|$O^vbhURaR7kcP(?7EESUNs+hyvriD+(&X<{6 z`NkyqQfA;cckM%03Je~;5`R(oD&a+1_{=6D*S*5q@o7Pe`hliXGr=4IDjRfbT zJPFuWmLY3?`DDD1$i_aU``+5qYryXDz1~Ci3Mzs z3L`g@4;r=GOD^%}2_`(AgDy>RMA4*uzqED#eDUan9KZjkCo9*qqd!cJ?{?44X6~}t z_}BLf$ujKU(+;-YmMwfp3N>eb#ZS^SJFU^mc4W${mY!7b0N>fR_XD2ZAuV#GN$OLR zQYXJq|JoDN_fF4$v?5-y9i23$`_o#S_m_AcT?+ADXX6o$b-6k>7o=iqq&XmX5xXN= zXRv68RfRv|Dx1Z#3*B?itoS+xB~GE;z2Cn*z)O&IJNF;#-M>rV|JmNb#^b-(I~h#q z`G0TkF!TPqz5CCh@4qYW|Af2$XXftT;rySnx|E32|7nO@XrvW8Qbk#JU~t*l!J^vW zR0S)Rd+{x%>Wh!?9=%*F=ooFv&W8 zHvD1putnHTjaG-o>gO|lLtODs+*(3c#2qH?5BCjTJsWF|KOnk|_oUi>Vr;0q*6DIr zX`t^(aNGN)2#3z#`J6yok$R4mX;t}{69M`c(zoO(Ektdz!PrIIJ@m^0?RJ z%T_3Z+0Wo0EZ{W#bgJsB7m+e?;PYD?LbqwxWTnPm zek7jPp~CBDb&ko!_>1mS=$pZ1-kka~1@kgNVlw26bj#|~)~WqbQvMldsP5svnzrZM zew1@1mnbw)_UtluF1P-z3t9`llIJXh9BQvltNLC(W;*Tj{4PI&(gmNy&qm(+y)CYF zVC!QKd)(_$>{tTR%#yOzuV=lgf*6Rfn(mo@!Cic8n2E$1wf&6EaH^UT+ai<_HQeJ> zc95OUzxvg2(4hu>c9x;3+C}JoQ(zu}>OcoP;P_`GL;Q40#|-*k#$1O4rzFh-2M6CxUg6 zoXn|y6ta6f&8+BoVWL>^fr;4p_&1hl_#-9zbUA{FNLehg);!~QOyL$8F& zbdtovJJQRLbw&sE($TBG0J+a^CE85ILZ(1gW^=W36cK)al^8YD8p%GQXTK&TJjW`F zm~#kwS5NglbPT(#q=UqJfcV5oFz<^dPjT$0e(@}sC7KKO4t>N?V+2fD6eB-1shl7E z-1#tGZQC*?D&A1{)4h~OuAT9mytb#)_cAwBEnoQMGaDBN_jYP)9J@$4A5t*B#|{wN zl={%i)8YRKH$kq#=IyN)$PsmCx@!l-jWYvh^&FC-OadrVxF&UYa!vsy#U3 z5ICk1BonsXX_Rh~%W(TdPs297SNFg!tW7UlWA+7>^hEWu+W9PTD7*Kf))bsLX&_rTVdx|eK(Wsk8v?UEVANODDG zW7>^|k<$b2`79Y^9Zdx!3Tq}{Ssdk6Day&5eLC^e8>;5=9>dSKIcr0> zIRif1dY2g6d=3cq`~1}1_R@n_7Iq7|dEFQ3P*@kJa?hc{`ZZg*m~X!eEn<$b%cWLa z=TX+^_0J3FH>oT5#4fi{vc#p|UBbqUxLsYaYvpJuUed*|&7^vsJ$Z%r_8|p+y`pg9 zuqDI3oTtRSGrl*@sGhORHdMZx>`tYb*_SqWW?gnbrgo_X>G3h{J&mTc=C148z+%#B zM3qwBBZ4NEjy1BvZ$5J9mZ1k?^!}o4$OaYCUD{Pn9foe{=6A{ux_KiK^RHoF|71RX z=9|*-%(C3d_~pLF6kIJ{Xu{>kw=8jutt?S4>yCtqp%`~ELmthtk(68Kx}QpAG^8W6 z=nSEJD&nf_g2b%D+ue!l)~XT#Ec8wr^(qM8* zIY%ccVT%>J($|ewuY2V9yGN7$&bs@Zi#%_aBY;N-WI;> zSnl++;0L4hrlZNz6DQnA%hZbp)ip^5=VbmDdv6(5Wz#JHqlAD+NJ~o!((E9l1wka0 z?rv!i5D*Y40TJo$?gnWDq+97uX^@8R-h2Bz5AQkeIoJE0AK$Of>)ONIGi%n&>a~X3 z%^pGhkvnVW+(K@I#X7FXV5(b<$yEj(7Sf~&MoHwg*aKNEp=&*h^Cz#*1IA+#U0i_g zBaG0R{cjTZoA=58K7og&!~dGV!>^kE4+%VM-G7|G|9vlg^VJ#P9^>!3>;Ej7 z|MQLvrUsaklZ{gg#sT06n7n^3PcSujctC96zsET_{@mbTYCyTbY&e+8ZN00ERzv@KJ6MfS(%CBF4FR!E6v}ULGDc9%?WMfJUsofdjh3}J&(gTNgBa%xyj1*1y?!VLxv2XAkj{ZE+&P|L{;oEp)B zxH;Llfj5r;GO4+ELBKL@5Dzem=p$zT7y)s?MqtojPS|P? zV40kN62Vmj!U?lHU?sqKz+S+B#qt8Uz<@x2!vj_b*eNeeIl+KG0Qe7uwFnH{a7Kf9 zxq!8t9B`5R+aCyf`#)J7Kp)J8|9g8AC&I!JFgN>vIDykc0Ny~Up>WlLfFJ-iC_pnX z4uQhxguqS@1w;&}4A6%He1g#of^xvddBK3faskwHasVz07y$GfKmf=aU^HBsP;MCO z0VRZu@E`;L1r|U6{Rad9Zvm$Z-vw9zC>ST~JP6qpME_se$HNUc12D`b@Bn@b zCU4j#AYc=iOt=7CAV8h~4DeMffPCO`=LW+)E1(|$4S=F?0fr7!UtT~Hfa3s?2gZSY zVcwPpMlA%69|G4Wz~TVM0JsO3rhs630c&}vA#l-xcmadHp^|?BD=fgkQ2>YF1*{nY zJ17tUV8=yxK^W061q0B*JrB$RVK4w$aA*(&2ob>b69^CsVhlzk2Tbg6(Sf;O90nsS z4G;zlGZ;P#gNJg#{0wY8H*idVM7WCwIL-mc>|Yu#2rRH5S`aYv|K@XZEd-7Sw)&qQ z2=L!94+o3^aRBggoN$K(S1Sk*C1AP%^OGB7Z?EpN(cBx zxQRnKU_yei9ws)}?@C~E5J072#tjoJ2yl9U(E6-8<0341t5MQ;J`pg zg~DV30nQ4y1Rl6U1_3kx&I(XimM0RdN7z@TcL*OO}3xI&f0$drO06<&-JSAKKU{L^oN8kYiDh{X#5V*Mj4FEvk`U3$x z0T5~cI|i~FxTZmYxCbnPyDS(2z;OZg4d@NvzJQztir5O~Wx;^1a07>hS<+2X|4kpx zECdmMyb*vI(77A!U);ZG1^?;`5bFWB8@l&*b`9bJOzQvt{C~-V8)Epom;nL)5a#({ zS^@>KN+9yWGe>S9A_IN}QL-TN>i?nr<9oq?i2#`=kOlyr2NtbiEh6iKr8qE6gn3^W z1Q(*ff$snU{5s(0fUpP{1Q6eVgy>HnzCRp>hXa;>B3cAS1fD-<1X2(vHKPBg0{9(7F?0jPc7R7*c;|5><>cd>$ zP0A3|0O=1b1^Oc;SPud7&)Cg1uu+8M5EA;MIX8F>gW%zUr%P~&{m~w{R>0=Kh|~*S zaPYwS0hj4NYRUO`DUArfH+?P?$jgC55#A!)3^&5%{hP!CmNp<<)eRs0cap&iFJ3q~ z0B!;NyAcBa@m`2+V2csGn@~6X9UT1)4BR)42b=p(KR2@>L?5vu4-nCT7!Pj|Bk+s} z;4aLM!}S8rO+=paN9z#rA7H_stl$QnKxClig+~oI9{9--YyV(J)Q)ib{DU8!fx%Kg zM9lj0h;Z%yFzmnf{&_~o@Q*a$h!Oo8(u0p8R{R--?}ZroBMLYSoSlds9D*BO(Q+dk z7Cch_(HO*8;S55=T0{%q`G&gveL=$w%ia-9TK0w}=r4P^5r)xq(p#yr6^t@g0cffOh~A0&YNK5m6j~;)a(a zKu!pZ!E!;EPyjCuzyE+?LEuBI{DT|FApkGL^EYl76z~C(A;4w-d4Sa=!2QnO1pjOA zpC=d^9-vr*6&HW?xOm|SFPu5BQ8=;iF%Y13uwnsldYp(OAlM0mLd^Xo1b9LW7scOm zH)Qtry%kKC;ra}(d3fP1H<0syfNUC8aKZc&kYfA~Ev!BOW??o86l}1l1A~SFnIK{X z;2vPP8z(1#3o-r|Zdm>g0^Y4c?1+Fy^kJ(JP=Bg6L^TFK!9R1{e?$FGXZz2`|D5R$ z)v%MnDFCV=Kq&AQ_Kctv0*C?74g{URnEZrdo0e0a7E9BvI2`5lF02D&uLI6Wx zl>|^o!>V2c04!TYC?X6wJbwjBFCZ<2g*PDB0|6ay^}u1^Oa|`U0HMRXh!zZF8-H;M zwhw{|1l2bwf)(blNQsaW{3jy9-HxSdj-S z!65LfETGt&`sPaj}7KrCd zxV}C77R{XLS;Q!bcn|rD9(oFjDH2tZm^ZidF;gcV_aGS?gC&fOm7$oJjusI9gX{0} zOgz0>ngtXTF4smhEBe?D=V1ZJ(}GxpGoFdwe&~4klV@DMq6i8?_<;6$1x7Hlkd_Lmw`dfHkYak+q%Zv zw@-dhBs0+B$lGx_pM;iNcw(*H@+7>|)Y7?MRoAF|J>NMo-`_5*q$KIanCw$k;X~il zGSNq#O!ugNZDm;k2Z=BGQV+e{-tj^e=MYJK^41GMtSc-E^e_U2TS!7&7c4?5O2ih7 z5ETg(i#j1Y!?V_2$ryU_o;LEWtzL>L&G{>Txv7cvsl&AG85vKC!UCVPET0|Eu9k`B zo`q1Jo~eXr9`gKz>0YC@>(W!)=1bZ#9%p154sLFHTRY^Qgj*}xnaVPrmdV>&hF4kP z%Q$G!zFiZ1xl#o+W>0L7E-^m_c<)8*9D>iU}O zQ+i#(bdu}FHOa;G+PmLlPBWfr?uTV{lO2{!P!AdZ)@#rx*LA;e5Z^@1rA|UH*{*@8 zIQiqPE4H+Xy!48wnwZjxxSUbX*tN#2-TA4$iDu28gQI7mckeVcwe(zgI#6+&n4jC` zRC~maCNUp`ema|Fr6-r6=)H=5G8Sror?wjD>%3sdl@AoD;W3q%x$*Xq$!p|j5(@HZ z!AK;*@Pj+5(AuU;+the+B!*8y;@32?NT1h)+E8`xpMR*nC9`mii{mA=@OnWXnWO7M zj7odyIt7Ov^LpR|al7YQYtYba+vWVzEh_yx968rwRDvL2I!PUvmfLC!SQWc-@j=jm z;d-FMBhwTAyaSsmD(X^b%rhS8^UuaG)F#6#Na@?QV+CpcFWI*` zFuOhHJN%TdTS6zUCr@Z?COzjRmz;pdf$NH$jwx>5i@QR%9WRJI+U5`C5~(U>sm2?9 z5^CO03Moc5reDVlG`3T{cRGuH-r@P>-7>9p6tI4(5Li!W4KzGc*YBy!TmT$HyB8{7 z1w{|e08C4lj8}4><7(^N+tz=tf(|)vT`vnYTJ`jP?Rhajrb7PWRMaX~)Qyr%eD?_{ zwh0Q+BkT&`PX@b>Yq?G*eM(j`+prgW>s&)Dl|Ul?b1Evi0sl(kV&%N74E4-jrBwPj zXf{tFb>l)0GBrUywr1HS_h|)BRP{ER<2-F6#6+l9S7TRpz(XzYwu!Sf-SWdj$$q^@ zMJu0jKj!Ry5&M$nD$9E^o{Q?I`jO;vZl69-^z)Pvxgrw;O_W5voP~WUqwf4^`NhxK zw$cCxn=6wN%Z!Fv{(M`xZb1#uMt&i3^-^^$)OXI=ROuk1A(hdr^haI;p%LdSs`5eg z!^Muq_t=cA-DV5nXiSUMzRFzahIhJ-(>~)Yxy2gS{Q%yTWxman;~%Hz-pa(B{y2QI zlYu$d4kI5qX{Hl>G#q%zdCj#E_g=h~>EZAhef#2WX&Yt#5B%x7$va2OXf_RkBAl;~ zS2LDqlvsr;yBZ!b>#@q@5uQEImaYC)8F8}l@q*3pv72u3t*X;sDl5iCjlKL>JMA9} z1P=65r|iPr-&`qAB!i*FA-Y(cGed;_05q&n!PoUHPAsjq5BD2 z++M;P($<+T!pJffvdceZ&Vzk*J;c$?_E@WS>ZMJ^mTzwbUruR))cJ^JbU6b#haU}? zTE_}AF`jsxKMWn;yYspZEzvE&rL-{dZ6?hywAj)1fXU|l6N=2y?Z~$RW~7?~FA{~k z!c|#V^1mrjb{Yg^VjZ;qG*_W#vdBcTX!@3BoyhQOsHtL5?aQH6p~vIkU!dj-eXrst zN9*?#RoLX!&X@ZSXh*oB=(+A;rnj|W4&Y2j6t?2u32iHGN7!(NZ)$gW^pR5b{ zFy)G8TU67)FOzxkCD5L{(KtM~Q<`LE9UrIo&V*@P;QmX+`UJ^9nX3e0}E2*B&xE@&i~O|U@b&GCRKyx zNxwNq{ntlIs?yU2i*{3|-!B@r&`?yk&Fs5M9hmd6)yLED+uqmcI&vq{E6mAC@qEuJ ze(h?j)Fi&o)6EdMt#a4U^z!pd(-o>>%~f&XQ8lrb8~G}4EXiJ$7Sa7qoXnp#oW|DC za_YKF_3Y0}OXwEMq9f}$RknyCyY?`q(u|vl~ zIjuyB{Ce;M+sXii3rCd(k0MOT>kucElfe%kbL)fc*uIoKJ`4oC#b?e_;Kd`fFyw5`XAR9=uKBeOY0gc8_n<{Cl)YOg+r&10X`{W>eROHezQ!$rin$zE zyl?q31Ji@Qzf87VFc;Ype_=m-d38HwN0el(<5RBuOtZ+uML=Z{WlhrVugOQAVm&gs zE}AmjZ>ugozQ3m>z3|ge=k>M9zb!jtxtKkjjzhY<`N4P1$jD;W+h81>pU6P zL+!-fUr6~K01GR!l>?j8hkt)tL8*&FZ z>QNiAd%1Tt$F(O#HSHTl+N7VTn&DMj3s?TI<_`Rxt`WC&2Bgn<< zmC)l;<1_rYFpKc_&s_~rRMIzn%o{G;-_+($6+6$x=y$mrpIq3e?s}``d%aa?w|Z`n#Ks${38)Aqe` zkTb0S+wKni2QqIG%*Xf(`{6{no)H|13TSfeY4IN@da}-)>CQKN-g0m?y^Hgc7dSqw z3uyk~N_qJDs@v?Id3S4FMV8gZeFOTj!?nJu`|mz_vg2l~DW_{fu30#%rmIS;Fq9TpYeEb0S0K z^)}KU6w9;In%Kdum(SnGub2951!~OwIBxqk@}1|)st0#+8E5q@d9UKpJ}LG9gl5;vY|AyPfSjiqEVE)|e)fTrUH+M*_BHw9Oz6-b`ZZnNRGJ_Ay;oN6@}w0( zG?yMfDeufsp|pw3*{#bh+frEGUNHYkf4|%>)GN@`g69s&?+@VBC1y4PJalJ>YD&V= zgYnG(X^-v6%&08Y(sAm}bzYIzcp#jO6#CcHPBw=VMxT+Br|!*|h99pJuD=a@IU!_%Om3$BzG{EmY2GHc6~(L ztP}8w6)$UttFYaB*T`0|i!;Lko1)Fllin^t!hv~1x>4>V&S*C@T1}0{&C9p! zz*TyU6;e0<{bGsI?z-N^gY4Gsmk)RK8q*DQ`>LE$1;`52qte?uqnnrGrdQU}8KYi6}thThM z&Su|}po4+^g21G%?A{t*TF&;OHOo6QaWY)IAHUKl2G1}0($%d~&)nZXBn%BhD{5~K z6Mx}+LIlN6oSE?$B6;7CHUHq2>V?y#Qj_z03(-z2l&}Wsk-Os`NBb%$4AV{%=c8hb zM7mAv*igF8=mvR!ng`WDKtDYN8LSc z`Ob+cH;BKLbBl(kTD?Ls$o#lEgQ;UmxyZLoA+vO{_I3VsxamT~ep2Q|aO5m0qd8`{ zfL9j3`G<9P%?AWZmF{!r`{=2u--xX%>930K`+Vpu5IMse%JokhP7jaCTAg6JmvjmK zYQjE^jQvW!AlK^r$q!Hp@pDXJPS4~nGsoT~I~|pD6ztNJj&}{oY@78D3hBAxSqhcT zO>oaz*%`TK=*-nr3~oOs65T@;ej@h$J$mlm?Myp|=ARZw#KZ+rflR~R+U}Fj@NJfF z;qhk5pbjyXjXH?iDiNgq7MdWbUcoKiA1PI3pKUQKlB84oMxGFGaz-0jXA%=4zgP>E zJ7UINQcz}-C+BaNtIDIjnDEVc91$#IcAsEPq(*zO!93`pTxU0gKRA=lfFaS@UB=da z+(PYTOrq{i>xdeju*A9bECPFc)Ad&sXz~7u z1S5zh5Zj`$Xi(1DgW8n?N0s41?nD#wwjA$W%^!vM_Sgk3Nh|UbD|rHHKdTg!ThV%= zW!Tz~4^20cl39Ot-~A~&Q<=^r5*<$?O7}$AWX@IfT?>iid_pK5n!&mJR);5_`cmZI4gtf_L~`J>A{- zPn#>|u~gqtf0f0iOj7|4WcI8-(f&uN=B@ zrkinO<{T5q`z_f#soCfESPlavd3*(B6l6+%s*^k_r+Tc^r3t9=7szNQo5Sz)*3r+& zR!|t{^)Wx*OHup@p=Qt}@i$#tyCkwumH#T-<#YAq$v*aqOMYx>c2d%;eUWIBGLsRS z`{J}jwZzZRrr(q-VP94EFCR~hCMlm=nZ79O$rL#FHqr&WU-3E4Q`kjl{yCb4M#+m+ z8jI~!If9&I0nI>el_kMj7=AuFsZA(b%O92qkKa(%(|UqEo9_wv+`5INVwP+i0Ma&V zBYmH#BCPDdU#Y+9{H)bFPk{z!S~4i5fHtdl764_S{_QjwJ(m!ihoyH0W% ze#o)!7xA%?3`J$d zRYscrT$-RrdR#BJMB_zvVZ&YN1WB=}-^?^7rj;UtT*7CYTCA}O*6GYiL!sTLWvitl zWZUY$?I}+~jF;;5^=2pP5-x9NapyJ2xXj7A%8WB~I$Wz^nE7&qeKaO1M5288X;VBh zFNQ?lEb4vUzRlCZ_7BS5IIHKwOFY=QCA9BZ@Xma5ap_TsDvybO`7>J;IH2|(p?Q{k zUuRrcFRF>WWc)%DakzM9!4d`Gzc`a=H4!0Wop>5uAsR0gQbsIRrzo*ADS}$W@>`|L z_xR(qNuU$mNYG}DSyV3j^M&pwZ_u!kM5wSMUOzU??i0}dnP!~V_^i_$t#57ba58HD z-P8CQI_es)Pi?VDFOv2uTu9k8eJz>&3}uY2vZc!BhnV^4yREgKd8_-%swG$^l5E}| zjY!3wDiLfN;}3f@et({L8~U@K$aJorI9Kvo55xO`SV*?uqgSW+1su_8gRc@7ttkvw zBvS?UKDrTzku$9ZW_;@4CW*iJWRN5Nw!>7x3+qJ?IY!*?qhJ&E2Lk@}-&<*7cUq&c zsz?tABre>B72cvn+kJBX6wLmT+7h!9f6YVV#ks}`{TJD)kA=}|ep7ajN!e%0BV`^% zwGz%&o67=!lJsJX#1*{wD6{poI;CAkarGiuh4#cmnxQUNh@R%)t}XI$Ty}TeE@5e= zTRpymx%ef`wET$IAwHw-sWbXenXL-)_rtS~PkhKH;|@eBh)$pHlv$-Y$8{8u=H^*l zM4fx-C?#}ru*qzV>J*o;rZif*;%~q1CLA_kz~a-l$(EuG?^>oc*i?9!KQ>1`9UDST zFeiGou-FgYq?33@Vt&>DVJ?+D@(JGnwcOjHzZtZ)$5{Y{5T z*6wE1H_TKknYWnY*oKMdXzJVZq7(VCpS8`Ngz+og67qeTxU5^|`*;zJh5$dIRc@H( zhe&L-f~nu)=<_T+Nf{Befl6ksm!o_p%M4j>JSR$tXLT)eo6}E=4odd2tm0)WfqVdY zga@nHICYUC!CFDxLnF)%JxIKjh(aq4Y7p=J0C(!xtYE;LxgGz}NbOsV6qUMC9&b)A zQ&wH{Vu-Fl8k3%!Tl+XLmy&sixNZWCSg-K7HU^~oo29(J#RejI`o4&GPx=O%a z6q%-;X&bRSe=(E(0JJN4nEP{Pxz?O@*6(Fy7_Pk2GbM^Q$J3L$hH1Z@>x@d?HpxcX zerB`i>Dt!x)!|u+-+AYsZ&n+)VSwRX=0kb}-j@h*UMc$RCb?&3aKx-u;^N;+w%#w8 z+tfQ*@>FzrJhN(HlptbsxKpZVkeqXV`#9PVHH*~a>xt@$T1p_~fK!k|>u7k=rM6i5 z)z^oUlHH$v?*Eu2iKaRD@kqF{*kg#*weJr|`HOHI8RWXg3&#;3c<~#hHa4~w#5a8_=thl zF-ni!9A0f}nIJa}vSS=^!%B**auw^BwkBswgM!~XSPh?mQGF-1RI>G|2pJB4=CV_4 zpu2YvOR-yZ>bpljLR(n)xZR_nJJ62aP0w89dRtIr=X1vQ_vLo_5Bj7kQK=u%oEw&r zh;~#a+}ri%!7LtMWmiPW6~AYo&gI{hp3A4HvaG%{9e0;HD2pZSo)9fN_i@a+uSsmw zXcfU|hp%;sfi#%S``vWusP@dQgsJMqZP|jS9{yUQ@e>lLW18{)YgE!d`{pSzs4i-p{8hcF_P}ACyx&&aN>JaO0{2b zSUc+tK^)^hzFbUr=!1*nfr}eiN6c&3D`~;b-+BH{KFIKq9FtX1d7^^WD_!q44zd`nt_CkN^`rUaUWpa7kOdt%B=ylm((%TmZabZ;ln<)9 zgO}NI!HowGOFSx}z~nn6*h6)H~X{a#5u znL?<5<@-psWjEv0L1JpW;N5y7btMxzde4iBVy_f14|1*3-JAnQ>;ctepDDFa&-n=d z>0Wj(DvO|kdezg`nYM|5*?fg&Ux!vxV*#i0*stES$nPH1l-F;13EG(Entj3`zcuU? zl{14iF-&qu<3>5@Hh%J=l#T~7-wkR&Z|atNfX`K;fcJ#Q3mfN3iko37ieS;=!g`hK zW7wIZ1GVBlaY1gS1j~a<3(bWpD_4c_swMJO)+I@~u$U1YlzkN5d|_f)HN*9LOxhlp z6sGU8*IVngdD9;vvt0~-uiM=ZlEg8mz!m|%Zr|iS_je2psMr;O~>l@(cfM`euJWk%hqPoe2)t^;r=%KUVSf zW-YO}7g}7nIE6m;cQhy;DethzT1>?FIx#tqk)J%-O~b+Lv-S=ha*RAhcKZf#^B&sz zyoX`Vl&3Tm(y(fH-fEAcOI1B~KXl2Ld=%e+uq}LTh;;#H_3lsmNWnLag3Q+6S<)NY z><13z4fKx|e%kJuyq@&fx(<0^<+Mv5Li{Bl0h_+^*Kz?y8mSg$g^4v97K6rX*YqeU zcX!TY|HMMw zi$!5%Sl3!(lPxk9bY@7e7?di2y?x}DSe|0@ldM%wX{c5RDtT=x+Rt!{y3HCBr4~|g z&e?WO^tIo`Av~4MPh6{jV(sD$ikXQu=sk%93ZbqMwoD`QVar6CL$=!M7r*EXQ%f2) z9B9e)klIOH%$w3Rb=vJ)AHA<>vFUnGAo`4fW-F7`FsxFwsD(XXV2hTr`>t%#__ANf zS%%la$L(=QW`EhxkS2Zg?a7K@^NS1QSE%*3?+!d=&>V+MH76Y=f7aG%<)mG2r_S#Y zCd&=6p`!e1M)Cy%ktaE_$`imJ=N`jQa(Q)Li{qHgcLuwLGq1#8W`!Q@1Q5H`JHn^ zi5JW5yRfm}>%+XMK!dVoDPx|WO(IX9EpdyDYRjPM(-um*)5Ur}ZQritE=jd%3tZBZ zKoTi*UI{$)?=u-2(;Hex{T2LLdBtJ=Lfqh2WXIY-+G*(UMlTulnb?oqat+-kb1`n! zGUJbLFv=qLkgWUT>n6!{%AW`8?K)#`AxG{J+zuC{*x+N)n<;s}Sl_NcX3>?1X;hc` zc4Afdu^sQ>K}g!|+v9#E%e{;-(viY-59_y(s4!+<=5S|I*3mlbsy{f{>>@q(U?~fD z6SHjYAVl!f^?GG)SuC4IPv6nCIy*(+WQY2bF(vla;M2I=-GvzBnQo)FD)t-@sIK9o zeAyNQo)~tWM$8qf+sCV_g5Bk$@IFH!oU#5@{NXoaZ@2J79meUB2h}gM(iKeEi_F}; zEo^)pN=b!-$V!9qByiPZnNV%_y68NsJFY(Ue%YlQc}T$hY+3$cj580v@~2nE4Zf?y zX6m&D^yrO_DIQgp!r)WzZ#f_G`G}w_a3`ht(_wvXB@-T_ApiQk;mK#wLGFW0(aCeO z*w*xv)cO_jDTng~By1ZIZ5P^iSkzXPHEwO$`HW#I6fTtCn~NWjsDwl$b~X;KSPJLP z$!v^ylN&O~$I;WOTW!jf5>jXJ*-r`+8gO0or=HF@M2$1^3I*sB3tF_{kH6s~9sO2F ziI4i$j-QQ|s!C5b;$g}bc}%;HvZ}q&FtLTD+Y31FpFzs!3TCUm zG#l7t4yF=ks8Cp9&>@^)e7wJ}LBgzT)AKz`_~#KaI?fON!QjBv_eX5*tR$JFk8o0Q zW<+l%{79Q||DD3@?7^P0A5gx_iuxp@P9G2C>+hxz6A;<7nN|%W~)!e_Id6-aD{mp)h^^tXEU% zmgicoEP4KUJ5ZCo?EDF@z2nH*y?$@^QENFe&&7;M7yA#CQW!d0MjtmS|Zty zP}&K)*Y+|zrJ#BrlY##MtJYrE<@==`EN60O>^K+&l+Wi?{5u@%GiL1Zxuf0-YMV7adY+u< zY7mqqx;!(kUgUcJm*R&!1soRq8k}b@@$Y>;&9E^_<3q`&$WQROV94H*LQ8J5l2$!N z&gmr`(V>kcpJ{IvFW5uMtu3EyA-xkV$@sSVZcj6l4us;nMF_tL$Gqk=xp%;mV0VVN zBQe1WKW($=1*SXV!J2KYbR`9cn3~@^M-{n60)*Xn?2hdxS8?7oXFOc$p&Tze_!;Om zclVRz`2(&&f&<=NX{$<&UiUSHCqch$#g)g@3_L#P@OG$gq&xIT43=-8zmEIRTst@( zNA^PLN#Dif-2Rtc_SB4es)bv%q zhGM*}2#)V6f za3_&R06ZN@8~?CU@SwaxQSp`u?fdgby?8@vA$Kz9$+&M}^F6Deq$r^w?o?G-f9kY* zFH2&&MkUZY+L|d@BILIp(Osfqr{$gqid+81`_IE!39UWFEUI1ZR4$ic_S+C-W@Qfk zJ||JiDE|JSooix^V&Qa(p5O6;k2$FB93T4j8(To=j)BIKiN1!)C_M-_qldBdEL)e1 zC^eH?J3kDxD3!JWN_=}D*?Xp^Ph}tO>OWg{en*F}HF2^9z3{iyXa^nA^Jm%fHTVbJ zf!4#t5>C9nVM(>c)XAS*f(%z4dJCPtNzU$iU+v%TP~1_KGWD%h*7&^=?_Q>T-eB)D zc5W}ONq5?~v|tmy{pIC}(1Dr4-$k1mEQ&ASBO!zHhbn-~=6Fq_5lQvKwoW$JZxp z@W=@jowMR8gRDVh`zB^vNVMy(>^FAA;SL6r4ZM2Jn6W+j8LFrtzRq{C?4Z;w*CNVW zhcu7g<-U#YxR0kf^_}CKcz&Hgd7{s`FgM8K@bQq|Gr=Y2pdQn?Z&KJi9C#mRm1aRt zgEcrOLW<_U8ZxHu3J8e59(04~L&;L;bdcRcFs$8)j_xrLvmU$aSzsFSP(%rpJhI@f z03Y4itEovL`_en{dbE+Ii_^_x_JMb#*)Qg2MH;<=B#=`C^z#3>hAF?^!LL4>b+%iV!dFO*Xm zN5bSPZ3f*MyJc8*zF;tF`W=^F8zV>X?bDb%C6-8~)9s)AsFWOE*}@*I-+yg%<^ChH zAcA)r#o}XMyQ&z*i4RBM*w<6AoH?oVVKAQn4!e`&oe1K}xCP=u9~t39@*GPKnlVeZ z)`&08)q*Ee4@iey(P%FBjCuAlRP9|q3)p>&B9Ge?_3w%)iY&BF<%hN(=Ovd5d;7?D zH{EtBJh}WWF&$jF9kbFQ6S=14+FTyTK~wIMwj|-M{7Fvg>O_h0jl&3-WoHKB@&I#C zZg9!PRW|YB7@dO+D<^BbP=IUgj-DVkR(fm(=&^ib@_`fvwf$_6exQ-u%9nTiqiIsm z$%tbxaj<;R{C5TQ+6d5Nt_T_~zs4N!*$&%}wg!PN9;~XS?t-xm>(<|&)%+U_NJ$j${nj-MD=vRT=fsL!$_( zp6}vQk5Q(T6_c6dX@^))?7EL1cs6fQW!B^|KYeqY-tmJ%SiBQ3XSu$6K?)CaGess? zK?*27>uhl)j#`YgG8_^19h4XO?1~Gr;pO~mMZqsw1xLTx90YLLus)I_W475yef^B& zm3qPjMwegm`g}ftmCl&=Ro>-Dw;NKKRQkNjlFS>m$?q|YL^2FsC@WuSMV>Vm9 z_3ZjaD*lkx1N>4xONzqT7^=XR!U{v>twZyVTD{$sRr~2x>O@%quPmY=SjQVq~$+1|*SHh9pO=~}scUa?`FBY6kJA-iriE$gJ zo7}VFeWOIR5{WTvU!mqt#mRJ;$Snz8Nj;d$!4B&Y*7JM#YV_%w#+5*(Jvxyx#~?N< z8VTPntj?YaHCETW`$5iA&mW1NtBWQcW-ExeA(Pb@uASHi)Ut57NA+45WD)AAnt`FWKh@iggh_Zf-|S-V$AKtD#qiiew69Ltah*(pi> zmGNtA7Zy~?JVF)_+GQex5%Kt(g%gSO^*M2pTy~>OjkL*0zrmSVyQUdQV>WRL`JGYW zW>AIThYE(ik$JTJCq~nD0i8>gzla1*RI0Uy0-_7!YwA*=r_PzXHQx98e`LD|zmgCp z*b~c+h@HUk!OgblP|aBNAp|q7uM>7|ZzmLwnoXFf`iQe=k2S2Ajd0`T3h`u;6`w*&d->FhT5OljpAW&6kCWd) z81vVBkAj_64h~dAU7m~HAs{}ESzL+HNqEAQDL|yucJ3lMpRyqVd?PjL;#VSC`YGzC z>v8Ky0^bSQv*=HRhRvgNf6gNj=Hsdf-HVaSrg<22?=*nY-l%cu@iJWmN{mdQwesVE zw^~22YggDu8CwWUYcG+F!H}hv~ZRa&BJnnbSRHeY=(z*+D=S+=-rZ_gJ2N z%p4n8EyeIxJYQp)Ke9EMdTX6y?gQah6IDb!7w2lNw_e5`wo|{hd5ZlEfAPIWbyff# zcG-(}x*nz0<{e_Y244vyHa6947@XRbyd*Uv?)K9n1)rZ!MMrxTS;ctnW4&1^0{0(5 ziw`)bA5Y1WQih2YEncvexF_JzKb@G0$d#bzL6OdQSC;dFU6lff)r)cuOQQyx%$;1&Y}TF ztC!k#A|Fhm44MWt+_!h^-%b*qq$MMX2cLeG(aI_cTz#Ax79oc^9e(2WE_LKGn-*vH7@b* zT_A%7PBq25wCBYMqSzF&b*bQ&f%`=gc()SUE2NZ&9*#98`u|3InNpvZ+|7%VK}C%| zs{o-c37vf0%J_+HH9oCTIQbxL-J07$ZBDbkL2*Q>;EcVfwA0-L@4OrrGL=IhUU0tt z4W}+}!s}9E|7)@be-X>cFPc+M%jACEY_se0=A!cl>hw$w7NI*5KP-1pM06@cr;6{r zKlw#T*36h%H~Qsvkz8-ZnTeWKOfZE%ANP}zxM9rwHNU2lK2wd79sCO}<`68Lul~&w zcYbg(O;CR*j`rhxzJrh6X?CX)pD|`IvGDV2{ftOU>tM2b+>G;n+1~&k#IG7T9 zwEC|E^EsJ?c|B>T5IBn~RgX5S-C@xCU6Oq1&B9{VGL^kC8*Vd*oACa~!OS`6dtAX* zNZ5D3jeIhtBIj4Twr}uza#Vxn{qH~RP{1NZ4Xoi$jg)M8Be^rH&FE&aIGg0khbz z*={v?nV~~pug)rJYq`(1SKm@xG290XzyEYjZsXt{Kk0@Q>Qlc?niZGk=eIZ11f}&F z(sCV`&1`&@7(euRe2N&1P?)gfzbCle_-g2mCi`#k@Kp{&H!8hNIy2ERo=yiKH z0gL-i-PlfRO0x^ng38GNKWVP0grnY(^AC@;rdvNsH>=AcKQMioN80r_{hD?xzplG8 zqZ&zj*6G;gV}WTz9bPzwJKU*8elSk+C4xl!gcUypC4~J})MAme)~m1J^1u}4@dKV* z>(Aq;6d&Y2@pShP2c`6)q~+D#e`EXhUXfI+&u`=b5x(F4X)^a;c_)N!5D)sTUk>%! zu^UpWIlU;Q(TyOvlwTt0mJ4kuT4PYoCG(D@aT{*7<@y{Z|32{LD%MHFVdKMrmc}gT z%iwa?vB{=V42tsmOP(K%Q(vf+ohPs&W#uqD4YX={Nr-{E#@PQbfUxjLtmG9#mMF7( zb8)PTs+4lznnl|LFP7(X22baA7q;30*r`c&{u+&YcN0_73Tg^=Uy25r;bJzlX98~= zL_WepaRwDiweLv0=eXyHK4Bz-H##!$1o}B?XC-mzXW`3$vRs1CX(p>#oo=PB zsWXKHN@jK2GF;=>!1^R1k8?82=4#hA95znPo$U;Jz+CZ|Dn8A z{EH>hz~4{X{GoZ;JbLerP~>ay#koq3L8!cF!=Sx%<&`o1?>IZK#Bt3YA%Vnn_1A)) z1^-V|UZeA|f(Ow(RYN06j+qJrpQL(JRVMXR-Z^g)ndr$lJ;bIPo{-29{3&N%l=-%~ zo_j+OkL}L&9?SiNzALFgacD@rM_XNx3R;#+EFi`T4_sJ_laL+zFo6QgU=;QHo32i@&0Kw?TY(3RU-t_$YZh zG@UiBu(NVL>zAJD?wH11w7E-@Z$!B5sXTjauNmj#8$I;)(M8(S$&INnJuI%21H$?f zIX$?AttO@u?`D1|tZhIwzy6*4B!-l|I_K;=J)3Yi&67*=J>Aeyufjf&HBOn9s33R8 zA=ip~^-Q1W>nq$c7;~LkZ}Aza%M6#S_o&&}NTZR4Ml-NC60p*SH4R^y5BkSC2(-t} z35~59dV+5A`uZh(t_o=TMILu%lzs2Me!4@<8J({V8!x77$-DMDWK2R!#s(2%m6;0; zolh!c4A0#p0>_5ij>5vUFQzZ8A@x-bB5@4QV**w>BrKZy!gdGqiL@!rZKtJvdSvBR zt=6hA4%h8ghM%$v(H;zM=2P2>O)T)maV&`)_UC-EuxF3bx7RX4t}-hbAeGfRG3MC` zJ)JmgevK{m$f+gf;Fo`l95wPbG^;|SVniz|O~+<3tHA3}E)%(=g-}5JfqM}5E{puK znnRMlD?PT*bdp>gHrC^H`VHGJQYcClgr6I+mp}I%mUC9B;g+td-qn+DiMvw&f#t~d zbudE-&ngtDIFgO%H)<+_jt1WRd)YB*)n_bmTH^Pa1CX9o$2;+sn4(xux7w7suO{GC ze%3;MMr00Z9`SN8vsv-BxxQRqewA~d<;C2?kA7#xGOVG;hklK+(kei5SXC|})Hn@SDu*7lw3{Z?@h96Ti<8q(x4G`Pnrr_qi znUt{B@fbPj`&PJ`SW$$0^hP9!p&?T1QNu{@I4FPRIfpu-eh+CXNu71yF>r6Q@gPfJ zK^M7iOG8Yl2uqo9DKT|7t_)MuP-yLUPFq(KlR;x9_^gWksem%yaI|AjVAtpijH+a3 zoH*03m0rV9eMn#TL_u2pIzE~FO&E zG_&+#s}z>vu4??Af?XQ2DL7PaHlF zd1s$E!MDKoo3}Z}|3Or1!l{d$UF@-tIi;LqWRkoy{g;}6p|OnH!NbJ4vEa{briN9* zW4{UK6J}0Js;b=_we9Wm4^9FW^ah6T$gm)wO45WLxBFgO*eSQdGexU^T5LzHBaz*G zWl`E@^*eLZye8Jn@)>U$DxG89As3qTioh2s$En?a;F&Ig7{oJ-w3o(VJIOY=6Rl`Bt6! zaHfX2wHNOc^{jj+2H5S|zqqvNw+m=cT8G1wBJt`S%cP+@DVHE91q{5R}T#W0qwWEtYL@+? z->Xz1#g5-Nc>9KV+I{$JZNAuoYM%QmKhe8>_`3$jEs}i8sGtpdN&XJWjfi)^WS5kTZAI|&d`*^cO%Sodw82v-Sotn)T9K%;n_`+MaLJy6*JL8A^D6%TrD4Hq#&f zmG$`EIvduV;UC8iRZnVjXDJ%*Qv~kGr&+K!YP{6T_(eP5MZl0HLWuGtyar^kQ<h8mut(Q?opYPUN$gYfkcJ!g+eRBPv>W`Vi;KH+%~IRT}?b~q=Noc{;bocFj zP!p9Q#C5s2>2hpOnGQeulbD#EAM`Ra(xk0KtANFN`YN+vdi$ZD(WK8{4*xlkffATlbtg^Vf9s^faobW~S?XpXVnag0)rK6EvB^i2SK!b6HK1Ifz8pZjm11#y_5Q8V!=^$|SA^>YR=byF^dEujTVoMiGI6R^A;&vvH??4Cw_)qyl!BMAM^ zs?d}ULO24fbT;ufY&g~oy`_6FEmi_qNpzB!d&=Y<>exF~{Y4AHM?4?UC2C3B&yDuwZJc)w0$6h`RkVl@P|kwdSHIyX zh!?M@h;76>Wiw{(ZedB4X^lFOC!7=$e4t_mt1>e+8Qr6Zqj%jeh_BaM61Ni zpawx=pSbdrO}UB7Xw2>m5Tn~_mD>j+Ip>-;lhfAc^vQJ_7&P3FKtKl*Yx3mBc6R{To2IW=niwD0nt{A%9s#4rbw& zFToi-%xUvZQo`xw%sX6Vk7R9e*RS1FLv`c1|9v#Terp@c%eI_5S27;D-k{;%T^WhX zMi~SB1W^$ZQ(DR2-}{8-e)vKQo$&!WsBqT6SOsZR^UotTKgVA0T8sIcHsL6Sa30~w zw3PAis2Q5v{_9GsKU{9b%I3ok?v*oUITpAkF^LyoeklF46!=h5fm0O`O@9D)uvHw_ zzeZ^+svZ^%N`)sOyQI$@^_Y?;XlAjmjXBh%nD3_@qmbu7m556jWlD;dD-)rE(%RE2 z4>4_O*-42(LK`;z47*i~Rpa_poSoR5E{j@t4a@e&=Go(%!pmqBa~zUvu@GTNG4SH3 zmwW|)!rN#Cpld6UjnJB-oWo}d@tTPASYt|%yJ~`jNesCE>+;5ITAH{uxz5Y(3_RT@`M_*YvBJutx z_=!`+WpVF>#e_0gZkGr{TOZNG^*+v9;~yxIm*pkKFXG8O0XpbZ}RN)Kg$WLnjSA6dQ`-2 zm$9rht7^5`)Rx4S28!zHlpOmKR~_920Z<{eBx_2VkkTjLuIBU_J}pyK>HP8Fqe<#e zA-op*F`Nz^O*l#*4%_rlo`Df3S4-s}DMlL?6OZ`U&r{>&@cApT1ruVe-Z3XyDMy9u zmuKZSOdsDtrc1pX0vsWqdxa!dO2pNpMTugfu7{-YA*I{at>Qy&aI0gq%3wozhsM;q z^8JV9bBhH?-kx3~8wH4QE#$3(9SuN;RSUw#5nSXhy=A1yw74olbXNz3(YCu5j63w& z3CFev>sntpqP{hWaq#Q@1Z1}MTbVGS>P>Kf1`BQa#AR zlJX$|OI;m5U3-3vX&lu$QIm{(W|DS0ef6FmEM(OI1>C<2r>mIQ9#VjJTN?6CVU$vW zWGMBYHN?55TjHPC>ie%GQsoMLb@Kf=*3CAR{`7HKqy5s6A3+Pc&RjAZ~`e(W$X?U zK#)#F`8gL-v!!uoVqm!skU04Toym!n=((z;p!{_8CLTzd^s70|DED>~SH0{(VLTN! zP^Xn3 zg=7TP8Gcw9qSgjxP6R*vjQ_3>{D0hFv@EOyw2VL0ksl7r5AB8JhsFmGa5DPO5cb2Q zg$4*2*o&K3n3?|+*;%0h|8?_U9WBFul@iVd))qzrwr18Q|DiaPoK0+0|AXQ{1JwWD zMn6oYpL>`aIR0mWqyPv21OY+-VSorg0w4{L0muU607?L5fGR)@pbjtq7y^s{Ms_wf z1^{D#3BbhN$lAaLU-I z$Pahqhtl~olmDswKe!_-|1oO*JAV4Guy!_a{BfpP8#tQ?n;6*{oBa6Ipq-o@O$=OQoL{`y ziLw|8us z?gn3oJe+_Z`oO>lSl$q1l#3%!N5PylJFAP3Rdva>*5m6QwO4-{at8rn$LMt(m*5I0 zbR{ha2UwDT&8lv|O4KQihksyf1N`FXlaCN1xO#IV3oL+NPEL+BE{Hl4c~CMb9&E>A z-xN+Bq9c$HPamdNF9~>@0OF>nygq;S7jw0Z_IL5DeS`Bos6em3T0mDc$I8FQ#i7lA zzhHqoO(D!jDSs(v^~HQMs(z#b!|ZHN0o&I(e6VfwbbUh`@4x(I8r|3!>%%-avDr5V zt81!<08utZS>5Q|PzNFqi|m0Fc&d@D{UU&mi{=@G;gZ!YLw8|{Tr6tM6!Rd{$t)cK+BsT#8&g^;G#D2LRXm)bGbAI@QZ)kF8 zs{4ox4e4N#pZGUCgiAyIXqTymIF6r=x&qfbFg-mzLJb7e0o1E|wA9;!WbVlo^sVan zLF#+BbA5hs09)r>4E*%B9<;|d@1;GEyBCNpoNHzKIrq=E2n7xf5Dc~xn?L5t_%Pz3 z+=Cj!%AMZJ;|C$DE)dAm^6frQ-S^|$HCy2_RHMCP)AN_n*E1qWv2w9932EB5%xjM% z6cjnYA3zO{?w_0(2GZNtM+&sFZvgS~ZI|`!y2E$zol+5K{iTEZo*V8MlOhWg;1})96!`a&HL#nzsHou++fao9Un|<@OFK09T_3|le z?ao=;rn)(o{Irv_5OX4r>~W1v3_}MBTA?I=6Md=iJ@TC_%I(ANfdMstM}ocp@z3HvXr`~?KVZ#&^qkao1Jiy1a{%$* z`0ZM0`G0dZ@PXHgsDB0c5oYo|Y5NJp`hmVkT_5~@4g0Q)SmfKG);ss>T~1m10O`J~ zdx!8QHT;Hu86Vt*KX5nMdm+ECtlU4x_z?P*oI34^dtY2V^;@Vd=KNOZVRZA=VJP)` zIC>-kY5!@R@&#{*Q(N5eCGm~^%gg^;VYagE{Cxi`cEIWnU$l>oU0x;&=tt~U*PX+? z^IO;eHR?(&OxHa5{g-a~loE0%Oe9#GTubwf&$D&ly39aI+ zZV&Qxs}5-`LM#7Dp~!WM(LRR9S4&vh!28CMMVuva*-*eBzkuw&itV|48jluLW!SlW z=4gL31zqZE<#ilbH0o@;GAKJa*z&v^cb&aS`NarNUY1>|-csf9rpVS0TMl7>qfgBq zrTL_j775xLkqR01e_e)fIJxjdXR~|>66TIZ?fKzMsO(hsOk=vSoi{4hjGeB@2n!X- ziGzEE@GwdoQ`hGb$2&qxNRYxb!#Joo6wgd9}PH@y0vBWlvdf`k9St+ZvAIf|C}yqnA6 zxegJ8&bHyV0wgccxfIM35>_NIz}Dk4SYGMyqf+h0^4OiD~MfZI&fK#VpFDNOy_x)RiUFy_~R7s&P7CeNC_2cOjXY ztg@$RN}i#Qq%zWF7j<4yw8Te5(s{6YZ@rFVGVUtN5EbVeRe=Aaha?11XmcEO>#U_T z&&*%IERcC?;aOg46M~y8*PO{w0hnn~#6B`Zt#6aD!m&9gt&+fCG?l{oQC?pqn7Tc% zI(7B==OUtW{blQOyrfk4BX84ADRLQg-?DH+x0QCzsO87>Hl^H~J;`Caqv_&ApRc)! z%Q#X-v1hA;#D>ktLc!9KHosQLiEN{NAh)t04ZOX{6Vx!J$$eBf#Qc_+Rp|}b@jTZF zAQvc`iOC?Cyg)F-1{>ZOrdThP;C8BAQvBeC@1H3iggqr(>3{3TcSoP|K=GX}S{9IF zdgtzrzZ^9PGrjm7e3DG=gOF9*kIOg{GMvf}7~4&p&w=v|%v~Q_@~{|_XA`s=ML7vt zUY;Rvx?v)>hmNe0fW(82XL1gg5B&paFa7S^>J;djEi-5<{$N}lo&p@8l@=sr3$J?W z1;wwaiOCZ&QFbyM9EuwF+vr80r%4L&qiv*t4CND1UBBj@Lz(LF9a({a&-ok$}S zXmYP^i6Kk7wR@<%=0ObWc$-}!30c{A0{xc@!x<1F@2Asu!sH<+@ewh;J$pWDfxsHP zu_0&}_>yc%bM=+Wm7sRUkldQ$Ta^kWPqGCQrxY~hG@OcgY1>pZ2XMv}8(7b=a?Ba~ z4blYVb)W*vK=B$Q=uwCEr}pB2@b>HFn?iN0%#Iww z#rn}VyXdY;4hh&w zh;DJMiECpoKE3ps;*)p5H|(29xLjz2$h6?(3m4OFanY~wxU74VmJx&Hi@Kq-n{ zS<(RCnRUs8ms8oiS)oDA_I2S@gI+E|!BwmDCQD?r4ZG#xJ&v z8e?$5X6CjJ7i|qQjfUq! zpU+^QwcDg1XWi?1n>xvUy|#_w`=j`%py1meRTLWbJ%!FR?;}V0Wzh`Zq9{9aPhieu zl|ySYxMQlU%(eyh0t(Oyz5HGs^mZ31+4*u~%j6J$@cW1fu01zaei0%!N~Pz&8CR%B zZ7ilZO;Sy_lU;BA0^+6wzdd_n?q6C>sLUzHMKOclsMurA<*uG;|Fym8uqyr@7Q&37 zkH(JkzClvCzd08t!`F``Zszp97yQieUIyZF^_yNjemyW!fXwlx15V=il0>oogwxy8 zQ63LSYE%gkNejR!;o_=DvyIJo1lPHki%(;aJf26RJgx2ATop#RRP#Q@H4mHhL zf33K%Vq-@-RQ-^P*GG(n7<(devSapd__vNBZhC?|Htsh0S+TcbLdRJr>NT|1OR$~^Azsih2WVYxMlloucwL}Afk8u za7~CSr_P})1IbqM9Ll0^5QgvmsSz`%W^Ed&@hZDX^pt#z4YD27l+E#y8KSXc*}s`L z5XF9wU=op&O**Lp#a2Wd?Q1Ig?OoTHXB0FcD6dHjJ*(t9VWB=fnATo;a~XzgYk?tL zdimzWU8i0ejEiqgkf91ljwd&^W>)bhN(X2Djm=v6t-lLhB_o%v>G1g^@+Z&6NAr`E zsyt5(xr@PkuoJvK>Ykk;iS^~5*0_B6S9EA^N65Bi{bi#bK}u?a$Z%{ZH+THlf>tD+ zJNT~W{$rH8*9-JI7T9pnBXA6@1*+s=J3P&Yvxhgq129a+@eK7?*|04??!^w+^=(aW z4R1eDQKaLQDGQk1ut>Z@nLTc~E6hJua>JY51mDnmL&ka;3~G$~>NBw+^hWodJ1a{w zcd9MA5Or7)XqC-f7JR0tewt6n`*Q5>)E#6|&0j-cU{a{ElgZ;dQ!YS3chX&|f~ZzJ zFU258X{bM2J|((Kd$@%bX0d=Z$sXPJD`PAh6@A9wN928-z(~ z0*!JJZ3R}wNMF?@+<^fE-fbfow?;3vQE9SCcQ#E(cuLfs&5WH>wMrrrFjDE5`tcZ+ zcnhQCE$g>nCPmFIRgZY{NlI6k;AOyg@U(d*0^s$1uzRkZO^-jCl!TivujC6;Y z>~GN1!g!}oxa)L#v|N%lJP zBcDZve;{n+x2>%@k7<<4B&nBQw6mf<+s9z8NKhlT8{;~CC5AfZnCuHOTd^g)^q=zY z-Xs0&0`03{Fr}^fA2CidKvfx5EAV>0VucRt*%)s#k5YPQyjX=+^}A)@qQa1!?%SEKae7~su=N;Du_ z<#pC1fbY7Dt0aC%iY2klc_r9$^QZCWv)XOHVggdx%wjtKm5lyiuK24&14a%K1*f~| zim2P8?T?yg{pFSr&9tBv0Y`~UTma$hZ!Zl`KnKUkKa@ZM(+a{?UlIy$__xx4YIe_}Q^I}=$>Zw;L-i7}xOhyYXJm0@8mz#;Unjp|Uz82$8ivHJi6vI( zee;|vrCC*;(0Y&8?nJULw4Tkkk~%f6OT3V%1n+9WyDj{ z9N{!B(-C+orD)Q<0atxwQYYVS=>!H_Nho7-pHRl>j^(oQM%5$+^ zNKYP91{U0H84`Ffp?tG~OpNty1jLSdxuq$nfI z9jDzoW19svj_SwKMrz2J4w^y+ilz_8bPz}R7ut!HM-iFFk)G*oA-0A67pJ}fjG`OA z2H3>rQxZ$M{UVxCdB*XAGtxpa^OUvpOu`?BajRb+<@;7$^qdb?kQglKzU+n_YNfk; zkKRQ1r$L;jShof(4(|iQS+u~8x0X8oa-jvak*$PDZ%Hh0MooFK4WXTTf7r^aZP?UtMNR(%V68P!NJK|4(hYc1$$ z{f?orYLSeYOK~*+T{d*qV638PkNW6|q4Lpn`geR6bjSmshf>E2nSk+lC?%irgiH|$ zHn#8c(k#XYn0B>UzND_=TzS{94g)t&=@7B1(Z$E9-(8V~8bN7y$;l!1kDT}pFx0@D z-xR)|FyIs;#sb@FwdBap*F5<62pRV1)F{@4AQoib!26Zj zEr``zW3mAM)6~d=XaXZkv$>=``NeTZv@l zy;8AGvpW=V9$*5wByAuEu{ZGPw^Mg(RNzY9WpcT(cb;4)xJ71%*i`^!FbwEgqd^mx z4P_P#IkYXxINNM$mHgmQ90{00{-aUj*{z`XxUf<7H(#+k4@pQXpA2i{7fmF-#zSEt z^qe{6!?XmKd7j1Hxe4+Z8|W;K6B-6aEFYf0+#JTlhO$mbKX{nX;n$6~fOiv2wS|{} zE5B@;Xa~jHA0jz*rd`Ac;|r^vYeCPO`DAW4=MW}^&(PTpTc-@apUfyn z#lN2j57;^8$2wE#$G&cAI`l>m958V(K?yO`_N`eQQqN`K6^urwEaJ~pa8O$qgL5!` z>q+gu2~|kU&q{hqcd*cyX%UVSqu^&vSXX5(l}l4L(Uz~AnBEAQEd#bR+=vsU ze>ltvJ~QV7KU39+sIB2wklmATd!ttcZJIXZn%LE<1`fOj>+dV$pnWKaw$cTpS&>~T z;6HhoD5azMslfHEI7Qi$GQVZofoD65MCsRLLjp0K`5(|^D;KnuNKDrfV3JbnyHXa8 zE9MUlPgepV_?^w~&(6Z~XCJleRl(S^*9$4k7|}vnuLU-BRdP7WX#COiTmY<50!)IK zJg*ptMo~+w2OCXsfW7Z0>X_Zb)GT{&`W~5H!um9eW`IQb5d7sIsFknF%VFGAqE<{N8fD_a%%)wu~eCv_X5CLe)HI6cDmmN zT_khgpi{~ClW5?We3tmJzNsQ)B?#hHxF>e+xUedi!Fw7OB=TK}7e{GMSLip1!ul#E zRy2bXeXU$2h)pQ9tLDhyGW%if&eeMA67Ofq^&EZ+^v>Syo6<5MMS7qC=Dt;mv z2k}5-NOg!5RJw<&Th9uAffkDw(8!Zx6ZFGkodX>LT^|##VVo)G%D3zLN%!!BN>*o% zK)8*u-s5nUm@Av zS!P?zRHi&Cgd@Y{{6s4+3}85mzDrgMVoJ+&MySPR4oh|^ZNWF7(W?C^66s88ZaRRj zoIa1BIn|1p=6N~z1I(#7>084`<816fZPmqrFg0$E=+d@}Y7App{x17U_S|Z!LHMGs z97*#mOIb zu!XM!LXum&yw0)VySp!m@p7X8^Z^-Id%_n%rC;)8T{6F zrBon?(fes%7;#cWl~efG@tbmmfdLz~*UoKqt&MzV{3ao-*NL)o}Joi2gFYOy3L18++p%0kNZ7Dz-Cu{(FzUOq|lfFzp z#8cPxlZjy2gKOaudh7Um=SV=(lGoO=i^x?I4xDl5F|>=rRT zeA0zl^qSX#32YeNHM$Hd@Sg8okujQ~+omw9>I8)f?3Cb~lTJv8lUW0r#@h>o@ka6K zy8-u7&RPYa3<2{VK^y*mfW8A~UGbRZlQlb-f4err_#Byv^_C;R^mSIzXXm=TWrXph zmzi_J#7KG}2UH+&)&UTu7F&fq2WZJ6;fRb zf}+K>N@NhXt(OQ8-fLP@DqZ!IdWAMqBD;^~-2@Y=I3YR$(&A}}ZQ%K`uZ}|_T2fG2gwk^R)z#;-lnsqT| z<&0dJw@2JfgMz8kCj~c;1lp*Y7z>{o%5+@x!8tYhM`$lp(Sviuu}p%Z0Rlv=>2=w5 zdq7QggBPVSQ))tRd(R$`qK~8fg_QL7NATX%JNr*u;@~E^5%G8asvh!+J~xdfbGsjo z&www{gqKwGqtGJ;B2UT<0l>o_A;`3~1H!Qd6P&8tTzx*o)YrB$Y|6pJWxBmDMEbi# z1Fu}R!cK{wlVWdXT(>N+EA9HtcU};&zrV!&jXLaCX}!|i;1`8>`t5tB9Un}71E;e} zkiU2WhMM~M3{h4D_X6(GHYsxZN;S9|s4Wg0wlk`0QCQGPwhj561mElRPX^KOMeHkq z?h%}M%7E_8vo_q2U)?1))xb@(cSVnuFzc!`7D>22wnImzNmXsjMD;JW#u0tl5&LeK zJ&`nFa;t{ikE;ZB1;rmVf%V;|QKGet7Fjp<($fQU4-(?`TbR>_=1@f|Yk*=HfJ&Fa z(;IZL37Cul>thrU%n2CFk3Y)2N5_Yau3Cf!S@Q1ehJ3j3(W(*e?r3f{JCG}RsalTV z9YH;bESdJLI~!f8t`Ab`aLD47gQjR;$JAt{*4Ifxy8S3KsW=?z2E6PeMMup1X%-9r zq=mim5UVlOeyhk2o=orv6#jB7K5NxEUj`L6Yl28xSC34Mb}fK3G8idM^SH&XZ`&&& z>rk}jhPVymuNq8H{c%mC{`E9m_nf(3k-DmTTdhiTTZ-uWS1-OkeA=g@(Uh!;l_X3- zkGXXn_HR6S3+m6d7%6-e9TXinvdXA)=XzJBb)LyPn9s!K#34%0)my}o)2Z=bVlJc& zOrU~GRXxt%yDc<;q}Ll4qEr}N!_8e)?sh~g#@w9d(h1AadngPCwD!pGb*!A?jGM+X znu=}i$mVJc)RQPI@h2HdkgoWY%x`~97ZeGjCUq+^(nF@`R|o@F8W`m{TQzNYtL$#? z-P|NRDpqMey@jg46O|y&PkGvr>JtoWKj@EHlPEDQ(e$k^$yUpNT@)^2TJJ3N*N(RI zm7O!9^`EGs1Z$D}v7kSCLfR+6wI>JaO8aHrf6DGj$qCB|cjP0e_dmu+{ex57zikY( zpxRuPT@=!AiAX8<3_?8`gA zZLw*7royeUVspy9J@8(Mi88g`<@}7r@_d)$$udT@=%_RORY!HZ0lJ{>#Rk=((h@_8 zrlqpxghojO2sL#)B~V$_OFoGqG&_yW4nFc|m5v|z(u?D|Cv3X7*j_y<%x&~Ubc2c2 zDdr}al8~M!gHe{hNpCZgBC1)`~(i(cL zA%XsK(wj#%m>GR|Hr5D+YGVzVL`7jE{K^iBMR0R1ZX9}!V%iBO_mqxihry~=>@J0!DX9bI6rPYiN7%XTPA7(Ur8~pmrD5iyeCRP@gzQf!d=a>WAopgO;?Ud zTWA_$wMa2VWl4nG&=0(Atf-k^@58)$^-Eeu-5MT_LS@AcXYOyAnxLKLj?enfgX#X@ zqh=rTFgZGv#1UXn%|~vi9WZM&#G_hmErjvl3#i}yr8)?nV{I0HtRUCxtMJTSk%%#` z7FAzRrcrWcOe_!awbQn4_rka)l34OJ%gEPr;b~JtRRICQr%_60h^R>`JpoF@kXKQ= zI5k2%(zN_XbHFUG88sn1ACDYwdp|YoRP^YSiwLr=F~mYD`7I{=w@(w&2}ta2RqyTb z{+3yHnZ5+et-W_zS0WVMt`@ZZKewJ0J|)W|oWnWWIN{m(IBt@59QY+&7<@DNM7$iy z2s92KyJbOthG7`6$Jul`LW8w%1#8Z-%lU46rl9s&Xnr02{(N0+l|I zj$ysz_MpiG?)wHk778zAMyVQ-z7A_|d$j_BFJi9KOpJkJgH<%KGtPQxNtM?;0U$A& zJ<+5=S$eRD*V*HE>NBB|gPFk=R;-leJRe&KK0XE)!V;rWHuD5jD3s)wI)ujN$dl@H zYPNlmgZK2R{tbTE&(Rk*t+V!b{93K+1^~tQA~aoEfZ<%c%S@cyr}j#hb)hze3Of`h9g?M# z#NhFerjJ}l@!#C}93^Tt*VfhYTo^tG-z%IVtvkQYH_nY^O=;o)nRMw^L?3Wg@lL`P z`?0S)@oJME?9cBEoMC9*ALX2>{=fYs+{j(Ug%QGvcd;K2EuoDDN@AJ|=qH7oJU8=~ zRTk6y+U~WTwrzTs1rFNHNWhiOu+o0H{Sy@Y1buz7TwooyJHQfS)M6mzu?E_I^z+4I zvTRD(agk#G-Lgga95$-uFTTdRhqq!=eY@zorO>?F)|`tDRjO&@!j+((jZ|*|&zG}u zw_BN=8C*&ID_tv!kjng$jzE=?K%te8PAOuE;YZu-M3Z&wG>(GE)?XQmt_2re=^%Zh z3;@;v62uNqTA2rLfDIv6QygT4HLR9d^;!4iqcp@{sY-lIVNpAe!ENU(p4y8jj1E5% zMr!T^d_%Tr$8wSrl}3(j4g2yDtp83c9jekp7fB|Acill-sv$pl9aotToQlxnK+9z8 z!~zoSAmY$?XC?+x3W>FpzvFG(kY?XI7ALkjGs}>2ISd!sX8#aX{sbyQ1O6}^xuj5S zJXl#Uy5t!ayH+N4+F>)8(ADO23V&E@p%e>bKW93=XVeGg?D>8Nj+=A-t%J2hzinB3 z%5Jl}Q43j|k;irsALxg48rfp~Zz15g-u1%Fx@Ec;>_j;p>YBQ8Gp(y1o^oewT|3%R zqYz-!U&SH5v)G;zV*a}#3;ENh3hdz@7+njAhL%R?qmp`R)GT4p-YZU7!7Ykk(|cYR zR;&rZq8mKuL@E|+SMb*paTrfnl;Qrqg1L*NJe`3i#n!PheWB|8Dj|+Z87fOfsf!7R zBYq5@3O(^Z$)M7rBK4lYzHU3g85QXzv)>f-mpaI%y5}oZLsZhHl9;b1K_rf&+&J4pMfq^ zTIyHat@dyzSLNT>xdcCUKIALz!kIB{lCWxzh9U~6p*KS%#U;Kj@{fk>{$)eFy9^Yr z>J~Zlp#0O*sG$VvHafsdcXQ6lap>gB7Od(GGfr7VGVmwLi$=YRMy&Xtt*2MlP=SGz zLwUF8GPC}a@uVRv+ zR(h*RrB82v)(j)+s%sP?o2nt4#NGZ4V^gU9L(<<2&thlDk=^6WuGMlA^##n%+D!W&y}bn!8AKTg?;BJuwDMl)U2~5saIM+UB zj+%>K0bfd-^F_*|{SYM>$|J)<>@)mE2JTRVG25ezJ~ATUypWfEV6-VWF|z<2Cca7Q zFs?Q1WOD?6)VDewJu!oCCVo&Po0^yB_Xi0w`o%%_O=*kchH zNoI`yhzayg=8nZ~4Xu5-Nnp{Y7ktO|h~eU)i!x7oFddJ2pU>D=83J-Q*Ul0`WC;84 z29qqZ&NyNa!mTH^G5S|k#1l^7s}ut^TK{L3q%jfz#$R>_2 zBr(qNy4^G2!nTQ0hor<%Y}-{H@4y;mw|;G88r9{e6xI?4Q@d+LS=61T`5187iq~In z8K*j`YlEZ9o#5Ayyc7rclAiQpei`!e?s{wl8tje8TT-=H ziCNBai>{cSiP?}tc~djYhpaIZLuJSVA{w(`p{5_1!3}EjLt&t{#l%9Cq*SlESL< zYtR8-=f}m84pZL`RO3OLMhC`#NM+cE#?@P-_P^!0Yb>4vW4IoAMZtyP>YaOspLp2X zOU`=ZLXQ!6g#CxKK4{!aaHL&jWO&hvPLEE<6=~`xSJE<{`f7vr-#nJN#!Kdz+$I;~ zb2a)T>c8M59%nv0D5mS^w6WyCo+)As->h-aec3{)JhhD^H@!0s|oA0S+fHPj`qdTI1 z%ekK#jM|65s_8?oKK)a!`uX0W`R=4(>hz0^Tw3&-V0|-c+H}*3riJ7sj*Z1>%o+RP&Fo}qfi@K? zv0t(Dmxv@k6p{c{YD9@wBtsh4;x*b*K~^c;BB<_>6tP(IG6kV(&%7Y#LbsASbq}*1 zKV_2>xfR$VW(#0dm%YPiA=ZY#3hY@XLj3Ct!?VDWI$)@#=i@VF$w88Yc76SDUABql z^W(ip2BHi!ONue?aW+N4X6cXtCxNM_o!!cWN}dT^u5rUH^_`934@$ z5U`xPlZ#_bKT!Udd<78^$th+`5jPwESF?5|eD(cnn{p%mqFNat@Aib)jkk5;yKpC+`&|Io`;8{8H^DjxnYX9={ z`#J;oP;a|8GiLwlh>}eZwdwjgj|a19QE(FRn3jX~+}+JBCby!ytF;&jwTPq6-%L+1 ziZJx`$8;LgCV@`!=wx~pD)H_kn`mOg*c3w|5ktO_*wO?CzZwgJAe-arW<^Axk}5tF_~LMtiIF{{5>G90I?zd@%+8^|&S<(-3H(FSR%wWE!*f z7iYq}<+4s`q;Pz6R~|JLb6O310QD`p58ncjFjN1IYtSh)Zg8IDf>T+JS@t0fxF|`# zb1volOP7v=_&w{$FJF3~Ce) z3*5*&UJ_;xL0ULDoga4C_%OG|*Y>l58v*vgLQ>1~qvWz43{YvCScb?iO&$sB;s#Xe zc8oaIF1s*-(~S%K?Ns^Upc(C=T}RmLPVgb;!?;j8WNK}zhtYA*G>5e`dl zaR&=q%rJjSl~8hqHVrnYui$PpzZ@|2(&-FnIA-zr1uzx6uO`;5H&@J_h_Vh zr_FphD1{9+Qg!dEbF}NY^+_Zi=e&+WcYZgs6bXOvAaFjrJBrL;%n<4qwxmx!FsFI- zVdyJqRq6jT%YURf*NQ!aHCJ1G@&MMfD6tKnYbiY?+=Dpl6AD@C8|1T0q{~W9w93>% zoxCF{R@6aI&epLrFN`ulRTkQU5b9z=;A?K0nbF{BsJ{mp{kd_Z@LnbK6rZc!exa$R zdM}yGK%v-qPOTbP#TBFiZX)rLQ>9oayVVHRK^O5Wvu|)!@?mr%i8Vq7LWZ@ibvUi4;c2ZlNHb&><+NrR!lG0_ezDSx(4v)%^Xr*+0>VApY){PQPoyD>;04Yjz8UxM8(KMbk{>$xjDjPh2MYLGblb_gfU*{z9G?MnIZ zaopQ&bvL{&`rVrF;AkMmuwf|x%hoGRcn69n!Qadt|8p)W+B3X?WifGpyMi17!vP|M zLDM~ zaCD-9!odPD`PgqSGMh$ zv`c};4G?pb{i1X8^zvSYh}8k0W>lSe7>lOD-=@Gpw#zY14qD=UaCN}9K9JrchXvqL zvY)NDHPmv}8sn?|@sT|7#~pbD_B2{bY|;A%4Ou`cLV;4>tnqF`>*xw^a0$NL2&+de zm*$Pg#|OB~6m|x{#=bh*nbbr7(-uxEn6SZa_by^Tyf4#+qV*N)T~pXu#?*M1SZWNd z-IThw8>BzyzJMxvpzwp7^ubjy z#P@0cOGy1QAUaW7HvqV*KtTrZ*}6pWUd>o}BfIpAR& z!`vL~a;EWu%%;ftC5>S)dW(wKvir#P9y3sQ2S#ywX*v$u zdEG*$dYqA&4Eh|pP+@Z6TI2sXW=ek6;pOiNK3%UIPrbpIfNo(|X5|vi)_vg|8GNZ( z*mg+vF0_JxA|}_VTQi^=CtA-&79^jzvrEX@ zJ`K93;Y53rn%slCjag1>p+&1If-Pn&P-z3}UmIq~6IoRf{x!V(HA%I|G)$QIsGkPj zM(6WrOuc3MY>!qf3zrJlSjMab+#oME8j3_~xJeHT=AuHVhjo+1m!i!TD9>9WoRg2W zla38uFXz$z8#af4zMh4BLTN1OBDos$u@wKeBB&)5nSGZ{cn%C{ofc{(x|1( z6;19et6Kf>y@}(Uiti5wi6gfh_ul1AYAf)b|8(5YhA*3p>o=4By zL{qg*928Oii?w?UvL#y61YEYOPT96?+cr+wwtY&cY}>YN+qP{@-P_$Ww{+lB``PA$QxtakKLfx z`M27I$DWb`#lMW*Ol3bgw;%( zvN0(!tiMgzyJ0tEob_y5=v$m#J1tZ9cuCF@(o+<(4l49`ayUxL^P<-B*2|R+dx8<` z7rMai;Sm&(M8=YvIu36cOzMYBE~d_u2koysib`V+*)JNB(l%w#phpR)>{aeVUZZUA zqI0;yq*5_Qy-Q*RWwWn9-(F=|mm@EyjL`s|B6_kl`J0&MFcR{SHaU`5F5lBZj(C9a z-v;&G2^D>u`j}Ow%)}Smk&5afL&^myjppDSr(*BihXw7_3lYLPtJD%@ z6^EQX)6D7a+Gv@=?FVYQ0x375hMGTH&gvhuxhO@V6eSQ>JRWIH7JvaZD<+i2VE8vQsGZYv}po{pWUCJWat1}Gng02i`&2hrs*1Thxca;)HKxAm%qSq!OH=I?Rs zZUHD_L=Hst7`_)Ws+XyIP32LnlkK-jD4*aZaCB}?#s;s}4&B=)!*OGZTQ>T~qB%w0 z>}ZxNHO^;FNG{q@Xv567aNPL~_ z3T4SsaT!(mX(~g?`>a(`f9g%h;MKb_MKRs%?NckeecJ4m`IH}hWwCH_)&vh5`;BEA zsuf(mw`zudvAfpwybugXbf#-CTX;@v&aJAN-8yQ+jkFEY(*TB18oVrznO>enX*5TT>$(MiW`fH&hoPXG7 z@ltLCn2NEqzwM1V;$`b_aW(%;NZ}iFF=X~i@O1n%z@CX+vbW$u;}jML*{&x1`F=6c z&K(#CJ-+kW1;c;sOfAhb-)43@>v@-^aM!^(7T#oTzG8L@|2B)D;vL4iM8l~~qXENZ zdy33AfCn%b741e2@#>`t3&SwKCLSE7P>)2kHW#V(;WVqQxBHtD1nm8ZZDlwzy(qXt z+EHnB{A%uP{e6oGg57?u?ay-a@rg~Sw1R1>bPY7JeBMDAJ$d9ea= z?0M_QC2xyiKqOD=wdc>SH0}Hsy}|QmhCx#(K@#<^Ycy}ua`y_wz)TRrx(4sX;7Ng? zp;Ab;OQ7Ta<!Tg zROdEztW2J}`#onG`B|(O8?&Jm71F<2JIHVD%#2%88MLDKH;sSrBYXs?dN1f zcNtR`D-mFNZ%MsWU0X|8nJsr@EiHKfnglpS2&kAXYCi`9 zVYiz}=~5Ag%{zO(6R{ZwN0>SJZMSaA<ii?wa|J3IHl<6ksF2-~ww$2X!lTo)Zw=w>K>b5_hKUn?W zT)O=~WxAuWi?I!zqq*CUQFk(PFgB)ha<%;*TAj|r*unNcll6Z9_5V!P+5hF{{s&oS zU}5+n`v10K{KqX~_>a}Uigos%^Zx|v|2JaY)meFA8;u5*a1)|$hR2EM=Kz+m2S8|| zhu#TN5ei~1PEuSVoOy1Of?$)P5dT%Q`_uC}y4j>Mb(+I8+wr=~^?F*fzb~h9n8*~m z9*n9#2LjgzKO2N!Kxj+-8(;N)DhPyPr-B)tX-hpa(q`1p4lM zHsXaM97Iq#2win@G8)3c9$ZlGWg$lkpe{lXFhAM_T!?3YHDI?HFtY&dPWLFFy#~M= z9Kti7qz64$5E=v=7(Vh80v7!O&gubRBWOS1$RnVK+ybCxmHr8y{v#j2h96%vcn|!+ zx93LoW;d8XPItNhD=R&k8o~lNP$T$?Kt?YBjj=O+A673cfPl3xpup4>y%FCCGKf8x z1`%L48$1yC_$dIt_+MW}r)Ga4ZNw{n*FX1kNgdro`0$#L7Uckr_JBf&S1sL7#Ss31 z)-hz){qN7exC9Jz<-2`+Z8CLfpt{t&*ELtzYlmz%*6~g{;P*z3xJ8Y0OA$UtDD!CPXpiC1UiuO{R8;h zd$t3r%tCZ1y7i0n(^W$k_Xzf89}xlk1_I(9@C8&j7$C1t(9iE%_U#?!Yww$@95&#i zwcA(53#c&=aNs+~pS!!e#OwSV=ME#Q-GcKZxbcb((2Hvsh zb9)UL1mg4;M+uMOHTQ=gKW{GI9fGUzAGQ@$tbiK(7a=)c9dHLwQwWp_SjW&04`71! zmzS^NkcONnj&t}z>=8ccLW+#opnwXM;kE>}`uPy4B>Q%TgaBxgEaYa_w4-N^R=<3sT ziiv=rdznRbBpO`Nk-NG%=&HgszLF@rX@lmTW5NQJqOW1Ame&?;2+v^&1#8mmg0~<` zsj@Dc-g zsig6EGG#2tiaP#iW)`!=Zn)6~^)s|JK=y%krEOnzUDa@Y z?K9C*(*Ck*{a9$Qyk7QI=j%E`uC*jQB|Djm8S6cyLwyrVT=#|6?IreQ?b^B?uM`&6 z5sRBH5`?JLiFsWGt7S@2$g*~oADeAjWipsRD%OZ&M5UgF0?V|T^{3FsbrIsU&&`S*DKm*%?BJ84=46&B zsO+XfuY1Qyd8kpekIl$=qHXL?j(mEfxOdQ287Hm5BSlx%!5jhGHEa2NA>*XQKjK#h zo(Lz7&W)Ak`5-N?k$Jpy%xXi*ZG3mA8=b{Is<_ccXN}EQ@2CY}bXL{?^s}%@hienp z5-NG_(Pg3&VYA4IR^T@IuY~Ts?9jQEbkMv%lqWN~l%V7`tU1J~s zj`4ts;v`RJ?(+h{XdXsC7)az5c1Q+gr1*Y4C1_olq9@WCO*-j6D5u<)(mEnLJjYE$ z^5mas+o!0n^HttO)sn12k|^{cUWwn2VCQ{3$UKdAMn(_EF?gCm5)2e|0OIL$V{mt} zoscIe)6kv|U^sx@BYRkf>*k(RVk1hQ;&j~^^5%gYW`KKXy>^h66+gO>HpN-kBFUl6 z)%C`~zU0Hoqn335L-jxFHx@&WzCU*!xa~W{lPizgGr4*eqFv2CxUT}Yo;}h)#T#mN zGp{Jsvl{&LL@HG=iUAO!(qzYfC_}dsicV$>qn4)@R)`riEd5q-<{jUio->8+jwwY2 z1%_949|I@?v3c{cu#$zUKJ@vEM(boxy=51x*0EAV4tJPsn_xc(%HrVbg4GxWh{+AyBc8k6@H zg7pScD!;_T=5C^Gt8EPmYN@}wh6kpc&^WndicAK18oz@kUl3MNbajY{hsqYY(mj0s zH!^RqF+`#hZ83}FX}QJ?`Dd1(-iF)F-8(1K8^Eey_>x+eSCdzRKeRCfbfiuLSuKeS zjZ^W`(*%kGs=2^MvV}z<0*wrXOrI6|d_jidP^B^!7w^!V7+5`2bGy@}N%~hzmInsv zm1|>zCd$#O8+#wMmc8R28Zt}3tVpATW#7iC{?fvJ0>3bsHFCgh+e8^Xq(iOsk>6C9 z1C1bLK=SIXD%Ap@dEE|_*cL?3P|amLWG zn?mZeMOnTIRy0lQ=ERE?f(4nQHL@}lpaVtjjKB8l7H7Eby|<8Zv5z2KTEPAFUj2y% z!;n-@u%(hm;}JsT zp&%=$8ldIkoqc3`4u>QTIxCpmeI#uD#HNxz?`QQ|YXu0UV;1-B2;Pm9;z=S{UPi&f zhSgpcEuC!`HDlC9*IK1o#lxLqPvf5^T6SFS`51ttYjo!JMKt3{f|J*Sjp(2voA?X! zP}DKJr6hD-l5%m>N-zSQ4l#-iy%S~T;@e$fBc943)u$2(c*@FAK5#?BH%dobS#_Bb z;c}&|<`mnu>EU#E6_Q{J`Ilc7nU>gh6`yoTJh?-;WDSeyTiCKQgpb{}uqPyb2GwCW z3=0A4pt>M5u>15O%LiR|>ury=DUS61LdQB;T0^|u*DcOn!o@Ihqf%g{VdW@U^wws` z#{ATpZjm&u%ExArxEwnj&+~C{OR#N(BEVfIIGt>-T4^N_{gPE$@beE9ojo3Qy1Tg% z{(VVLDd*s7+|LW@rbE&%`uNyhj~yhPEGT7ck&C_t%FA}8b^*-t`YP0vv!r-YFchGZ z^V7AK*0~#hq&sBH$oyARdfhw}E;fZcA)0A%OZJ^NsMp-B0VXW7z6|31Oscg^BPuc}XXAs)4wEv5 zv{*W8^2W{E)Ee3_yF*0l`>WLtFZM{} zL}rpZVhA=3ti99Lg#r}?nqWuUtG$}4v~5l6e5(yFc-RY6guPC^pX+;`H<069JO?X% zEUKrcau+zXU8IPeiD;X|_;shq%N9^{`{^qzFQLufu)5~`l^N`n*sm!T;Q*A)8`E2T zB4q3rZ7dJ>ycX`0ueU@2ZSzuKm+G+yqnkt9%O-ZUdC(N=PE)%==sv}w&i44=NO3RF zf*q%^s-nsNQ+f@`*-Ug)bGeXciD6C)vxBOiei)Vv21}-xxJbO z($d7^I-mWsX@-vTEt94eYwt~ef@8gr)9R84oPwII1uc5Q2LeU%oW1`Q=Uw^Gh;(@{ z7bD=lGd=q5FOjq%>WY-PkzyaBbjf3f21aS(YN$z4D=73 zsd8#os80dvFzK$uhLv*@$1h|bz1w&oJW@}19rI`%zw*n!qM|Tk0N!z$fO{l-oYQ$7*s@7;p(;AHon5R{XxIh=HxY^}>w57X}!Oae)Mx-fvIn4wO z02htFqf?W+bby6R>KCwG*depJt zOR%$DnNAe^I6`#_4QiLd6@$^Hv?t}n7gc<2P335<24~SA|R%UQe^XEvzh|N^Rxe?umPy49p$qEe!R8 zxU5SI%XVFSU#WPdEZa}I3=-qmJ&cTwM@O< z2PGcP@i?DN@0%zMQvL3G*VLR9yLCUX4mgezq5RXSZ+Yyxlf^@zX=q$_r#jTw0-vaU z2=Tk`uwS809K@!GK5v_g!2Sxj4L2`u{I#|a1&?gY1FFl6`Hl{KH^1O zcS(&J6^lWf!gvPu4wsSkO5+{V`j1QDvI`U-kL#k|^3TlCVr1-2NVS!$vy3pYTnyu@ z6x}Sb31X-v+ryHa+FP@N!)UyUD7J9r$b-dh{aP)gIy(EyE?ja3h>G+FX(q|?(p3Z)7(}+oJpUR1kf2>s1)+LxQ&>8 z|6B?_b@n359=9Kv6rePnsXiMb(SV+;zwBdmF$o`)wm@KM_^lJ5mux>2voO+ga+wjp*( z_t5Hz-HX=RKw77PYzzpCzAU>E6(CerJ_eujk(zmrQ&ds@sl_C;Y!Qr4jGAV>Vj?yK z^6WY?Us5wwaDVdRsrL@+G^z5M21v_61*i$KTw<9&QGnGX=YM&rohG9%i}1V5Jg+Pz z&1;9-@HvkXqhxKVn%j9ay-D|Ch=WBAwwMDsmCpz7pUh0aP`b^qxSKx8G{Z+)A=FiA zMGVjc-!w9TM^r;*jvqL6fdpxu_hcGOym!4K=AGi`iDWS&%o-0#!@0(s+Y9_$Iin*E zqh~CH_d#?syYGZ+E9W3w_>nKSMEE4SpZI zP2I(WB^g=oX<_(tMxnI(#q&V(%DGI2A~i!7G1$dD%aj&f+r1GUeDW}OWCnKx-+fBp zkmB1tOhAASv_GsYUPJyCliZyw9}cmq^7wn#CF??%5S+^fqSjP6w_4zQ;=1f@w+oklJ1e0T(+!D%{MO|-zb)y_9f zM#eJXR<34UkG1XCecMnl_xnt@v~x;Z38o|QAK+$(@ZJeLL~Am!cY@=Seb#aJyh!ej z?5FzY3tL|bh~R*6zgqRJFjzTa2NTYnQl=bPo?S6Rlq9;Lfe0w7%KV|oMT*@ecd z#|GUFa8NU72)wdK)sFeUC4y}cY{I_O^M^0kGX-fm+er}nREC>yM-*)Zb;EH9o2R5mZ21MU&-59w4TT26YJXmivP z!cZJLo$~@by!Wr2VZQ~M-bz-(XY_o;i-&+?3^&zh&X!`n$Be6XJbM!QBcsI}x;#vW zcz{byZwAtUTFC>4Rp~a<8M{a0&W0Rs!0tSVqz`=-Nm5;esOmV_&J~64)a5}av|cS` zD&hDg#16j>oe&8XLS%lBlGdRjOXbqpxNR zv8rf`HiE7fCfaa<)y9nWA9IxopI!V<2AsoSvqQ3qK&g>f+n8Ts2lCd+nVyBax)dbo zQ?e>X7H#LSjc7`gSH;Vm=`4d(d-EYHPK0UNUzJF$0!E z(wWzr%Qq*;27A>k@&ZLb;%RZOB^(;tyHYdH#_>9a*oJtkj58L0nV}>uCnL$F&7YG> z+%KusJPiuMalIZRr-;1@o+>;zu3j$X?PYTPjDtEoA2ejW`CF{1t5T>2PisuUB%6Qk zcOldFCbU{^Y`c+J$!Zg4hxk&(>PeWW>r;;~@7blDMZl0QMX@Kx3<&iO)a$T z>#751{M&XvqK}J{>S-L^n3ies=`7xG@*3^&B#a9MiOze(`B&Cd$bPiyNENrP$9VaH z|8_E1INT{}+U`Ko@U~-Ggk#P)IdMTbozjF7#Nkx=uLVNFJYA!rZVHIz75K*ZB2=*Q zsUtQBkxmBpYnRv>#4_Aj%{qmSI-E1^=fTIQ6<})CNsh4Kw3S^q;joQ6FR`XD&t`fF zHdNG*+P=A3flb$r6sR$iis@H^g^=sCF6@4WLc`7D)~7r7gQB=NEY3D6$EqOYAqoRv*xgenwFLfq5Z)n(66QyrGmZ%&nb+0tPn}V<`y{W(^@Z$7m_ZRak$erG zz4~HXPz@hp>(&Q0FGek-l-*{_>M*s}+@g{Cr~)xI8Z|nKr_W+KEkzG(X42|qIE+lu ztVL7~-v{z|#sZ&s5t*zg54U7;u{GbG$hngyRuj=%f${sPhdYc*cG2A(%_n zK;-#Bru}HogFpganB#)@@dV}BP_x}&M%M%=A;5tGXIl45Y`Qc)0#aUE^K3*71L_*S zy()8W&L($T?Jtg@!kgr;rJlZ-5MAS}=4Yc9zJ}S5=P|u3*S#!_gR459;%lpoNpUKv zd~Qh85gu*pkCCwD{=+}vC$Db34+)llX;j?zM-8TFBq)hWtui$0ezyQM2aEHBR*KvE zCQAh~l$-5)+W9@bA#pIrZ1!HUtEU|P@-UBWAcMrnZ>DPz4J%@Kt!nof=$p$^x@(1j;y z`}X0UQHEZXQzCK=8zODgg+1ev8Fm$ZYi)EIi}p{_%oN&2(c!-*y(ex$e>)_5Tx~Ax zF;|T`#H|$3=Ax?F@~}AYR^lVp;(ilwrT0ypCs*cXI=FLAUa#6&VY5{He&bHgXJnfk zTo_9J)Ip5z{EZwuZ>fBLc)0_9plf!V(K)xLnK-oY_LeCtiR(H> zNo*-+j4c_C{$2jv<2+yftQvyJ=YrFOny+&R(dlfsLjrvJpc%Uny}KQ{@*jd;a!;N+ zU4baUj-DcqTl$;uhFo~|UxKQTzmFl@73sEjy?rS!$(EQ0n-aQZYOoqkisYH=x%H+3 zl5~tJX15|1NIn#mxI)exLYXs?zd~%JS>@?pP%Sm;PFlje!z&MwcY(X57zBu9gX7cF zYb_*M3hnFh=@g?=X9&&=9M~o!0`*0@HW9I$NXPSYDUkr1)$K6TmfK9?(@MMAC%A0? zF0yA7GF?vr%9}(H&@D|yem%@)rZ!8O$ly=RyDb==FZDgYGDzTSz-h8-oi3zXiT6-o zf~#6_!EH__xhL7Y&Ib#X0L$p7GSIDBU8<TF*1|k^SDNL22RYqr~k$Uv%4UG)glnB^l@`S2o!IY@J=+_R_9*1BV=f?lN3f5 zItx)R$SpJ+Rd$_+1s|4g26SBZ(*5>KOCA>TXu65&S&q~AwK}g%=w;Npv!#^J)tMaV z5=Jyfzp6(5#1_9*QQ^?qUh7?@wJhZ|1Y@g&I*T-BWTyz)u7uT?c&W=+&o}ZQeZc*&wm~tZu~o*D*%H7*I|AZ(B|WPGjgCU^Sxbz} z*ZZr<-s-1=?4>yP4!(b1y|v1kTg2Olga@LWVkB>t``GPkUEhh}f?+?ujp*WMhm{a} zKYcucs@YPxbQ@X*DZ6dA25bkLp~QmOnwgi~9|<;+SuG?)M-~@`RK7NCLMs8?WLBUV z?fFC2Do++UV+9o3l!8-ch1bdoV`meCO!iiq5R(=0YY!uXUXbku8Oq&sywuhY;L4{( zMGFjf&)SS9O}O018-@ijHK6Q-gRD= z5@i@LLF5w#?GswVjP*lXKh);1a}Z6S z(_DOV=G-UZzIIWv+g(6ldF^cAJ4nE;L6BOLGe@f6=Vh?5Kim@9&*=8deeZf}(0IH} zbb+|fk%-maRo|v*a^XpQ?`l-Nbn>dT=eOR3l#r&bK!3#9luqB+m-yA%VkA;KBXL zWyK1v^;=m{GDoH5`fRMDzZ>6rgI(gEEO)7t%Hf_f3)47=sv=~t7+>3)0fTG_A@gbp zA-gWoZ$jr3(85HEAi>&v<)t;zy_mJJyUjOun9byyECMczE zNkM;`%91nz8f$EsP(9J+PrHS(&~ru)+s>Nu>ZljVp6uw;vt%-)l+O#Flw^^bO!`B% zWL0~CbSOpRe;=q&L~lVVwWqv8Vq-K!lApUe=Q51#%+lR~PYU1&Bc+70GrF>`(~g81 zW?o1?Z@VGDb^G0RG$qcfT0+uI>dwZ;u4C#kF1xkaXOpgc1%+wEzLwXLJCblb0W=xe zk-WSTA&W(9!luQZ$**pWn^`BO_r$!rRWr_{8_x-ksA3C5;A*V}Ca5++aVr+5>`@f7 z@}XU$ZTXf$1nwY-Jt1W6WoG|fKe$3wi%yKz^$|0Bhn{8m&F#$qq}x}Xf}qw3cK0N1 zh)!BRr<&=MS}eN>#>=*FusoPNfr4UefadkAd=x4!E0EW1jD4A40}yB&!z~CDr|N-Z z!(maAar-oJeg$Zmt%8*u1)`%vlW#G-;@X&+#Q`c48BKW^wJkZ*A~7$MEeoOD-W~I4 zzc1!Cr2J%-$-}q)e6d*X5xQAC7)^}YNzo$noN)Woxr7a?AG>>KIRpxfY|{?O(XS4y zD{Da)s#_mjeQ3m@VJ0hD-d@wsKMH!deM~e&5uJiZvxAk$i)64k+*?ya-O#0+$g5|$ z=q`hVIDK}I={opHOt#80O9(M8AWF&k2$xP~8YXg+pFUNgcQIR8j@WSUGgHLHQa}Q$ z?_jq3iBp#(f44nIw?v~wfC12$bCcY2DliWGkS&r1q@s(8lqK?sQ0R}EP_qaMc7O2M zH#pp_PtAXogyHy?u*Ux>2_qyarKT?S&m@ep#Q&BRxI;j^9KnR^9U0T_~{9P9ZZ_5mIO z3km|71yaGl1bgP`bnGCIBl%6i(a+6*owN$=`o=bX6W#!PVZ#B8fPau};9cwa>)&io z;nSn<9>E2?_wM`!08gPp$tfm z_r|YV4UV3DU^f}&Pcm0GB=*rR=%V~rzd$;~x1nQD9snT_Qo!%LJb)5#fHP>9z3;@H zm1&$eERZk8d=?PU7NQM6I5UhH{1jl6PePa*5O*O!@&Ytw@*Q8`Z(T$ne*g%WNT3xV z90R+)Z(*_YTsYs#*+;QHFF;kGlP6#x5Fegzuhkqbm;k@_x6jb8_JNP2H;W?4vkhP3 zZ(vGFLN7qTj(|P@T>(gipUwbvVRU>_QV57Q*Bsx!JGQUgm2dbf*_WTyF_?DXApCoD zzfShwwZfjWmv&y5*fRWlO=m=MurQ%^UgW;Dp#MPl&GPkpUsJqX-uYU7=_!0=e|~Rs zDLy(le?~ceh`jLG#b8Y=Uc&=#&ghaq*qz|d5CMJLmSH?phb{RF>g(EkM_J_XpAabc zakYIp#?Z^Dq|l+{!3+6kex2oapZmdGLj?*wB4*X-xx)FOk>lU!p?h5P(4Ke>BI{Ic zBcSl8e9M*sffM0(56Q_3qW}mJ3it$_?B%Nw`T^j3$P&nJZ(qXh90wA~o1p<{>LT<2 z`V)VsDCMyGZR2=z_2}fnk$a}(@6)}|3Gcz*wTFE3e~-aE3FbkTY~uuMt!RA=&J5>gN?qj)uWR^U zQ24=dyNHOrndhg2(^awX4|q1|wCEPdz^Aw%NnmOYPMP@eYF>v^p?2K{Ws z4m@9koR-8=2`*%L)i!1B(Ts~7pZuRqG!yI)hg**!TETp=3U~nAX!TnaDmY4$3kpJz zIWh6AbV3`PGKt_{c<%?-TRfG@bN*(#+x>ri^sNoBd(Lzu_E;gzhLsQzEmfd(X^D^E z(CW^pqC6;*$QP2Oh+cc7nrB4qGx?DvWtAB{F1>F<0{0xLlTt`Sz)H(-`KlsFijkHa zlWT^*e#x~ANKSTkcxQEyNO&=zefHn>Itdnz9s>Sqc1TPWG~XV(GXmb{?SJb@@Tsa+ zW=Mx+OxEr)0!98N<;d=khvm!nAaU{~TG=fwvOB1Hxp4P$Z7Z9Sn2nCX%hszs08#Vl zm07=aKht@2*JnIR!(3_b{B%(R1`b@2ncp~s^M{sYTwHL;hKSMRprddJtJ=0$f!V!k zdx|mqE=PF`l6xs@SWV1&1;P-(i1I8MRN^PzBE!t?^G{WI9bVa~NWQ>a*ndCeYbOu? z&<$REw5MHlH%E!5GK$>iB79o8k=sqhqNuP+cFI_LV_6JfuC2b*``MmeHR_ddC-wCy z?m(N}wPKN|)a6^%$1IFLvZB-F%tK?uisWom-f$bcHH2=`JiCc(=BXH!%;v8QswaC0 zh51XfyIke&^7G2{*QVGW65Ceh{(kknGcF?9 z7(qYZr&A3j)-Ii=Y5jiFfa~V1=~l=6@YWzzM)J_m;FvayHRhVY>m=^81z)mv-E(H_ zr_a!i2@^(edG-D3GrN+wd`Fr-S29Nkl;A_}gFPYWke7*5UD zUUz5iZ+61Rs}Vac3ChfbLcN6iYvaHr9S)KsL=6ftvZ*PG-z@UuYCw=Jy;4PkHm7#( zYm@ya+HjJjr|uIg1sU!B8?zY#N^hV249WrUx=RA+Oh1i-$>SB4m<6(rlUkivWv22` z&|B*HVAvrY9DCxVFK@}u{(y!0Me5*u*Te??XAx}etXm!o4q_3INho-GAx;`BaAm6u zl_aQMV00e&59PI+N?khpO>37`S1b&i1DapE!~ce=U)It%c%hjPgKn;I%=H zLA{a}y@%CDqdAXh+|>w*1n%z&ru|*KH0}`|KG!h}Wh|fCtZMK7idY8(g%%cPEHv*u zqm8iLnU?e>0d6VuPK;DhKZe6nYdGHOzoFa*7BdtXZViR2jP+0^F-a6wFv=9vjQFdE zsjnNVRUe&O=Q=&*td*x|%IG7n%xn5~r2v+}vWJyLyC-Xo=7xqw*!lJuEOYO9-En5l z<~4o|UI-dEz`-Jo#)xB5B#YXNhpr2*%m5wYrD?YPdwWqNoDpWJaE0twOTvoi%w#vV zUVEdCr%b%u`sdx$$Qi9?vllf_O}2+h35DN-yqF~e%fiz|pUYJxrrB(Z6yQ3pBe{=o zPn|S_erG`p2xI50KUs-;l13-3Cm;gThZ~iRa=9Y4{Vy_4Qj*7|7i#NhhSY`jwaQLP z8>(I9L0fI~XT~-gcL;E)uwTqM-!--Q69+YsUClfxh-2hfdYpB0TPu9k>|9} z)8=no3@!4pWZ>lb=KcC!vCM_U;-HCfvESrPAm189lIY^uzMO+CJ^6yTsxuEv8J;Ck zl}G6`rG%qq<>=sK3J)R)bd5x(J3hHN_kkc*MXEJzftXk_sd9XJO@7IPHSRFaWJRbD3-V)3sjRv z``Kr*(^>>5`zbQusB-Ow()Pv}*OU)9ANL2mJZ?^FjW5hIui+JxXiP z3_)C1_I`%RyH2zpD#hx&tW1qpW= zT29tT(cEUsAFu25fX+gX|TsFoOktfyU0in2$-vd;~*&$&ww20?u=Vo1ZG zMVP=<3cR*3^C-4>UPP4HFavt1!!g8@7pLOCR zK>m^Oa?J(}R6M(SiX1GI5vkJwWP))+vD45q#n6E6#(9CwXPjI3Gu$rflzYvz4KQ-) zvxAAXm~rtkaO^F+k5E`eml{t?Js2I7QnG~bc&8mg%EUc7pI3W6=c*CB4Y6G(^`LUa z=M@naqns-0{TpT`48=Gxax}ck$7289nBtmQOd^+?E^u?TNd9O~P>LP(IcS$(Bv-Ad zz((0YUCb6~fv?xvg4e9^X(P)twilLpco9i1nU#<-))+(2l1X`P2^R}d-Ef%wLEvvV zDd3@ZL7U0}6IVFO!3Cb7ez;-Ak>0UR|I&RGa_<$t zdbec%2ErbfJ^xSbEMUdAElwn=k1w5=K!dY=|7O1PW61qmsQWfzfFR)t>CtK}*%-qr zllENZ%SscVhZZ%(+(tBaScfx-wuWjTRj?yX!+y=Qg; zqSAAl&YFoSL!$$fVG9&#oWTB#Mxx>PxL<@x51jSE3~KK#dvRV+;6fg^8wBRdGFdI+s%*ayav0{RMXh8`wT@R0-g+ zNn_{(=%Fz+NfWC6LP?*KtiP-Gv>~R6Ou;M*}60_urYi#Vp2Mf0{~AWd7n?G z(Cc1-?sGGWzNuZ{OSbJ*hM`86f+yHuUB^|zgVB~L!Ax|njC?Y&VV=#^ZtgtDu=F>I zt%#O9>bcw?G&Z5#ymXx{1AHc7M7*(c_hm730Mg<2bErS2tS5z}_H4|FzRJp*OA5!p zFD%L(Ol_a)-XG0MFj3Dp?^8#koq252C|t_2##Yq-DA@5xWr>QSYXhfD!l3es628lh zPh&Hv;d3HIZsP5_wyZsz14d;&$JJ(44y@Bbi>O*rHNEX^gv23cj{?JHK4jSY3eRqY zb2fiv@#LL=KM_nm6_1i!;yHlD2&AX+`Y30|N?ooOnGuiBkGA}hKJ5C`CHdI8tb9CP z@Jgg50LF|iSL^BfJ2$^>-Ef|b;;K1K<67BXgHnn?l_#9h=NLOV+kC1L4oz4}08jDm zHMTuqIN6(~+X@(7a3cpAcB+2x<^o}TVRde%s|j>+Gx&(XP}wXd=T(<&AF>${qaRO> zU;LQ_9L9_Un_9po7Y7|Kd!Rc$kJ~^#|8X-ThwH}MATkEBa%cxdU)t@+0ajV;TE23u za2Q%)$}}LySW^h2DUp>2+CA28$B^>o}?6BEoN27-ax$x%! zRkTwk)k()2GqKaF=e-vRlvJ8GUp-C$d{tQZIn~A9H`fgHdoQ`_VT)Ii=h331&q4xb zs%Mm(Dz)Ig7tA0ZUBSHBZ2r>o=P4P&!**iCM6EltL^ZVW70Hk>4;_E_%S?OY9i35G zMayndgR9wmjm(c3_dN<0Vr+8P)kmr;Ff|x5PuZcYDP1G#PG%b5g<4?5tt8R~wH`Qh zm#OFJ=@1gR!f9J0YVlVzl%AjMyUPz0##wUy-G!73y0EQA0nex>_UWDLbPnn+d3E+l zvVA|nqJ0`2LyyPoJDZ4}YrjIw7Ohg?ay|0{!DzfMk;rEa;%Yjr4OH`Zw>w?eXAA7( z1Rv6sYb454cxRZx5rXbrY_41M35a3G$XG_qf3PNPX8LOfmHXaapFB*1zBhZPJ*Vv; zbDlm?Oi}9P>GR6^COg{DHgEWApMUHbH@8!dEfzK5FZg34=V(+2aP}**IE9M`gq+nR zxT)CkI;U%_?giBNm9D(x)h?F{>PsE&EI_@XW21}0$nwf{W|EOPv5pw?uLAivQ>+9A zw&uQhxo96=CYx6U=9ce8R?@Sm`+ktENqZM6H^_}>&FMOIMcYpg#VKNrPVNH{i{hB> z1WKd^P1%rpLh{7zB;rt4V`+|T9EE8wIonM?9)l8D&j)GV^p`_wy!x=~75f|OlHB^p zunDu$x?z*drTfDMaCcp#bu@M&T#o#)xwvt^qBM{@73+66-rT4B^ceA*Hx}CUpJ>IP zbOws7v&yuV)t=DWU)UKR$EI98C*D!Aare>E0^Mb?(M(hL{;6H2FQbBq{*Mu<_<>_} zrD^yej`xfQ-NMtIbN;QrF^yJ5!P;`j*FeE?Sg(_Gd%Erc7N;QUaCRt^E>!7YvbiH< z<&)-BqbuQU&HK12N2bP_Y~K?HW{>H=izHe-zHaU}Xjwy_B1{N#{>)_5yGDM8DSZrd zmRg5hs+}(0rfawk7E#d1B~nk_(6hy13TkbgKUO42-O+bTwln62E4EFuTpJalK83(4 zv71ZLy%oeKwhvs}7m<&rROAxSwGyA_w6ba?i{LsdoaH!R7vzNxTR>jd)wOYoHjcOz z=MYmb*{@(@^QtZ{5@-lU$Nba_*1)mC!3 z)MI~(P2ux{)k>}LFwnwB{b}DuHxTJp{S$+6qQ|#A;xxA^uOYWFerhiN z!EZ0)%!9$tLHsKS;$@da4G(eMDGZwv#l|r2WhP6kL`GY=j~-nPYcyeRi8@{9(E}DM zeijPaEjGg-A?_)>77tn2u#-=Ut3bJ)WY6On-h@L9n)Id0Q2N*s-7wt3o@-W^G`*!- zvtZ~=g(>gb&gg`>`t8AjP?AW5uF5v1(jkz|@bw*2K>EF)T3jVW>T#yP66ch>%V?D| zkiTUf4mG4VG6xnFfaOo9BzRmdhFzAz2`#Y3nRf~>E3b2Sj?;=Ee5emK2?O@J<(^$p zjPtqYC5x2FXK2-@zEwAoD~{Lx!-Xt;`4udy3mD4)Jz(Xi4vzrnej9ug4+;-KniqQCluh z=8ZCP{HczV2CkVxs-hLv8J_xYLw_R+b*BJ^)voTS+I5_P`cx6)c8aHmFboIqWt+DQ zoMqHjQhb0|Wo1OKc#x?H@sy6xS?bRYiv>#&(*Wl<(!`%Wpzj)eb{3?`tRG{Np*0xE z=tr`MExX0lSe&Ef<5*Od7cEgJ{sMl|w6 z*$d?CbdhMK1Kln#6>Iml;!MS)64b9*x+#h`CR&-oRA%Dv_i-4NBa!#Xt?&FxZbM3u(ZpJ zuY=$f7sXF0M`fb5A_7NllF6Z#1M{`kZ1lXaOrD7fwr=rUltzWjlZWyf%FRifi%~f=l6Zi?W?s- z{=7;YyhMSW`TZtE=#r6jlMk9IH%jKiCpeR((<((yBX|`1$gHy4$7;z6<5_Ql+lVf7 zRW=c*bdZJmcQy&GF&}37NGB;c;TlNDHp^X0uW5~f@CR{+P)e$nNRTRIOxbQT*ROAg znbTZV`FI+^=C&crg;!S6r4H4P+It zmw_jXO2J)KC4`B`g0|iM#&=z1@u5h&k3DcfblM=1PBKS=GK{DUAM+5VvMV79^}|h?9g=dsX{;%c|%r@94SB*EF8x ztzpw`z1LkppFBRBK5ZpcMX#HJ&}g(zCg&m)6ii%$^&I z<~wX*_2LaTC}GqG%NQ{{U8bZ$jzWr&jKtj~(N?9qT0R*Chr{H}ZrdiA!N(Z8rXvS} zK$bxPL}&c@T??I1JaL{IMT?=azO0<_pm3>p6#&E+iQ^4u%xvaFcAQv;zEMg*N;l7(NVGjoe`Zzs%LsmS*abD__H5_Am+UnvV> zdQ_$wvry}J#LR33eOeMSM;hlRCL7%*=bgg zrIj6R>g1FDI?I2fQRn)nK!p=NgIkm-&m>#zGP7NH$NG3zY;FEj zmEjzmJ2DSqJ*lly>66{9?)tJ1Lk;O^x+m2dc6qT@-Uf4QI>zcHdForhNWPQ1agvP@ zrOufV308rM&m{4Ul35OW=?<}QI%I>L2^wb?U>CJGMuan%r{?E2sIb*JD%Zio8r_r^ z@ogbJe|xzXtvW<0;H)`I{E-340aoej_O8}_#e)#8!~P!?f zhob*)gZ)3P^9JUorvGA||Ht@mx#)kSp#PqWGXBe^|Cx)jGqV5RB=ko!&%j9kPlW$p zgHZ-XCKk5;NJjrZH1jP#n)!27T4{TVAqv^qy}rEG4lWTOU~p98p}bb)hz_pC){YLe zlAp^&Me^#DtA?31p5t%RtE@@l?FO%|bM@Lf6%Y@EpEA6Z!RJ zBJ|$AvEWVUUIEy9)-nxZ9{|XM_Eq*h$ze*kI)Tst5bt#Khvn;h(_VyQ2#xT|_(rbpQp* z26lmWtPPy_Goc9vRm-$P!Nvbu2O{?j+~p;uZoUUv4Zs%<)-N!6pKtf;=?e#Z?>g@4eoH`$F2rQP2i&ES006kHHkC)3xGrIgB5tKjX&o@pc+36XY^uhr{+IA^UeS# zWdl9$jts6L?EPA+TKFzKp1@zQ_fC`Zu&4?0o}RTplOUh2-iq+1wXX|po&evt)m1=? zQ+?;#qlkNY`mY@@ku5R&)?i@^nzfya+pKbg557h!dgy+kSvj$hIbZ-TzkV>aD*qlN zGk5lYZ$*a>RKCZZ{X=kPU^U(*z$bsTfE=IME-n6QJ%Gtqn$?kWxglR7Cs^n2LKE zlfEq6vs21?4ZI3;p57*}0hqZz1eoMKuaocD!f6%zz zzfZDVW;UKq9qirH*LsxjQ%XdFK3TT5(LWk3zO_Re134D=o@E{GZhrAkPvgTqkV$eA z;QFDBEZk}MZGP`@1B@O41oN~3WP3aTstIPz`NE|?vjC8PYCfRt?f(Ke{0@9+1LUvz z&Ry{Wz(2togab(b49w0?{RX@J5S8orh<&`4^+)~gE$Kzo<66xD#RkBCfg6PY(D(w( zIjesIx&!cw>+}M|dl>w)=#KMiVe~ig2-%t7H~FXQ z<@C=&MXfI&_niE;Re!C@Z~7e&0R5kv8rwgsBOKqs9C%TVzreg8k8jaFYSJ=#oPX-s zhIA+1gu{IIduWa6S8=RjzKn4#Xwi*+BQ3fplgOS8w=)q0Ib}K&jf`{}bE9epv-&E5 z^=lv=6`SzSo@m*k`k1GEiuQ#^YRI`UX(XA8*_>|sbgGkbfrG{8eaLR%2uInkE6>QoN_okkVS)G;DYUFDr7*1-jaSsRDnYZ_{E>O9>&4+s z%^@TAz%hS(P}D>A-O&1)ZSS+wzkID4A-ye~<&yoclvC2FeQrC37^!UhmMLuxeem2B z6Xv}+2Ajnsij8-ir9*OXp^;DvC<%&rpTE?;t>KI0zxyZtyc1ljiiHAyCj2%I8UWi6 zpNam9a@`oPkzokCW0&P_;apf)lJR*I>{|3*96z7S(>PnQ(J+;LY-R{ZMu|uXkURP2 zHv7tZ0)(I`#qRui=c2pHA%fu*1)>!$DSJAV#<%+d&<{{_zrlN)fQ zb{zg75zQ}e+P)CsN?(Hqq;mi@u^%ojRbQU-tEG$mef1|C8t`I5`ifHpbHvr3P~BKz z&*+P5;rcTUp{qPpTj{NKn~af94|KB>`s;Z=pJ;uMZ92Vy2;HKsDqBN-_`@XWkVb?Y*GH>(?d*_))hrqQ_AIU`9ZoH`LKbtZ;(xIFV*cv>T1 z%cnpS?uGy-E?dA|Ig2stzfHeavIB=}qGcWa!0FYEYmmChT^FtjYlCa##TXuykz}Tss%<-; zTe6E`=V2(eU=;0w<6IFEB||whv4JLvYRsc;vYKNGU3>dawxH|wAmRedE7q!BzVvvU zRSj}1XBwB7jw_sMRljI5%d@;dXxJSeTA~FsMeEXr!STJ!KN}&qY=a zJ`Og5bW+RbsJot{0dl~k-d@>x#r2qH%MTXAp@R5kcSNDUa@AVdz`vOnxS_EKS*{zo z)`^-rn8;ZMWxaW1G||zU9v9Jwn?K-;jXOsy7h;C4nEG-fdWB}*l(tc)kUT(axck#Adij*d*5<-YVCB$mY?c8Jm&5xA z%S2;z3CE_i3S!VYXR?Nu4_jyW)2upa&lEH_fF{TRZ4rKz(O_O+(T)77CNB!n;XFb zTI<+-dm!_Y;)q>wz~H`J-!U9fvm(u`=Y4+Q7J zC%mz@`~Vx&eDJ`h1cTq+vDdu+`r@6WUnEl^%QjGAQ2N}Mq_{#K2(b*?z1l)yb~e#C z^inS9)u+uHIO(0`(X7*PXGS!gXk)>GQ~p)f4jP?zlCe|jo5WenY8+Qsu(s8jx}#h} zykU96+Z6>U1njY;ed9do9Df2l2WHy(EJk5XLu!iBN6x;GTwdC4nX}s>RWG%r(@>)` z>{AOetURlFm&u2hP1{zTqbYn}W1_7(zv6yBcEQ!6liY{?zRrLph;XXDj@g4r+4V(R zlo}IKvC*e?c~BntVD0Bnx*45}y%sm{5Gdw>r{<}*b309&%>M=>CnF(hA3~I z_~x9l*s$iSTok|?Pb}afn;}%m8wB%$sbgm+`L)(p7-jm)S|K#&iBKK^x6h_8VP(^t zC=`1NsB3ttgp*$uR&7GqwZSUc3`^I&ME4TV`Flg}_bt&HPmgE=4@lo^LH68kk(pHT zw2q%35W^4)Bhw*#84Wr6h~KQE@g!r>UpO}RKE-VFrQQTJbRCS8ILnau>dON|5SPw{ zk_b>`&_Y?EWj3YwL1gt%$gUHID5L2!G=|56Gj6ok>&CFjL@z%=B<|+c?Qq)QrOi7f zycclyt9~S>*aP9LW)4nhfoHy|#tU32B?qGE4|Nqv!g4aT=&Mp><0uEQZ<>nYVGm zl}TEzTcsX;5r;|(L|dGw+ieHJWM=1qCp6Cq+>IZAe-AOBmMUkJ7C7-u?dMgTT%NLh zT5`RXJSzf07xjwv8}O-#wf5gbtth4}cLvz5R}099eGXu!oOW4G2Nnc6<~}(Z<7~>E zqFHUq-Gv7IJ|K-s zvsLt+O82WP(lzU+hiaN~?~awSi4Xzie|N71+e|7P<{J9F#n#zztx7@oUFi=gAHhCe zi*2`km}npliS9UBrk*~d7Ee+eudSO z)3XXiefw-B_cz?7n!lfOHMN)~@g*n^7|sjtUM5!};0Bw%r}9KeLZPCoozZUwmIMf*=nvqC8x%z zoIRrh-o-BZif%QE9YIpxGK&lTsY~O9(^a$5b3)lKpPJ{MH0j#rx79aFnQ(6|%JV+# zB$O*A+9n-ty~ZkO+mPJbjHyAL@HX_GPKOk4qevKmAx>h&E@%l)q}zdF2Tf32%c4sr zQYe}e_Bdg~wzJ_O#yr{{y}8+~nT=#1jj7IeSQaNMSDd*T%{TnT3-$n!`uR?`MS5x*%@bz;C5Q!iF*4k|B z!K=pFs{6|H51ys?raiYAUeRJ_xC*Qyt&`o2cfaN->FQ4##p5gOrpl>OSx@4BnY!RM z(AF%EpW&}1TL|6RQpnn@!9}I!-p1YC$otLX&ED^2$O8{ce>Rxk-^ko`Q^onHIT4?9{j5KWc^F0QMC-Hnt6&U zo2L)A_Y`78=hFg9Q{jcSDInMlu(`yGj3fp7yR>0#+-5{Hf7k*6MFEcKh@B@)g^uZV zOh>Pc8aO+P;1p9Oy~U41AQg16MZ!2>c63WpM7iB9|0>pYf~2QK2nyf@^OrT**}A4>`9RLZix=L+P% z&@eqa_pWUv&apjO@M8_paOFW&#J)#E%da&NI@dU~Zu#Io^b8TUj!)hma4C^B&|v*n z^d7#Kw~{^wf0`mJWZQ5_QF_~x;eBL0V;mUW#Dz1a7e}!?eVB|cqnu??!bBlxkv6cr zciF1eXH*P!Jt^LMX|w7%{6SS~Nr!Kn@@@jT3eUQx$x4pv3}upvAP!gWW40?Hm9pF1 z(W_>#Oe$OLIM=@2;HL~UsgYdYFhuJ7nanS;b1aa`d+yt6qox+Frhpnu3C=uM54-ZIS^}S>!JIKb9np9`5BfURlJH*RJOj6Q+jt* zh^J@E>P~!6ac{51B_l;I>k%NH@LrED0lKyp)nsWNA%`i=0NbYTL%+CD#36>a=ksjqve^^S(6S2+{P|;>C7%~MX=QVQBih8-&s@K$hy!yD+_2-_>>;m(M!aVOcwSJ-p@wzf+ zQ#6yDBVsP1QgG}AUeH|#-5fo3Z%ze42G6tzrN?|ifn>r%fQ3}@Agi9^8UY7C;5G1p zZNENw@C~Bxfkx{Ak0CN{^m5dkljxfpGu5mRP#OB2p59;VqgJ z2MeWe8|_2f>Jvk?xv81%-5tJ!3m2lAK_=2gPUqENf#?@)bWR*rsq~fh(yGKC8mn@@`#FL&5N4Y{t z0rs1x_pr^zwH*>hu4Sx>mQE`kv^A6#rO|`)tUYG6X0t6g6ot!hc6COe3Z}S<5W1WS7tWE= zW_y!_{IL>SHc{+%#aL>GUGVUuSj;=~)8oZ)WryNZEX1^;J?8|=KEkamNC3j3up!ry z0l(<-^?wtiU!jNhOs9>2r@dgt9FodZF9uJCv1@57eWn97WiQdLPu~)2p0sTckBKOQ zX{?@c-d(c0n@K~#C|b1}g6Gtkw1yCDjmhr4E1j}^-!RK%@l<3Q83*;|te#KSFeOqH zkyxK=h>ky#j|pn?~iNKEf*3MsM_4U#MRKL$N8DKbZsg<_+!Xy zMDsJ?eb(dftKeq%C(}*6CvC{Ca43PNz3)o84+ag2Q&BHHD@Rz8yjGRAgSAhI-W*p3 zOa-}aqEl>DDj!L%h6$KDYlN|{@o{^H+S%yN*>X>-<`7x4VPcV zLX{Xd;KiAVS)Z|4ann*}yCN)H*aKB%9c9R}OOqNC#-I_xc1xesnD5Z?jJ}^n8b@MR zYE{&*R0#2-`K0}F3F=1U(?f92ZQVJ`Qe?^?_uQmB-*`$WE<12+1>hyCRnY*{uZvSB z2q_?{EVj39hb%6tu)q{#{rr<5vy`>WGyRD*EwPxSgJdteR*KS-Pu)ER_oPAj?S7JG z8gH{RQ>PHti(hYpbx&bXZ(yx?{G&AAqzN1hI-D(Ph+t*?RCdbhfK$ zd>vJeka;CeN#oP$o2+Ygoy7rt7&4>GMy^bX7vA0hM1##bm(6Xm>Aw5Ab$NBNF9%+) zna3T2y0&+%e$FoJVFFinD0$s-E4v*HIe@Nv7b2!;%sA165hZ6eL4j64+uZpxJ)21r zj`Pl{aa$wowcicEN*`0Nzp;YKEVgIis%w~KZqU`-L68dB+!Fsf)l&q!Rgi0rj$vryn7spJ@2z7Y>m%DN~u{n zra4czgh7-+wJ?b`ARiZ^)e)fIA>D(RlfaGDU9-ex{fi_Oan6fiaNp;FnLO}Y^({g! z+y&rbiZ&=iBVNdVENv}Uz$vmZEq<|}PgN|$WyKuXHJjGE&-2N%ppZI?A&v0Hm+D0j zb+4s6z;_|zwGVbCuo)jo#S@x|{zk~?~HS@xT7dvoA9#&}L zL{D)7xb3ObAwWmk1_!wXT


zQXx1an)drJiJ$L1HH-FzD`xD9!ydv2=Gp zcIdn9j>h?|xKidbNWziE4VP`*=n2;@w!{8~STM3GFn@nVI7+XG!69J9=%*f*5UoFS za-XJ&A7eRtqX-RjS>T)>I#}PA^3j^0TGoQ|{9wn^+CqZ6P2HWrSh@VTn!YA|1~`hLi>(g zjyq0;JW)W2+FPb$eLsc1e0cvvvTB-UFk-k(`|ye$WS*-uK%=!QH~s9=Zr(>eLM0Yz zC2}`h)oLrmQ%tjjs{iZoT5TNc%Ai2R0+I7cl&d=Sw(Uo(eI+i2BTrp_xRdPhL_gNh z=x$Rl`YY7np4USCk%FBL9mAtSE`%)G^I-?}_chq)Wh;oLETNE@N&0-1ge5VQH*N$8 z{L6k3SOEPo`95>B^xKpznXaV5z}!`c)LQ-@#9I}LQDty&#nxAlc)H0+*gi*<-%UqM zvR-@FI%_BLHu)L2yYf_d*zp_ogmGlq_}0|;POXd+3T87|0xo^y*J*_2?DJK z^|IcJt!+r27X3u6o|1?2iU5%t85pBk$^D{*n(H$vre*7d^y&;5-7DP+AIMUk3!HWC z31~=B*K!YArjL!8*s&j9OM98wynV*_odgXWn-cT)2e&Y{T3<8Dg+vsC6IWj(e_z@@NKKiy+&K za~A(@YoojZ1zu**_<9PV{+u7xxD~gsW;;sotM;oa0Uk3ary#bvr4aFqG?+~nVKp}u zxN5w#TUa^Z3h2Rp;b1(LW||V-Mp5L2j{c#a=p!m_&YAbBt$H^RH2;h;>QGLatLx$g zmuc-e+{1PNA|_&dK3J(a^X)E-Vhr6oP0&jRP)ZTRNV}EOaJHxdfpi~hqE)SG;ZMS# z_oxOO@5wm@B~cXlwza6Qque51p7y$6x>**6{gMvY@5Nnf*D+hTjy^1fnqwS{ed1w;b#VJoP_(Mqr4;(O9&U> z>oz9aV5Yye`N#_Th~2{?%_Z^FDZMg?tBlo8dlqgjwy{XA^5Zwi)zI{k$}*iNOwRd8 z%=f$ulOXAvEwWc>L)kfj;Wa)b%ckP+^On1ES%{j*Hr-bB&i%?W2BaE0N_e4X) z`!TG;+pb-XufD5Ai-_f^Eb^qm;vcM_K#pWI%oex zE{_&63!sn|l}ggs20_#Qjxb{yx4Wh39lN%j;@f!j0#QvwJ_8&>CQPO)s$IwC?Lrnr z!p@(6MU)+y$~--%P|NRN+ZCxE3)>cx#z90e5FdP0TdSehm1e;WMhR=KA+PM$ulXw2 zz_+YuPaCa<=85fx{&IA5mLX%2P8{J)sP3pc6kBM>d3n>I6KA+$E{^D`0oIgKBD&2y zkc7%?glx{13Nsv;q6f>A^VKk81i!h1dB`;akMsnpDQJ=78WKg_^7EWSb_!-#a$krY zu5B0$tC5FhS}B`1e@#sm5g(WK#x!y7n1!@OSV_!OsR-T{U}b*~B+{+H9i%e?ZK<7&DTh&wkAIbK7@%eiq*@HcnU z64~AhBboiWATJxZ)UEu-{LExrs(zNsAPi@!Bfj5(;BZ38*38y5)ZWh?KL=U#VDBFD zMrhnu^-GMCZxpA%j}t)xCuYO3-B_~;Yj=OpP4jGssX7KNX~b1hke+~p53MzZDC3&% zrBF&kz>)_Y&CL{CC8g5!h@c>t_H{|k{1c}6-LcAa2#=M<%~s*S%33XaHPLqEF#kX< zfy;HqZJ@kvLi#6^VcRkthmI3eU_`K%m_dRdCm!`Q7sYfYoM`1>@6G3BO5qiKdPzTMUJNbL7Jp8f8^vOPq7Zo2QNcTBhnZS zg#i4Yy;;>Fs7MH#m`MmQU3_avVx%U5__6#hg#l}H?`iSnK>36tv+HO!o|rMvTAge9 z7y~r8k;wAZvr%)DfLU`Vg+%@i98k!|*-m8Gj3w@8EBJ&AjoLW>PSD@oiZ6ri%h?w3s*CVtz9ACD{9q;fEX{+Vnv&Gv)gXO`#z-bl}O zC?X5Rt9lJe+_6PCisZK!?;fyz9-syigFG_t{Ka|VBFnU+%a!F10vFaf% zB$XD-V5bp~@{qdcNK}433wm~pzgwmY6n`a=V6Ha#D`Bf-Xc^!8VA*^gRe?>nrsAx# z`Q~2k3;^~5hEjhYRMeE@Cd?X`4DK;=KMwCn%vUr>RMrGN*!z|jQoP_a*pbj+!Gj>? zBe=TAR9HS2CM^*#Gu}#Xm%NL<@7UHL*aV-~s5Y?IaV?E7VV!cJ5 zp?%o=F{e>d?Bs?7_F1uNTc@JUL|W8%B-_)Qs9QIh8ArLaM2)(zPk*p(CyAGxwWcmx ze^J>(U#Z&il6cO4aV;_QbMUU+W9ghpfOw7d%#5R1Az^?{8-fpc7G+5eFyS~A%Z)Tr zM{E5!WVGdL<PS%P$o-X9mM2*-qo?&7u6zUWD0gr{pPt=aztww zzlxKWb|gcq6GTVHF-=U=YQ-7TOt=vg2Cl*C>wdXqu;RtI*9}uS+wOs2Hq0K&1#Z}E z7%K~hUa=f6mF#^RTSwk8!|As0T-8mv?wBf;NE0TH=I$5jMA7|SSVui3)N(>^xiX}M z+I0)zanZ~s%i}e2l6pi$0wCOyzHrP^f>!TRE}(Q#KIzK11mXGKH5`Nio9t-CW>rlH zU~ivC!h&SmTWWV=5{)Kuk4`0zzuCNk60XwT&HbY!MbkrxW?JB|VKma&%Yxk909^+K zOOac>b|c>8c*8ZW4rb;W^utWi$d^}dpizsc)0PGw~Zm3toe$%n@w%}iPdaIGm_Hxa$+vfVGT-l zC~Jkk>Pc4_Y*T6ehJXrt=~6nr5}o|EqvUmj`VLkqes?J_1+csoH~y`4ybOdjl#+RW!HMha9UmQ_%yLOS9+}F(}un~+eb&ajwyn*ZT=T0u`5kcsZaic9yEc_ED2k8ktb%~beCtY{ zp>wryDA00Sawn!DS?&@>XzoDF13?)qduTIKK$X?H$e5B|;l~Bp=*@8aM35Mz>*5oe zh)yH#F=0e#8)Cz2WeL!gbtRZ+Bw{eHi^2Qt3oP7PUiO`wq(F%gMi|8BFB}Wqx~`Gc z%4!(IsrHl=7O4$d^O=Jy4srpyRZ(H4sEPgzS0c36TgC_+X5UIKYTPa+Q<)0tn>FJhsOltUG@_4-M!aG8#oV-k9R(f;e zO+ zJQZ}g?sq1kau-WbSVMRs=|1`MlAcz$l0(go$g=1%FnUevVq6I%<~m=xIQAPK{tA&#CvPI9*l3iTwja63(uDH@D6UsY%1%h8YP?QN;* z>fV8ac7Y5hAW$!N!6zGXsp5EQwZc`_HkGAkzetxiIalqQ4}^LR zSy7TEO$?$7+9KjqNlg>ZIfCPV1@UzjT)jaJ*};ZlKSWYCZ$c!gyS%9-nlQgT6!+PWf0gNxioC?5HCgi;cu0d+0<~ zm}k=xb2CeFp_E%#gkadEcCU^*LKX}g=Yh?!FP>o^=o$QIJ`HY3wx%OTwpKgjHK5p} z`+-T+1ZZr@j+_N@nU@Lt`X4{)v`zC@5)X3KER{EV)V=a>I_&1>`AS`l=H)m$|A$p2h7%kQJJOwiA z3H+b8ZY@fPb9#Lxp) z&@7wPcn1uZ^*HG`mjV`}|Hjxx;l(1AtxO6nT2ch22>bRnGoCHB{KiYG(VeoB`M0#K3<6bLgWLg&{yj8h=X&F=*SFJ6T9Phh>{_*4vBfNCo# z40$Z`a%zslK5IAPq50{hYGtXYUOMepD_na?c#q7B7n78pP^dhT-WSGveTb$J-Nlmb zKct|G(W_|rKuf?0cs3h?I2&VJSE-{Dc58)?&`i4fOofWgN6(9ElnF)=2-WfXYgcCf zem@Z#FLeZ=_f)&SX>=2u*E<%+l+!_}(yTu5>rWv=PsAX6a6a+o9an`y7W`(4^GXA; z(&$!AN{=G@kBq46mz#*@5u^o|l^Ti9U|34OsKfNW8rjJ8RUCx&aw^Yc!cW!D7DAkg zHFfE0`lE?qQ%~3RrRX#lu5vB=U-l7W|6atzVGz}h*vBq2iH)1L{&xjAu`w~e$(Auw zY-6MnV9To_cAW93D?`%bd`A$rQAj6`PVF&O=;!-};s$ z$hV3eXd{=D^ziWbr9W-M54|iaqJ+H@-oFNPMYtKK21oqs28x~^?*KnRDY*BXuZEw*6`56r$-*A)l=sP9|i zS@oetnEc^d4;?$k-o-z!OTmoGk7gVKq7`NiXs^?54*(tWb^_t(AcSCefLo88EEQ&M z*Y%hlKzIrOfauo;R5liNq(fgD;HJE655DA=q)?|Z4YMH7{za7V{)U;)V@Y^F;qIX2 zbMgn1x)}2?(&c-KUZfzAm9Ia4Ylk>yfkO3_IL=g$Rv2Zvuak>7Hb1J9jLsV-x}OsW ze%H=ZLeD&wdk4NRmTyHk_=lG^JuQGHA$TF)II6@)!L4(kJ3b(LCD;7SvoF>c&79wl zqY*L&Xchlb-Yng>9%)H@osZG}MJ*An_m}ViE;_*5s_f!jR|A7J0xtG<@kz4E?~pl@V(uzyj3 z00O`C@O8Gf*}1>+gGY6#h#+5FA-tjEC&c|m`4(G%#{zZ+;ar_pvTWti%Qg8S3ve4-3MVtQYoyUqSVM zc$;$dBZiOeLl6QGp7a6GgibzMN$tZ|_ai<_i8<1B-@Q_!uDh}2gpd59`POkKo`-@c zNy{GWO%lW|7fgrCsj&Buq=uu+S(oKv{*!?2_2vh;QpIA?l&Y7S#o`zVkaqP;2$#L_ zw4wv|$jj|{^Z7T6ZFI|IH!z*iRLlyg&D}BYsayUv;7XFjn@57z0>v>DJ#}~C!Y_L?Hk>e?Cbzkv{nYv4g47=+X z2kVPrqOn`K&v26Fc$FA4M0QdNs>hp$DV?i*ix}vc2QZBouE6c16yv>?&hCvh2_9gM=0-{Ofy{=ws50czD7FF=KIm_s&xHA zAq|iXtzTy8p_xXL*9NU;5MXn-%w~bVle!$*bFK=TLMSoUp)|iHNp4u_H%06nXY{O2 z_DHFPSpm6p#BLL54*XA%=F8as9I*w7RsB(-|Dbpuf`88Pz!k%FP*y3r%g3p>o~Lj+ z_NDKDJ)GBou8DWopm*XX=B70aima#L4hTS(=tYm zhqEiBa=WPGy`AnAl8IcY1>6|mE!w3@Wc+TjIjE8r7kL*S;2kHU|y94Ao%?r!Wn+KJf9y(WBsySuR->{|V5XD&a#JuYUfdLA1m{of2mti_-_ju{4ZQ(H60z#h-GA z$+&6p>s9tkHxWM6sp(|ofF`AvxEWoWm>3(!Q7Ln7*d*~A_-NT*@U|?D1u{7R z(_T4)H-B4>b7j+Ux;_jL#q*vD$xNy$IuJHdJq@Ae@Aj1lGga+j^iNe0SynYE?hT{} z9*aqTYKnyqqEp!=&rZq*Psoryu~FK!F4q{}0X=60o~q`o*{05!C?F0)M!oeb&M5{( z&kZM&1l60j!yv`!C12gCC~94-+nutw(6T75G19ha&jwhm>=mFVX9@V-Ji{N_MgRE9 zXTYq`6mg9%3i7>yt@dW%@mE5KA-4hbYJ@A|K%Vyvm2aH_v2lDB{zVDSXvKe#W}rZF z{2MO#U`k8;t6?8h;uiE#wVDD|L>pu8qO4ig@SAD!Jf=jadq!h%|EYo2zp-yUM-FvN2@hC8nnA@zu~jln z3FnFtZUBc{2(%e8K>Rv2V>50uCcpKLuL$$x0Y#HA%C!Za-sdw%Ej}wm= z@~itdxFvq_o>Mf1VbXz5Qfg+_OWeU!i#vu_ij^jS6lW8ed!Ri;ve=HTbO0NYS+w{D zL)-31!vq}Rh8qVZcP-su!SV|Fb?nbZ^s0u`SqY#y#ywESsx6|bYB-vZSEy)}GkQvd zMBnWx|8#}>aC~|U@?j=?;^?lc+RTq6o*+Ua90zP6V&@Z|uiSVg+t>>2PP@#`l6FtG zhrO=8=NgxgKkNk*NklI;hvl~59y594yq4rBok^2Da;mG^c^7)ZQklp4TExzV$M{a} z+9ed7kLx9`sijPit*&joj{Vi@akYvoOUo@;?XHq?B-gMe=GD5esCN%&x$JHWVb=LV zWRjY_k|MYv3(~EK&Wh&V`FI5}L)LAi_8Ey5^vVjn-m^S&t4@wPyW3OSki})Tj_NQN zS-M7T(VB=Nnr?9TWTMvW%ePzQQxxgB5K{?QIO@fXZCQAAEPzd}{4{2RLw%%t-gnu- zz^cg@Z6VtmaUDum& z?QCKKOs}AQf|NS#>0MyXnLc0=&!qzBXjFzuc=#Y`D%vvQ5oG>5c4T*P+EI|@$j=kyb%9nXr^xouw}MsKZLI4N_elKQ zWLVI@QojF^69)zJOR>BwJBCj}kODsMB7Ga(A#W7Y_QihoqRqZnrFX+*&MXz4(3aX- z^8~CweVV6jafXVS?6T>eVMA~;kO>T=i>Tz&qdp*$@1jW%Tg_O9?uM-nOP7WlMYPlW z?`6aO@67qDyv*-BM0RDK*&Md)lW;xzf;f@(N+tMMlt&l1WCN zNn*)Y$rj&(OQx7ph$Y1y@zk>IQ;lR( z6bl`A)}69Xl`+~SXA?iF)JsN`3R^WA)P`FNxu5y5DeG&#{_{W_&y!2~Q*~FLkW0+I zTSN!l-Qi|hv&v?{2_+(Phc+8YXMQ3FjH?eihp%>b1CeWK1BwoLGuILe#)M)f-n5-# zU#+29*yVdzIt;xX<1U0R2MVxDJDn?)m9Pj`kRJP>il$^n+hR<4h1QE*(>aKH`locH zYmb}O{pNL4js+jhUR%T^ydi`%1GeaO5^4G(r`I)--zjH@XJC$`bVZF$H#VB1d{;t8rVK)VVXi}67RqG=xsi2eOg zCKQ4()6~Nx+G2!3AoG5(QlqR;d#Kfc=Q*w6j3n;^; z&B2`?x(ISoKT^q${6jlN!2`RM%F14IbM@QxSwvZ`9 zn*JNB&*O(|^%cbbVeOrQYzw0`%d~aUwr$(aJZamujgz)*+qP}nw%vKFyQ*(R+={A) zdYutF*1sP1+OgO8<~LrA@Uu69mx%3xSFpYfs>wnm4e9z%%$mZT{{vzjUz_Po? zI}K(Ktvd^}7A-xBO!cD~DaTPwoGD=j?2T452>I41TrabC(0nwrvhX<}o#klFJJm$G zXnQwit=Yfo=wdj>8(zbT&CHCgj*V8+jzbn7Y(s_QQ#n*Zx117?llEcJnbaV`kq%bb z&Q}h5R^j&uTkVQCMuA;CQQDXgCOL43YFI3`7euJCnj2$h2i?hIDss$!>^oX$7r!*= z^}|YDg+pG37iGD`APXvXc~K*{o6CRX-hZ z2vwC-l=&E%KEQW@ineK6h<_KMm_A=NX2=)K!6U?@ zB98_?F#@lOcA3Z!Ax^vEm`Lk7^jL?%C|xYN?TPUc!F{S zs$g*-Q}MFSeUyk*%>ql#N`b7C^gd}Q53zcUO@_68iDNOIiu5Ef01Q4^JM1y?v7xrL zB_K z$GhDTh{sB#E~$d#11{)HcFhPp-igGpsJD7Y`|Q5!7)sQQ$=r`V`Wu`*Wu#X#Rj@3X z$-SI~6A!z#nwM`npmKlgnlaohsYXrE6f;mJo*@+G0yjlvW+!y9uEbCIzB_;wyw9La zW2;O=F&2mnn_)+0Xy9<)wT&dO=1KwgmMt7Lpz&B+sPVNSKxVY|z(}s7u{S4A-zBBy zy|=3MaXMzP5_!Y%J&VEzw;+HhVg<)8iXz?mlQ?nZ#Ym#aZ(8xPeFMx@ktTA% z6z52_!kN~IARms`i#PseY!dUybA>_s2_g#hBCTjFUUks{10Gt&M#d444w#k%`bahC zW_c;oF>{U|?Cy~C7 z5no;25bECr$lY|3!bSNB-P3&>8(GV#JJJYaQo^174ciP@=Y2;NZH*#02-HkiLz?Js zxp-CG%??avx9-g5w~I$|;Jm>*x?#qjh)&9T57<66;`%69&@i_}`5v*VCQbHaXd{==2eHr6%~fHNDDW`Fr3kad`BsSS!EbCA z6w3@KbML!aUz;l@ANNpt&^7i*&vN~G+BBuJ4|`A*Wp0Hm@6J$ZSlwoBiHw+oP*)UD zy00{pb2k)iuQdMgq3CosUC^%|`(IJz{LL=@@u3F48Ki=}}n!g6t zqKEO55I7kHF3>Q&9x&74lkReIg{(?^VRIfIJJh4>vNi2TK6SLqi-96|K4SQhOaGK~ z$UA$2zPT_QlODwa9(q#&E32?=QQ24OSP?T_i)a&w7AByVH-z3!uR!sP8DXbszMJSO z1FZL);NIWzgr1*PQ{6b)-hMM$J~mXSlB~FGr>+9XT{e!UpI+4~<-v`XQW6WYF=8_; zt}l%jEPJXbfywhYM1VA^GM8<F2VE)3BVJzlCQ`f(DgrDMnhXO6eM`YS%ZR z4m_detf`97bY9Q3#5Wt#$FDK(xSkL)vCXf^Maqhv5;vYM%N8L99Cy_`{SIM68f??; ztE7AW`elN+O9O~cFN-n3n_23dmO(?rqVT#C*%3XR2l$i5Mk6ZnjWA6$H;^K;!QO=w zEUB#-JpH~cyTW9epSLgu%S4%)5P$Q%8-x}JUfwkGt)-XZvl3bqw5?7A6Q`rL?NH5H zHJNR|Aa;xq5>jZBNhFr<>?tx4vt&%*(|o9WX=jJKn|1=OaoErfo74t)18)V4AG$um z?r31ZJco^W9QN#88l0~>u0jgaD6~(kuH$29f? z$lO7;6}Tp-e6BUEOeYRxe=XrC-bzM)16*zcTcRg<_;8XtJPmu?gEltjQp?T#y%@N? z_2$o+DOOetOv`I7?dUwx2N`n;bpL`{$R04P#G!sLx0!hONyFxUmA%nqF_ft#1%N`) zy1};uT|{T7)5$K4OLgn#VV#xTXrIQj;rY8SdIewFgjGIKb_}dN`NInikor$`JOv49 zzI;*2TS+t!#balC(S;Np-r8rNoBqwlo!75%E=~pKLN9C)WgSofpQ~prJ3{hw_$dEN zlbteY(#X%VD9qK+v2y)^T>YaXo>QCQ+z4X5+MeE)ecaak5t+e=>X7tG$EzfbvE}ND zyXC&>G^Mk+#re=08Vy9!Vuf6F-Ow6uttY5@aQ)-Fa=tW`fDAttjhRwVKI9+(^-pJf zIIX#EgW*w>0u@2Z0=_vF1V>#UW_of+>e682qwn^zHKCt*E$1%(-%zUN{7QePGy{%I ziqz4LNtLRsiAax`VrDyA`8*T8Z?1Qb@mVeMX{QS!L6Hg9S%{X_+;whGqZ!uc8G-H5 z+GlxueKW0X@4HeIfwh&KqyfInLB&u`)v@lGV*a7MutoZG=%07WUO43s1&VlI1`0gj}&Aoupf84Y@0 zP>#4ha0T!79Q&PSm{QWavQO*?(;Hk=@t`;nWZM_B&i(ti=wJx#T0lABQr=6=XqM6B zN&UUe%MC-yrAw2}=(nxl4pFgLE*D>mW2Q8Fp{mYY!MkM;Du*QvPR%`UV+gg+<;kWf zn8xK(iRtTiqwOpRV$2L?4vo<}JzMICu5^a?$D7Zo6cs6vj*u+j`4lh=DaDw0W?g;+ zy-gfd4p%WE;B$zT(h}vz6o*jJWX49LYdaaje4omow2Pwe4|UI{T6l-=vbsPP!bA^z zbPbR0KCU}s zLqwphHBU$4l%VFM{I=RI67>*TrH8Mk=poqmUO((~%Ji^FlIW-w0Uy=(X-xWF1rp`C z3zHnQB*L_jFegL$`O(sKM~uVBs0uAeo7nB9b-c?Qv|l3)JJWJVk91->UJFa zHZd7V;%Z0kSeovXb1D)%0o%;#*tem`BkKOv1rbIEoDTbgGCgWMikF!n{?TSUV>>TLCi_hv^q1Ltcy-RQ=jfKj`Gw; zr~X<^H(dj&lU#^Ywjk9hZw%F{jUFl(MfVakd|H?5w(!y1JeHF_zKk-()E#F_lU{)~ zb<2YD0iS(bl*>(QXDA{0VW3$v40x0^?R2otH!)G{%+$-pSl%=raP+NktQxnSDz^+9 zdr=;=Ayx+0#3v3f2^2veG;(GG{39RmNttY^msLHy!WW4??ImEvfD$yR%GuYC!c9GM0}6qPjrB((L5pP^dQZ$RZf(=AY~99o`6IDac^19|v+* zH*MVQyHk_jGJeDytP`7nl-?nN9!fz+YBI%z)hp|}R+fRqWv{&}=YvJOLrSey*X9Qy zA(3!>+rwF@9Q0?LU0m33Sq0FEbouBtp=QY8j~uA2J@qJq4YD&CEC=JN&}t;M`O6XU z@(oVQm9o(3rvvNKlyYmNvj6P+laY3o#mG(&6G-k`+}y`uHZZkLA>d3{IYQ z1#!H$$L7=*A#svX&5DbfbW@%H3Q971wTLAIUE zy3%!--vTT0Z^kbEE40e;pQz#g4y}ra3QNnW{5Q1v+Y~2irEltp|BFOLZEc(c1#R8%H5nNG zyBmy|;r|j?W&f3R{V%|(`TtBr|AT-2&qS2%tM~o~5#`|c1-JhN5#`{Z z|34<8E}%+@mK(GIjq{Qdy|Wy^Ff=&xS-*V{Q!w;G(DV2NIP>aNiB7JN;w64g zVV|X*z8^a~9F|!PCRJ%K(ldm00^Nm zSRngDh6eL>LLB|y4hIZpeOhrY5Ury>lCk!|0)Jb0)ydCUH&NE`vWq2 zCIA&==~cO;$gy*wMArHME|=x%6?`^4;yD~}uGW@bH}4PEtt~V>44B%QdOiRuJr)=HHs6-* z7X1a^^VPlf6*r)qK+7gDFn6zW9z-LZsBXd8} z?!eFl{O*3RAAlY`ItW6i_wAQ!#*bF-&aST~ORkGAEckm#0pTVlVC&UA*5K9E7wq5{ zolfm{5e92-PmH|KW;_O%-dD)SFh0cS{WJ9EPnF*e$q(E9&-wk&{jxWik!y2q}1+?;D73c0xRyq7ffw6LGQdY)-uNcbTSxs;8K5H9}Y0%>n zu)E*-UxK46ZhaL@7jmf$KIwN)v=&qL^*((}h{CNJ)oE)Kh)3Nz%{6t-&2E+07OW4X z076@q(D$xQUDit#t3Pym4QbEv2O4wAttP{3C|TW3qqhff(d0C+ZR z|8^R{O@n7pH6pD$pDJ}Vh+f0HiKh*q2Vl2Ky=d}NK3oKlUc;9d$Yao3_8-Ih008dn zo+)1$N^wCKgs!h&o=>BGZlrUJgv)ML-a3-Gq7%L zV9?U`@;D9!CQ^6nX&4RTMfXfsdhUuJCM@PD50$}XL^(?q?U;1mzcTqZ87$6-)v=5P zt^-J3Q)ZZipeM7o_p$jH;c#uPS!Oe$FbzABN-NIBwBL>7&JXUa-9Bj*Lb_7q`O@V@ z1?Bj>`&d!6n~i$Z^FWc7Y0Sga020qN3Q{wY@mG;>4a~rLwFOX}PBD@>16A7>YENg6_?#&{ z+UIJ{{T3LuS`&brwQdRyuj>`EA{_G^4Sn;$p{g9<4B{zkGX0lYki8sld4Q5ocN1r1 z>|)m7(9?CG=^$K79mvu`Y>za)`&^2?aDu~p7eyyEvSf!Dn<$rv>V2M8hWXL?N=Jed?@Lm|T&DaHj4^m;GhJy_iwIlX$?0Tz#dP zwik6W$(f2c%vZzQyMJ}<5C}(Rsw1bUi|s4OO2!QALbaB#onBn)x{~Zz@p}QEmQ{@}kH{Rpo;>8DMwv3)6g6Jb8?qx@#)2E!RaGtK(Ug|7-)j;!E zNlG@o3w0B7Q0TFBD9Ds+t*pZ%cF&r_!m`Vf2~%FSG&LD(D<=<0>(>Kj*9U|A;X}uL zjNMb_{>xdF8868{ofS^)9z67l8iTaU*O^xbwDvADsl@_$97Bg*mQ+GosD4smn7u1B zK;N5anE3Gfm8o3;-s2leyFj%v0me43{=WnRscGJaq9`n*J}w-UolmZI@)nd`mlriF zLf8(jB8$A-WOXF{%Wg#|w~E0TY2z5x)pC6c&`Uf7J(R{Nx!YbEpr}k99JJ-&ISbKO zYc+;Ua~L^r*tc~aL87LuK6X;j6)3+hGoc21N*#VlIGL$eMGpVbD#Qi3a7;;(5M$?! z8$Arwj1C$yR$t=cVgn0AdIstoBLiaSFkuxhR)w zJ!IE9s~V+%#Hey%uy!q`n^MpqlnYh$Zwm24H&xRby2Oyvvbt^Z;NPP=_jSFx5*U?* znf7mCDQ|PmV8W*qn&K<{PY3e$Mckn=cN~RoZ7SsU_B0G=gdRkc}}XHT*(piyn4ad?ohzn`S(T(CrRmP4y{KW zu^uu77t0l6!QZdPeJ3EHIV&-&jPcG0_RCz9ZKMP|;of<9j+p8wG!1Y|xqOe`Y4d1c zbG2yTP>XWY=*?CdAvRcpdYe&}0LM@<&{<=Ag6KwJ1Z>Vs>QT4UblC^J4;<>$g6CGj z&u;wI;BM34l6M#rHW;&U!TW8lJhP{S3_&vfsvxk%TJD~AuSwVHrcl6HL=2Y%+=Vc2 z36D4}(c`5S8CnX$ii-$h$(ubIGja?)GnY~nHR8nZyxGrQt5>QsXw@atNW68D+CYSg z`3FDgmhH`V{q4`CmIRmF0XREl{An!)%7?xWEdsX&Rjy4OhVYZ1v z_~P3h4=ZgPmo^UuRl{ljF!A8_?~9rH+{_yHGv`FlDdx}c?UD9HI=`hr$raTmCbeB~ zxH9G~Duj2d?Q7W)K@>;ae7Pn`OyZDZf6?#ZhcPK8C{o<8_OY3`=4NmbRyvJ z0nU|tpRoMN!QmA9%GPqVZAZBE$~{-wbE3q1vEJhL=L*z}T71B5evN3!KVk0$A4ywY zlWY}QJ4d`2*!SGlozt$iGB4E$O1x&_^nwGCzoj89gAv6Q7YXC|&-`*M1VSCU?eLr1E{&0r|9>p)1f zK$60~*jb6EeaOWMb?`}thTLAXsikJTl&Ip`?*`%{NX$A!(E^ies7% zu~Ezcs00F`P>&Ud?8lwjm)L7W(Aan=X7>)j*wdAa#w46gMyQcxpYs+3GI$b3ZKLd}~W;*LUUEx-NS3YVYj~iVo zJN{~{bxM}W@_Ap@jurC=y=L1*EJnw2}<)M~T-DKDfqmu+B{{_{}?3JY8yPeeGFcnIn#HKSbR*u<9AmkkW zlE)rud~@2{^fHwtjEdamE&WRpl~nch6r=hnraY4i>KX*7a5%M3e*mPaU62bVXPqeo zkHcRsTZm0yrCC>xLBV;MaSI9i6yw9aE_TS)TN~jLdvMvbsn`fU9&kZCBvSOxd=1n~ z&0u4bzZ|#27HIqJdwcDUcO{_TfF00n!829?$}PO!L$7}?j;tS{c80p|=8S!Wq`!)E zc(mBcyW;6fLprr!A|KzVnlpI^HykI}zu-=?zK-_5cD3^zU0vpy>~3C9Cy8(`bxo_O zul!0_tnaDidzl>>3EWR{I7I6~JYb{2@4bnUc?Bia?P|_dwL>(I)EFBkAB(iK@-}sa zhNnbN3YDM?|9crbA?G|YT$!N2zYBL8L*}HU%nD5IrbPx(BSq+V?Kl$<1IIw9u4*P+ z6jl479NoNCa1`CNu!w(n1TRh#OE@k+?O-oT&eT0|yyT10 zajWQ8!t<9hM5*Iqs;`b3i}Yq+ieX8CxG}Cu=-^DocN6QmT0`PgI|CLbJ8jWBor7}L zdX w(NY&9LiWeTtW#|1&sG-TnlGw6aMzQHeAq`aq80Ev<-YPG^l*!=V!OX`yOS^ zJCj4*W=Nx8;k*woc4D8OkMV2~YYj5gAj!KZ-dC9|iZ`$HvuW5gW3d3 zJ*lS&mq{#01K2I;F9gQjpHJInDBwN}g2`SAMA{93o~g4c2VL4rDh9d6pKAw!sKFbT9#6B_6`T282uJd(9UR(`CSZO>7^vZ!WL%X{C1hShek zlofnF=bxeDONfX3d!|sEGAS2*sqMy6oaWWWN`1Dyh%$C6&8H(W%uyIDBBU46(n1Rqu(mtC~kJal!U@Kxaf6? zVTyQ&J3^Zbv5;gRcNuE1tr54^ZQy@_2J#o@JPa#A*FTq^`MmODZ|YB?XE$j!AJA4) z<;AM}oA8@>Qr}cSg*%3kNn={~p`+f%@rRZG*VAF~u}IjZV3ImA;hVFyd^>T2sv;V$$dTj6oi8FC;bth0;|N$(X->J} z?JPEIjhI7Mt#dyb50c>6G4-BKV4n2$H61U>Rk?B;2{kmia^3XY!jn}37%_r!LoHu7 zZ-UaWkRKjZInG2^MfkXTHK(*{lQ@MxuA5gIb1*Uz#NSt5KhdXeHkYWl8ivhf#B7__kdcFMM}xKBfGF~PX3Iw$gp7Ox~{v?lURxtTsDLP>nv z0Vc#Yrb0y$)AfICYvevg7my%aA^sKY!HfC=g>?3`h}tQTm%^0p?z-vypijvtvSuk^ z`M4`u*vAewuVOcprG<;12X}Jm%z0;1ptp8A2rZ&b^AZ=y_wRtYL^*r3IXn8g;vdw# z-KOA+)DaQ7bls0sdJDRr@JBmFv(WX?K(-FjCsZc#)ywC35hy3pUG&Y%LHwiW@OB+e z$b#O2pl8MW{0lBe`8NsNqp8is+M`pZjF{yS7TO{4ILxzvta|hPWLRCXxiDth-&M?T zIGV9LrItabSjlxZ-WH?nWL(Nui9lZbkHZO#C72)qm>ZUm_Gd$%`bhtYiUm)+*V%CY zdue5A{_yDQ26mk2~a@1E@PaX z(9P`wbE5;#6R#6%gJhY`^0mg1_QyHESK%FE-!beHEQ&90$Dhpe+*-aXvJ5D5UcX49 z!8sC{Lgb9hNl{Cr?cM8^n>i)aL`oDTP{MAJ)a|P<*K#Z<@1RhtaAe2r5jgqzlu!A& znBm1ZM!uXQzkm3S3y|7bSP{=9!`zU~86B#mBMaI{e|uaM`fTBKp;xR#n|#w%Qho^F zknxviliCOL=o_+hc6?EIM~JLF=ElSSASDq?0GNV^Mk2=F@R@6;?of+^>{Tu@tF_3s zJIGdRm467bX0t1kl;0z)aOs$U$!Gs@ zZ^Hgz9Ip@-t-d+&pI_-b)1RrI8)qgtROj@*+dGC|)?Y8YQ@T4+$0{6K%SEVaGvkC@ zc6$@zX&iZaU}%QB5oAO%aH>t3mV;H2SWO6emoe>hrPi;>m)MR98m&vRAlb4kmiyDX zvG>>J%^%!ujo_rda&#T}ip1lB3_h~%i9 zkoE}}`)Zo**y^El_2*wlp3!f4T84c@>xnAT9+ce7GltlFq%wY&`JMR!tISR4npJ~7%^6b{ef(m*;Qv|MXvOY zKj3%5)no>Qn45!B#TCx8Ytl^&Vy(Ery*yqu9Crgzi|0qUFcX^`)!YMYgE7nfL0vC4 zSbSg8D{j%1Mb6K7-IscuEv{2ojJZ$30hw5_7uX7kuvSO%L>5GHZJ8lqme|J~3SJxv zmnQf5t8KBJ5zm;@$|}lgbKR9wKQ6^pE}JDbc8u+_w;zg7_cQ07&3(ZRH9hMh#b_S*2jim?D;s`q zXPHZv{pGuoX%^uV1+hfRnle*Cmw)A!@)A|+uNO!)|H5)8mZYE*h!{&r7G2^wB|rE% z!iW_#>y`=?!(Bd3;TLw*#FvuijstU&6e)>CD)!Ph*1~V5Zg~3nO()*G{zI3SE`j}- ziJ3DDsf2$@@xOwXFl?63dY;^lCJ2uJi%%?l^oy=}if9U(DFZ5BrF(hd&1(qF=xDw} z=gyZQ@~9bUkMI{xGzcOGX)#C155{iXmF`uuSWl*Ngko<{&<4@z7rw<4#73*}i8j0R zwzweElSTBh?|aB447}G~KV#!=1CetXa6-In_(B{$Yif>u%TF#kt?SIs+^Q_-Iw{Kg z*cBd?VH5dR_ZpaAr?^46%jqWE&9}}zp;f*K*de9a-~B!2aNh_K^31cw`3EVQESM7q z!J)oc`~uv5*n@#^xQq3OEcf~=d}YETXr|F4 z=I1bYGrNYqN4E^vPHRs+O1;zTNxp$8jpJ`SZOulY*Ls-QxJhzCBxNblebj=t!QCXg zuSiHEyLoDO0=mw4R`ThWPu<60k{C)=7r11Qs~Q6xG-@l-C%rsWCzTlAGD)W8)n-Ba z_^wVvC!ePaQBI^S_FkSvVZUx`Fa*Y!dZOY@3%%oEj9nuXtj`?Prdz=U{iW_x)k~|R zFF9jWi>5GAkNvo>J-5uxh-h&1p{&x$djQn6ol06w#$?K&V<=tV{hmz-XkG59T7?6D zT-nO?_VvcxXx58cgBZuLO1=g4{cE@wca;`h_KuKS9a~#pVAu{B7LO372&IU zHy*M~_G&@pWa*eD8PG|nit(kl?^;+xRZh(ksz$bJ+PS=-MV9H+bAr{%<%LQO_Ew}b z69J~CT>gduyZ0kD8+YR6rAX!D@_8s0 z5nY{N17nrk3iq);DfgE4-lkP6LI9eLNxD@&&{sWFNEFn8WZWifA zzbx@z$2_^^!f{xMU#Y~cpQ{=6PR0c%d9Nj%SHZ8#Bs=v{sQZ9atmW5pr6>PunekH3 z6U^Ip-JLa%h>K8fQkRO;f37}&ct5VP2ICA#OX+z`;3r4+XYv6>3FDg5@K>i6g9N>* z$(-@JOK#<*x zD(Z9j)S<9Ik9VBpo3o5Z?#o6RJ&+ zRu$^LB^rHeGN#zMVDfgnoX``+G}<0rgW*tu#}nah?lH}_jX2iRl4Ud2KNv9ch&3Ov zS*t!bGZ|oxlwoYutCY#CBqYV{aZK=z+K^IW=bXKP3mnXx!}dbQS-3vv;+8Ij%Da(n z5RB8HsU$@#3@)Sf03@5>mu}bLYW7EwNK^q)3DJ4zbO0-qoDR+eHLm&n+%DUJGE)$A zRG`e?UnIrsE;aaO5|XX~wd{2HV>P@*tQOdEoki z3InQSJ&;pX1A}YWe1CY zFBRZ*;<2_#sE4vFcf4xIY<-yt$su1Pxf`T|t&V0EPRYm(3i{N;5VPw@Y*r1Ro)q`r zhaV~T<~n}d)&T}qjaw@J3^3F8YB>1tOR4#Q=y?h6{eX%;U-~8H(Q?@t>>UI#+R){d zGS~@euI|1nd~p67V^*BQo^(Tz$o&ZywzjsZlCD$jI28zQxc|#f%E#)y38kJ(D;3#f zvpIWb>HM9BJR~{}>eKe&I(j7^gy|KpiL!bi*P`3(-vZ(R9bB@x*E6RrQ> zB@yJ+B&1dT-zD!~h24LVM4YqU{qL~^Mpm}}v6{_@&&b5c$njt05*V4;m|6Z0U3`(xzp3iC4KOIA zd3@OUjQH#8Yn!u8C)bcdCkeLsEdqQTNmo}1*O9g9NnfY!8_kQ%BaQYNu9^;?n8U$v zN+&^57g2tDE=^NTQV&rZztBuZBqG1KxZv!#IE?H}t)>1o%-0z7Y%QGAQzL!TiLVg< zP@>sc3}Pe}C$P1#wKbqZ?MgstY5-Cf8&WtMQBeRUBBGTam@Diy!2EyJsH6ZK9)68k zG_#P|T7%Qu19Sb8n;415zI=d*!%6_8w6t*RJ)3}nto&lohC-TtnRyKyvtWsHtFxH7 z2BubkPS3A$5Ry8Mrly`YU|?))Y#u^bWFA~%Og@wvei^|H9Q+ukAWlx8=>R?`FtKcn zfZy5}Jlq`oOPl>?wr$~AWepj5L-_xw9TaaVgTeE{34R5xq9%8UmI%A zw!j*_d|iO_b4*`Y*LXL&{?t}K4y??q%?)*IjZd|;EWoK6YQTU{`}L30*VByvLYfJ> z|Nbq@y5Rc?sR}_`3K7Nj=}y7|?h8r+2+8~ZB%T;un(5zM3f~y%e^m(o)79tKMr~mE zQ`b-jxX#Jd_p?uCu?N8n*0dG4cQdB3w%)ep@dYeRVHrWIFs(a@vfdWhOP4FTnOrfdB1+cQi;+Ou?!>RS74n6KG`w!}N2j<=-R~rn7 z+_$D1jtHxO;gqiUX9oN~Bz!$xKPX2()=xil1omi_7d?xKzGpwai~m?rmvMj4{Z!V5 zFq}{wTyhU;zj}%>dwb;6;mi#73?6)&6sG^>J|NVyG<>&2p~~)~Uh^Y~K${vq^thh- zDgp$zG}nSsu5+k=dRPHC<@$f&;hgS9R`J7!BbllAmigs+zS~MNXc}@Q=!T3;4#Uwq zIWa%_fk)v6tpeys=R&gpw*NG(1AuvGa+$_L11M#~_b&c+2(1XOtpUIY_6YkDxc~&- z+71HhA-qMg1H$C@{6X^*xYQl&gV00xiAn{4LG1a%5ab{rp!f|5oxZQGD9*oc>ik7%tLmCqoZr!7&r*jl9?Jr9 z*LXhoHoZG#{64)u^7=nTu6BS~w>@!~6)@Bc4$nr?izCy7vXLz?M^ZTxF$-1*o zt_sDv0XuhVK4}|m?B9QIjP#ztL6mL3JJ535CwVTX{F{B%{ESe2`Q??9efeiUE5H46 zpEZ5}1-gC;7-tnHZ@Cz;Mwd{X`h8CYn%2KafgPGZVlb5=zie5^Q+ZB3tv_;D^o-xd z-gij!KptCF^E>goe9^=+^AAH}?42lrlTeF)HU7j)@ndL9hENE#i%($Up_*npu| z_|kvE(^C0yeH(Ki7pHb8*7zmKW?QawWpk6+)v-9!e)a$izPYeZA9{DKt|2}RC-|-H zTpB(G0Feid;33jOFYpkA7p`Kgf!sTO54^|od-Q*v-=yH-hmcO6TuZ*$YKCZH@*`P4 z?+^joJ3o6p-vz)R?Z8ocXeL*Y?g7-6f$P`h!MB^IE~0P6qpr*frKg>!*c;lo+x=d} z<>Rld$8JQA?xk49?oyHW8g_A~YZtXexTK9N0%sQmF9|-G_k+`_uW$C1-*t2$g3jI` zcCSw50Ug^jaNFmADzP-XJB4G8*jns6l*f5HZBLS|D^E$ZupyJz?rCtrJ~;Xc!1WXQJ=nMWyEn0T&sABE;3RhQ=Vsc;FZjZWBX)|7X{Yz9_M1A z)N$FytlhuH|MI>@bSHjhx_dXZAr!+XNdCAu!r6OVJ1S3pzYLUB8a$aXvr1KOE+W|t zVQkp8ekun(7Nu5F;_-4)87}z3>#?@;WW0p$Z;kv1=0tLhaHlu209*YI0zEl4`sReQ zVSSIgq6%qc$lHSK*LP(;4o z8AX`-f0R1|%i^Yc30T%;iR2t2eF0iIlXBbgH=tYYa{;)S7QO6C(WM=v@5UVL<73g0~xAIn?dJjcb4-dAO4nNfdjTd68h`v=nSu7F~oqnlH`mk z#?WT;I;KeV)NDLVpm?DM>2H)-P8O;R)$V~4uTGpSePheQp#6(*yTh(It9+(%?NW!7 zYjBBsMZpJFno4mqq$Yo6WO^qU1NB$TOpEe#tWjS7{t-(D^L>S|?2N$#gl-<<67pwI z!%A?fj;tOfOqRkH9?=ez^l$%Wq^OtA>OwNW3V}))Hm8zt^stB>@4ss7=wU70_%?IObe2Z zB-ySltLfDBUC&%*+nO=0giFh*ItHmy{(KCvHY=@`MMLjrKxjP_=NuHA#hdn@|K7A8 zJF6a@7-tr;8$024A%koVjT{`vUZ1}_AV27TOgLhYkpY1jCxorgnQzN?F&IA?KET<# zjHqECXq!$SDC?26yr8WBs-UWKY5%TLvebDp*Iq(0`Kh)Cp*_G9SPRa4?9yr`HGH#+ ztU&u%?-*3i>c9mEGHf1@$ApB2+o3TsC_XPNhWVP*#IgX0@Mmv0-+X&Trc- zO_!&Js33X*hbF-nk&Z$NR#oj&*!7g(H?~#KUxX< zQFb|5=BWS58**z;$yqr$=tP@grH`vyApF&OeD8#{jLh*Zr+%1yV@Dm7Ld6Kx^?Uq19goc_mS(n=EgRGk+ijg|ze zaE22Hq;lxLWe^jLm-opAS+#j7;YN^0HCrYc4@w?ir^30!)>%IQ##C@PazI#s$v~)s zXGPq$Xff+c72z^%RWWCzw{A-OTUTuGJw?au*tE76B_G%Y{l*Sg7y1uH(5 zrHMH0T1d%rlC9)_VChEp^V?ZISFU)#Pr%D*G6&Mw{UlneP07m8=2Bcp; z9hVu9zAqhY!8eahVtl0`c?R%WIuu7r1Z9-nIvrrgn*+c-3&R^d)catZ?`dS*%w(;4 zStDQ~n6ql0d;Qx$Nj9d2PoOe&YwC6+E6A|gWZd?PqV!J{4Px}~P2;H$Wl}BR`LpE) zhh|`rmtR6|ohp(cdq9+lYPHWxOYX;x8>0Qi+k|<_l(SSuRhqNS_72HYh+w!+K_D5% z4`;Vk(D9))e50W|WyhF2#e>eJ;KG`U8X3wi##8aQMYi`|aM#={L z)ws`~iT2iW3)VXx!_IyEN{2Vzd)Y%NQ}=^&QKCFl&cYCM zqg1d?NoZH0u?f4ogbDFYZtgkw%(nkp^ev~Z0dXl|(TJ*N?fR&ITO3Q-??nhS#80s$r3GnGiqb-#1q~n9E8i#|CPi(+n1=yQ;_1ll`8QpU zU-Ji=s35$F%LaqGH;lQNv7b40H#hBPnb}BopHx-{DaDdskm%=b8=g`$9ouJh+h;SaXkxjw?jJJe-reDr_f1Pr0w5BIk`du zi~ESLd0iO0ayr52J?p|EEbLTYT5Z&Xvqp*MNS+?OQ?!h3Jm!KEB@hr(JeYP=rEkb5 zpTb}kn$;Bx1%uA=R@xSYV;`GSk*qc)d7U@~i!r%P!^wIc^f>!C`9J*;G4**Bz8O0a zGEKb;dJl^_KYrh1cLN=nN43*rw)D`yJgDG#Ab3y|Dw-0Y*#-*3#D}H|)V|MfKRi9> z={QIi1^vAP;u?D1o`PKD=c}Jzb%}>WO>Wi{sphCAsv;+=mbZfntb!6OBpMNk^0avy z3@8vNDZB6=BqbCuTi_pr;Q@+D+I^X6`>iZId(h{wC<06I% zUOU|pWA-Q=nsZV`hl1snBucW_?f-}9oXG2X5T=+yt66H0C3bZ&25ck!_;3UR)Du)1 zTd_RWGHy4h)HhFFGL37_g<8l5YoYU!hiAzN;Jt2feD?>M(B_0i2nDZtS8S+nY4ARp zR+n(5*a+zNj|B-4g$34YUsEE8SX>e6a@N>Gi*5oVXH!HOyT^_z_fcxhx(VU(?&o4* zst)6&jnWlI$?NVZTUYY9UWM%khJpqw8Z=-sqXa^?3*E_x8>W{?Ah&-?q}#yyd|I}0 z``(ef7eau8K9G9#ap7*^g2QppVZ z)>jHzvxa5tVwvunq)iW(cFtOnAv&bTkozQIFJeR}f{2?w*1){wt2qm97UDId!3JR^ z)*5&Q2Ssse?3~Q$rc#t_Nl(gA)6X+l6~-DS&RoY3TUWN@kH1eTTUp$&lT+_P!759v znNW|)YQw#!nae0jgWrV{7B%x=pYg_%me~xr-GG;YY-SoA>#c-T-p%ADYN-CM{tdg! z;2tw5kCK!3Oke|n0@ZcZRgkG~GFk5*661D6rtKTH;0Q7wVJ&q}c8WimOp9=FL?VY2;%UPH}xZ;hTU1Z6^u%EhqWBZ0YQqojsR?Nj2J1jT*Du=;QtQ* zJ3z$08;?pViw2x<*P)-5-8UM=5wg9?!g>VC!iLu04&CeYbLKQNxog?vimKkM?Vc=Q zoQA`oM}MtAZou;^eq^xx61?8GkW1{dYLIwxDEeLl-+!=ldsgW~3mLTJTG1Zzu(Q;c ziZ(dE!5R7mP5g7gd0Wgf$0QW}t0UXxfNof%4uz*JXCZkgI$0#!q=;kzDE(C|J^kP% zGmQ8K-z=>D7@jBt!s_wkVj1Dk)iZWrZ)4XoQB_MgG<3qYwi?JW#h<@?;970RW%e-sXEkw}yzp;qisn94a#z)TZ;&`^8!dAez6YS!#+h|)vwpPnPP92p>% z>^O~3kbH$58i^*-zi*7-*$=H9z3_|Mlx}v-eOnu#yG#mCwg6L#yhI^lE)c+$${VEe z?wR20@sH}RbHRj)cbRZ$hUNACbQq~Ze#YS;KdtRF!0Y8GFJhn_!J3Llmkj2{Z8g0t zmke0Etsz_qDh*mGq^xtE{nl%Ucj}*Vucs8dzaM!e=0S^9rJVAO+8gfcAq32uA1YWu z8e}$|q;J{ZJs?(ax_B&;IbI~KTz+jG^y7}D`~Saee?LAL}JTXT|v z%dr8bV}Z|B&C2wL>DSM$6#fG?^k@_#DqG#6Uxyd0J)Vf(aU@{nA!=UFiquu~+5BwK zYpjxRVbhmLhq-H5U@Ck>c4mm2MtE6|8s0pEUuXSP!&G4#rvE6)?_&>5vuj#v#$`@M z@KD?bt}A#dcW*GSH`yW~bHl?{2K~it;PC64Z7D~GQ=wuOQ=yM*ny3~o<^J6(+dUWU z6Q@U$Xqt{FKM6#yZ@6Qk7EK6YlnWqN00~0QsECJjrLnXaRGY1arC)|x%{Rxmw5N+) zUSU=C-f_vq;{>7hs>+lYejwX+GaE{1R0!1Ggm90*a~KHB_jn^kne^IbiNYpZR4UbJ z+~DJFPS{Bn=PA00t~S;k>-JSMil+U!T#I}3bgy^pOJ4@lw~GdAzXf0?-T=6P%bg$u zuJ@brBO=V%<*@zww0^xscDxgYERTst1H-diw8BB8aP6wma1?{dj$yH^{BAegE~q0z zLOjG=&s~cPS;HV~G#|_F)q6vNkNM#{K7D@f$h)T+jZiSDJGP-t(J73!)Nj4sR#^*Z zm3Ur8eEyCW!QZ^cc}!$aCp+bgs^F?>qJAP>dRHl%{K`67bh0Oq4mL({b9CEt?$2J8z3Bu<0$fN0o>aI_?*nCks7~)k zBuSTP_E)98=kXMZOeK~Q-z?? zQ-PYGBMi26^LeI42-A{p7Q-AD0l%ucMbJcuQicLHcy>?UoUyb`>cBV7J0HKiXl}3> z#9)j2>ZiMRMFm2tWqC(Xe28xt2n~`DL{^(cVV6SCAxaI}TfX6c;vQ1he}ov~pDE;` zmSXh5nrhG?@tVhkJ!Mf_^z1($a@iKoFohgm_!4}rxK{j~N-Q>v6ZzwlT0zEx8&&0* z8G85+OowUibrVa{f|jaf%rJ8phXI6wj5a4bB)S&Ccz78|367X8k_vC7@lc4}(uW;@ z)`h2&ckoA_{9f6adKL8W0&aiP(ixk!qHZCU)0o*a6$Iv9KAgB&?K+dD`GhCw44vgV zEW!%>3oPTK#drQs_sHJRKb$)(nI`(vh4vg@!Z9m5Cn{fXhNWG*X=RAK!Qn3IgU3Fr zug1n^z^6Q=D+SeSFR${db$#H*fAev1Nx+!qhJ3vS?pXfovakvpSIAvpR~>j%X%upWjyv13J#re^_fLCAY- z$7CKM6Dbiq1BS2wA9y-T064p+&JXJgj8j>X85$I-I!`jRKV&#fXtgp;8Ho zz+SB0>?*=z&25b#x?1reG%>ljIo-5D;ZK{{WN2Wz=gj21 zN-evazPpg-dK-jWKZlR1{qhG$7YDpd3hmt{f(XDY9xM)s>|nVZ6Gqg$Y(0PYu&d}^ z@+sKHZCN-L3geUTqxJMA14Z^Ch&C*%nDE*TR>8}X^BKrhMk!1LimZy1VCk->h6F10Hi#^au zcoC{wf|ku+=nSltA{99`z7aqR4Y)=&r9fykqy!*xaM;Axc%iVSxlMVRcMnKfUZu@+%*jKe%Yb{+_g03^ z;BU7qY*49)=mntJvTN7i7k%l7tdo`Z*lZ7Cn%CL4cO7=f!#1$>z>;QXKWZz&Y7!$3 zBHiI~g`%#<=ntC6}l zUESY=S9_YzZ0vay8c9h}x8Q)Nlx@C^y6x%h45ufqk&UbN{wldjMh^c+l<@r|Jb60+ zhuDce`*Yr$N(AezfxF=kPxV92vt@6bH4Q;ZGAD&e+PWnu+9|_?pZ(-i_j^AJDm|;e zTi#Oej6&FEfaTPWr;QRU7hV(epU0`DijIM^yuEulK%(e5;nY6nRAuCV{Z{^+r)}n5 zr8-MDuJ~)&$~C6pP&2ErD7;`{cKLgBBJW~SLeIUB5LtFUaKZNmM;fp$ST+WOsN)1y z@T#aTO6yQlih3R@jd7Dm!_r*fTM+oV)vpbq4 zvDj5MD@6w*sb3R!?kvA+e`+#L4!`^Svp`J;IAwpksFvO;(LpAOO>`}OvvCn6*c;6> zInAO_*MnZMnl~oz0`g({adqaJmaas%0-{f1+#X!u)FH`}TdH#FUS(e{JF}CiG>N=n zqxvFDyfsg>#xHfX)Y9}u8X4*aI zby>&vV zNPMC6&@+Xnj5SylhNuej1LyOgBG*_Kj%v|Mh5x~yVq7PyXDd})D+JCqO}J2Vn4RPa zi@JX#=rYOp@%2{7Rsm+XEYWlxZDMd}VI3;p4T6LZ!!$2dy?x2HrX=m=5kx=G#pDT>I1Z)Y1w2(T0F{7R`3_qd0^n z^`X>sW#KJ$-$l4a=+Vvfo+UcFVdG+)$h64x<{Fwm`Uf;t;j3Jo3v+%-ZiXN5(}J3F z8K(r+YIWzwO8tog*#ej4nGc%dC@n`Wu{}h5WZaGWy?9+~=j^6NIQ;baIU%?}0Rg!? z96Ha$XPK+9(U=LFG&(VO7p?7vw3+HtP3rXA7ts9pWQ9{UF#Nc1ORTv1{@YSV{ocr;R0yea%zVq0D=?fbgS~%a zn5z4W-x;0c$CsnX_@LIU?wrez38Bv&rz3(v%y16VwM@5&I2eJk?VQTKgA)^3&(@)8 zK<%>{I|(L6So_?gw|LXzlY%PA9n4E_62bk2_u{hQxEef>am?Nbo+ zIAzPg1ifUI-Uar(Em1+v6HP6fz##MObh{P4Z?D(dP3My)YbaTe9Jq}$ZTdLgwSU3( zkSTU_57l zYKrI@PckE;;bw=n;Cmk-t`)(Z;FN4b&Se8kMYv}J-UsV<>^bQQSq&cb2xGG<4hG-9 zbsN@KoPb!VyNaQ1XD{mQG;f<}0JsQE$+`Zh0YhSJg!sJaa{}!$W9CeBcOmDw%179r z+b$6 zYp*c|mnl1z+6AZ5&n|98_@(8`V@Q4`xlARxQ}&mbjnf6?r8@WKJSMeQGd;u}g(!bM ztS`#*4|a3bs3-sU$V;(fGbP-4opG0u^K8&vf+vi@Ug0YbHhGkgx^jh=W&YmLrPOwc z@35beN}NErK`nld*D!CHC=q>lk`Wg9YNBX^*rY^1-=YHK8uiO!a>loWk9@4bD zHIe7gRwClKz?VGprR%q^*ko_gj<4?&;GtC$B#{^KRf{)K!QrljFHdwI@#7e+Xdi^g z1*wX?qsRMTW6~O1L$8R?C^u33nUnHgd;;ICdXw=}`(2@5|Lvz5BI0Q2eEUWzYB!W`>ScQD@fOJL^SIHUbj3+`assREw9XAh zlX=_ZAqo$+lmWw=-(|Q$-vD%j>b&aMV$IficW#LGr51-SyAdyP9%+`$71mk@C9Z zBFgURqtsLBKK)6Ld`um+X7S0iZXrPql!SsigtaRzoeXBi*MZK^8CMUL#G~=!PnBEt zgW!oCyk&-lViDE}xdv1vK?)u@n$bV-+ZgPbrad23V3kLtqrq!XInPgi*jQ^-;3*PI!{7IRLt7YFLz<(44(Dy(8~&pB)sS;Q3gJnq zwQ}aMul9g7uIFfzC)H2YzUEwRxuVHE(8+)$BRYFcSO1`?u|Kz6K6`8C^Ji-Qual^h zkNy3JE}}v^tVL8v&i0Ba(;w&yl8IF_7F)6L_=5csS*TwA}hZg7C?^VkU{KJ?-6~4xU29Zb`vi z3@VB$Hrc=je0V?PaE&El2p+03?*SaRNx(pyQ)JJ)t|qTqDJukvw>6%n)(g~T&cn}> z-I9O=NQOgoN!YZ5Ms>|BlEIw@%~IhXt&#Lbx}5X*+)kfItHN(a&sdvmI|uNuu{hBrtWkNc>qRSl&|VVYJALotSq@ZUOeEAX6E3N% z3I!_*BB>Ly)p02u=9Z(Q!^>n#X^&g6T6U42HT`HpJ`W~R@kojCrXo1PVhEMA+1n+; zTvHRKVqGR+6mp2qc7cv3zQF);w_DU8@?$?~uYEr89`X`)Z%JqI*1Dn|-10 zJ}09mf90PNuAjB*rmV%)u{PSegC1Sc-^kBxVOV)QwOWn?t7}Zzw92Ys%h3+NehP4X zgbPD{Sb^xgm^+(YMoS!}$Q3AAHK-zM7Tw=+z#U!ax-4uXxBpliV#%|8eRFIxdG}n@ z*#Mh7qbvx0o!Kr6Tn!Bvs5#uGne#2I;1fR1SpmhA{b=BFVpR2<0BUitYqJP~v||jp zR0ddg;Np44SXjdNAUa${%_#HrVTn5RL~R<^dDVbqWCX<|tV@FIiYfCZ0s*&tu(UAR zgwOIBQa?jD5_e4;<;B7c;>Gr|ZjloQ+LDvZ%Op0WKp_&R*;RWY*rQK+&&iiPf(*Jg z)4l{8-K2N)lo6N616OmM7E~Teh?OE2cq*=Jl<6b^#LZ3`tv=j|<*;lrrJ-5w2lSE% zw33~SW#9MbEOVmZS&|FV%#b1`pLoTWBE%Rf)Ig~_8<>28Q|7Gv>;qo&&ED+4)$TRp z=KyB)ugcF9FZ#s7MKENL9xNDKz}qQFAz}MEUW;6slGX%NAQ?j;Rh`n%XpZw;71+m{ z1U1!RMu}n~k!2^cd~0aNeG>VZ55~)fC|Ym!&F5U~^Ydx#kDagI>zvR{dn7B~OOjE} zN1j1I0UW`|^00@9S(4FiZE`JF-<56$cUb6>ltOr(4DLPd&wjteIz0B5 zNL;5P#c4JfBNuiU6EZEIn?ID_TPvucOe=YE@g~BQoo0QirU2WW%cN-L{p za?(V8?vM+BibuNm&Y_54ZA=8!fBY8X(W|%dwczYUo z*YC3Yy?{@R(+_n#MliyQ>IV#^YQHx^Ug8v`zQrlKY*{K6NGlBWmpVe7{9JR~8b^)+c^8E3^G- zWLxKqIZHPHDdNfpY-z)+DhBs-pDm5bYp(GO*?sK2l!F6X!^lJS9^R?xCD;yBk4Nn* z+ZMb}Pk?T7p%9H_>n6?MCb+bk(2Z<*k{LR+H?OzQ{-jA;-lDhWW|LP&Z)pZIEcmw5 z(|DHR$S34O+8o0@eHAB5m~=SwqyT7(;c=EG4pp3|k3~hw0@ZS&m)Y!UYJ@3tLaJG< zZdwP{%RRSwqE;6K@fVz7CZz#VNXvlHQd2nK9H3*BquP<^c7%ikEB3_(`wiuIPL6#R z>#C(M7yi=P25n=TMVx1x2rsJ-w&C~ETH+^?iZB(9-vY&z<^^g6Dqhcx6>g96~4m625Q$GoSIn6IU5tYy2v~`xeCY9p1w5A>~ z3Z(MjS>;8m^82YooUTg_264L}WMfIX$$@E_dC?dhI9>VY1ZmE$3lsAzTc1tx@Xr}n zK-U*vo63=fU!bFo!pOhL>`up;_u{5<}66FR{u{dwD~+B$;Lx z)|_;bKrDVQbN0k#Yi~+;w>s;kT;WUQjFenRKMbNie7;WLOf4ostXHHGZ#j%(5wyWH zg;zatqfU{{5)Xau2*!m%-rEp*jIF{uc3d-uPn69h0X49_O2>O!>D#MEC{P#AW{&6$~M*Tw@_Gz9b~Kc>LHR0S9@H)5xa2E7dlOPCUb}= z6Bbk>%zPGm*)da$=dpDp0cstie0(E2p*=OgVzbk*Ki+pw6lkp0%c<-*02fZf2Br11 z(I$n8gxOB}x}p?S_tmGSZu{{pzLG56bg{%Y%grdrRz(@5q)~topFv%J5S1ff-AqaR z*P|&OOa^Kiu+{@ge2GPJoT&xl`}jQmEX>dO&H8z|6x@=+1-}^g~YSCZJ?a zuc*(MbNhSye?X`wE@no)4;&iR>=+${6h?rddNraJSXn3( zc`a6!l2>j4N#EkRZ-D4Jc3@Wf+^poJCz(aES7$+3(j-~@9rEG(;N(*N`A*2-+yV$K z*<7Lwdn49r-~<;z+NCk%e3ek$xIj{5!liEo0qW}1i&3y!8!npP3?izjplP%+^08F~>(AE@(c@oHjGF6?D3u~NWZ z?qNzDxm%w28ZOuR40i`C-a<<5sDHv!M>FCvX0r7Qh@O+oa8e-yxBf|%d>7J6*Pv8m z=cT_;c?lLzFRk~jcETuZd_sKYAnFOo@)LryAgN^!UxYXHZT5omGhG>2NjXBPBukDc ztK@DXZir3(mpe8cqQZ3X3Vdn9iU^d`-m-mbEY)68EfdZ+4jwCuYTHbPYVxF?GK{?k zZ7?Ob1@&MjnUT#_I=*(ARdj#&`3)P4{ru33(38N>@s-w3d+uE6T1N@1%=d9G2swd= z!S^ZOvOv_|iF|Dj@~f0CWW=q|mZ0;b_-W-7zKB|_x}pQFiLqHBzp8>jZVfx8Xv{}T z7d;?MLQ)#@w}GM6wVsb~JM~cv`gM&sIgfk*g=hI({NfeA_yQSsU}fRstz{VMtX&W3 zG7S=v@c27DzbeQX4sqY%JJ)(XU;f%+h**@XT*dDAFZofFRRh9X-@0}J`{6!8wV=Bo zReS75mjGjIo`x}_Q3Y>(z>a@0N~36{(-Gf~RKc-2 zgH{d1Ijt|jf_lc)pX}`x(f(Qg7Bel4 zLyDYmnJp%%vmM<%1rbZ++OST3(-=($4gX?(8esme^|dm#4aG1oqBYMe2$JHfTx@c=f>Lrp5;W!XQqo@YUsclqIkbqJZ1jIxS$8jN8@@Tv&an|rDQy* zAHgl}z6GUCMtwMjWwHE-=uZ^t)Ovy_*;NZ&3NFu@pq#H8LZBSEe}ASZjQ=sY_A89| zO>S$Yh!Ui;1NDau3H*$X&dWm^oxKW~4*8>|h$(9`@VfxX9RVzNBQ1zYdo%>Br)_-L zH$2g+h(O7!Z(JN-C1D{5w~#yNTFO^g%dQ>0kxBr*o5LyjoRk2 zxvR(KBiozt!f%o?@&m$wc0p@HDGLk-SMs(EGLY-RO#r7ezIE-$6RiKpi5Ig_I?FsMKM8Y5xEwk}kN z@O~zLVa}oS-k8!OkAsmHv@ckzkxANVCul9u*5oVK7BkpqzghfjmW4`;5!(d5&H}Ie z@D_hz<%8Pesjwy+M^(clEb~)_>n#AGBat2@Pb()dBCgUqPM>)6EY26db4_e&d&72X`;OSX7<9Dcgmbxdo9g)MY+<(0y-E1yKiBgClHq zQA?ibInt#%$?)0k0d22%MtORm`Lmk#ya94?Yab1AB%&mUt8pB+OJS6Fdpe8~Wy|3~HxV~PG zahjE<;9BZEu~ZQ%8`ScVa4YJ<6!eu~LCTs5%`89A?5|?d-`dK*;`)H|+%(Z70{yJ{ zMM72N$BtfSFA#|Nmvkd#tp^;7ZbLE!4K_ZOX*a7%NGT3aW`4qcg|LX0qW(BFQ4Bqg z(?ij{V9zn_l7|_q6@w*9+f?dbPo#Zhr|rBDIv2e>P2e=Sy?T9jEoQ6VE+m{qiMlBm zBkOXqVmH-j$QS(CR}r#G)w;v1I_j}D5<{uO$}sBy96i?HqH#l4Mq>N`$BR1J8%u@j zI(Ud$G}06&gBp;cCgGHX23ZAoCII8`yzAn}374jElhEGN>`UCWahThHdcR`^0RQUk zRcnyo)%zX{?oNhw;-rfFp~|(-J4`hh8fR$*y@SN}_U1N)9s`=oB919b&tDj+T&<0r z5%zok%}@3)UkyBR`jV0&tKbzm<^J@;Ysh!Q%08?}T=`_VkH@$7A$10XBW4(<$77b& zvUn~05i0QXNzo)St{D;yt<D>zoOCX1`G+-4j1glv&;=MM~!FY^SA0 zyc1hqEwn>3a$ z1>D0ttl9Mkqv3$qwa|E90J&FnqhEfVyAj&;03sE9@~%1tHxB( zqm&cmo%`q>Dp`8fwG!53snND-T^qd_JtO)ZZnwuqYi#Lh-s9x9FDS1@pP)RU45v$c z%E{_e;hWXMy6J~l(s2xeiDxY-_p~-=v9-Z@THR=4$=U~b3}1H-%BonW zxeK=H9U7j)4)m9IVpTkJB@BX5Z(oX_PE;$E+z7&Mo0i71k`QINN=f4lHps$>S<0T1 z7dsVL9V3JTPohF(3^6*w338)d^UU-$bt-nxkE=W##fOCPZQQ3SjMXo;%zQt?OaT1i zz4=<`=5Z#FjC*sw!mHK)f^O*Q8x%5lhB7c}NdU97jsZRhC4}ip~ z3B!0UIkkvKT@-hru~W=(8hKkY`D~t_L4gM|ps-3iy^Nn2n&BG{2d810X#3+%Ag!mK zd;gv3_bYy5CpcM7O0e$m%kN~6$uD*Qv2fI!jL5!3BS3j3mDS$s{>akj5XA8hO(8-m zs6*m`-BkHzOjs1(n5Od4o=!2dFsjRqX zT)BKjuluZ_I;Jj4No23Tu|csP=#OAGcl7Vso-15!Yo?M7lX42Oo^i+$N+Qcm$+|UI=?ZfZ5KgIA|iV$9MMqOpxv2{rZP2C=%%avyq;UV znYFoN78pvJ$=5Aiq#fHEn^ApBOCbF?@kp@~W8Odaz2!1}v{`g5g?i-iJnCHE=WSkF zT=~!%mYK*RrH@;8i?$zmqBFnTb^7rh$0P`Cz|EAYrn? zgo0keuMe@KcP*ZNGq)Srqjj?1#%xzOkiQ_5zJ!b%T;i()0>!kD+uDUbxLtnVfx0Wwq24~Ngpl_Cd)adG#i8U?`j+Yr4@-Dug2XAs# zQ}TzPa_g66fnM^_WAI7IJ;LcPmTBHGq&8Je8(oN71}ya~ZfI=aZK3UoA*QhNIs z9r%`Ry(?-B7$xQX*X=WUfN_cx9(!Yo*Q;|Ispge3su?Tw#IbqTCL?L0H4h=zDAhBB z*2&*(U+cUv`$OD{PKJ7z68ATvO{m>d)xJ%xqAJ%YIy=bmv2WS-YXu(hAZ7Lv$9>TV zOVI+Hjs)(b+p8vCwstRv*zD7!P=r5Tz=h*H&Usyha(#uU7bt5{RfAg=foi5v4zB?0 zf7Ia4PFMa;`+-*dHH#SzQy>{_>2vuSqeh{z`FQ)u*K_z+^foO!q1>rYovZChHcV^o z-}gLLsTuVEJ5VY`f;|}(;|s|GNOCQD#w-EaV8uRcd^d+o!|n+)8>3lA^lT};7UM2M zSDH!;hna=4jhYcOI-dQgw3oDpv!2F3afm(mEcqmG)eGCIjWWG;%uhAI%1Z5-Q<=Qi z7|r(lrf;P_?Vr6=#J!E$H9r3U!z>jw5mhX}&SGIs7*7!)NNzhLd@{Q2R%jy{PnUoY}H}LyA%z`jD=$PH@XNm zP>eTB>`NT!WKkvek~4g*zOx}o&mFukIs0LpKZg@qDp8Ghx-x!n-goEM%;}jXzJvLm zk+9Rc-(TzGAz@fn^^}<=AG`xKYJi@EUJGY}@0O8FU)7mxE0Mj9CsU^xY}U{a&qmnoYt)ZP4lTFu~CV<`fgDTH+Yt0ln6j zpgkL|`rIHD&EQW*?>-L&)4Ad=Z}d?2?r}`%n{+?fOtJ1{8lW)y!)8&Z@8jd6BVafM z14o8qn&BkG=u#+du6A|+a)RIOJ)Q|5Sif3*9wNQCqUkssQiAKDxLwVjpceE`A1s%Z z9y5T(zQMXuCvVLqT5anQx|oKnM=bQH2s{TOl#Os%?QhE7k4B@Y#R~sokdKBtA)B zlAWRvm4yxEh0!i)>TyyBa8EDzk|9hs4JpaZQA02yQKoHj$>AkBUp3giX9eR^I*HL( zs28v3Mlx-Hbx5e-mV_i;8s$i7ndi zP?MQrgy=yN_W*{%RQ32QW!PC1A6?ZoxM+QU-Z@BTtm>(<)>+IlT-jmgo?>7$r#OMa zEFIu9Ao3SQ6U=jsUp01w)@pR(7CIaR%``1xC#et~hHDl0n@~px3XAiHdX#{^(x|L< z1VPLAA(8EE=ph7yoaQ-itlV@474B#Yty(U$%&XQ}k>;7_mSb#ldmdWZ-h_nC9gXlI z*5qFky3ATgg%?qR#Y2SAe zE9ptH$80fW;_C65abMQ2dTYir%RHrOnbU@$$syRB4d3vdud0o}1%{Zu=f5y17yFm9 z&2yX)IRgU$2PPIV*CO~c3^@p2lW8H~aI?wSvac`|Qvyw3RX|YTU}Ikvy<$TSR%|i8 zIGdKru`ee39wBU5tk#kaRPcRWctNUaLSJ$yQ#U|n z8BSD?uG6s8d~!1UV5qXF8O2cwVuOI&mLdx!wZGG|I7P(rWu3&CJFuW)MfR%OPfaQw zn&`}c^-a7sy5Ie8uKtVDH&)C%*CX{C2&)Wc&KSy^bBgKj`{LQ`Ug`>j^=4O_?3-`V zP)|D_$aq*@G21V~?z=b(XJNRj8a^jnm@eX( zN9MxpnOLBXj!rC;I!8go5$%MyT)vB-%Aq@&%1TLVxXv?gfN`^GtF!5f1_&!o@qfu= z{r9ppM+h9JxluaIt=Rg?_kQtsvAPyZtF&X}`?dup;miPs#-=75RPt2SUUdzk9=QLl z=gMG2UrZj-JQ9d!+jf)X{o=&t&1nNmhk#7+S!)-gkNIg}+B%n|{$XVpg&l+D+F(xN zY4r%b)OXw032V;h9C-QTLI?D#Qpu+yfsLLFNia8`_}KX3VDFV<=C;`yQOwL2G4Q__ zsRR9T*Vg!SGC)N4avs|AII%L1AoDu8)rUeNRWtGm`5COr3y%U(ecG^3m~7%_jN^_z z9GM_3G<*-Uj6N#u#%o9PQghp?4eWO0b8i09TN9VNOL>6=O+(j1d^C`UjhAt=IdPQ# zrte7n#-fb$a%)RkMG~PhcaL;*V<)m(yx8JrdQwvC538^Y;T;-t6g-P(YjSagH_w>e zM2-BfQc+z5U_yi21|{68P5s?G*72bF7%X1=8w4@)nC>$M@n_9kGf9c3-PcZAG3)*G z6@u$V9`y_f5d}=u_iR%P&O!qxGx?po@ym{u4GJ-p1Fh4Y$ZlKQ0Wi&CKdk$0O!9i} z#Pzc>N8(*z^^06Kv`E)ssE>5FW*~e?wPGbJ;-6t5b`Sx@_hjfcl-|V(X)ppJoE!YX*yp)*ZX3rTeHTm_SEh(E#8uU5$u`ePg+9Mn=hJ`%4AR4v zt3jmR4<{lHNyF60j$wqOy!r$A-YBQ?xR}2$`#1;ct;eEay$zQQ}?LuJ1y8I}r8Sqyszj30G44UO0+Ycaw;E!t?)c|yu%4`;u2w0yke-avV z^l7i?w0uF5Y5D!a&=O;QDSjW6^(Lboz7-StJ-r4pbmR7-9n&?d?^xKayFik^i;wq3?VuB_VOon!w$@dV1e&k&hH{T(vx<2Jssn)P5YU3DjxBvR9DGHMazkSREm!zu~RE{OL@*Ityt1*+uCf4vvyt9A#M5A?8Vct8q!SmZf|NLHJBp(*y~%S)-4AAAjJYm{7{arLm}a102C!=nl-Sxly23HrZsd}WVA zXkFvI3ckYDv!A{(dz*EB=Hy&j>6DK9mQL^22lAHyufF*Ns~*WZOrj%plIO*Y{yyKJ?f7Cr;h_66nyP<YM7jWU7DP!k+-7oD?i^z0bm1{?O-jrj8MY ze9fFV?UITs%~}PN!gqD%eV4^zoPG*(!Hs9>8y=~6Hr<$nT)J^t{t7<0tqZ&rPmF($ z$Iqdies&|-K08nDN9gQJZRoM|q^?hl1kaL*P9Bgx)+4refpY|{p;iX`59VTmbk5qa zKUJ2El!`;b5ZZiqQpj`mSbz^#QV`zc(%nWicHBQI$Cqa~)~8Gh)%pRCr$QbnEfO1= zCP(GEglNiK4<1{+VR=X4n7q)v+uS5E&O0UQ&KuqfOLd2=^tdz;7vVaK}*eB;kO z`YucX-QA&hpI{H|{tNoun6NRvUlcZ>bYR$tEcO?aWO3~l+l{Dzxem@F9Gv~eOtlbU zniQ-dF>Dw=cd<@;(!$LNE+_0n1co6>*}7KAXbJc&1GaG=VKLjMptD+NI8Y7fk(x*N^Wh>0BMS84^5Fs3|IFIAD^(#)H>I`r38A@ndNkU$Wo&0jJ|0kk zj6jry!Jct=p9&-r@(l|ybHLbw7!dB2*TiE9>Jh=-fU&5?%_>a5fkPNCi@%1^+6%q$cLEeP>+oa=Sk-LGbq~VjT z!iAMVcC~`zH`vSnS79t^1{IVLzMFK8KyL-Pa{V6;f*5duXJ3(N-J0O*;m5DrB%epf z-j9&k&fSaUD$!9Eh|FyYjtO(WL5LMW6(0d!{u zm0dtA{aCO)L}*6P>%)2IxIl&hE3)f}S%xQOUIAD){0NdgmPRpdnVrDGo!?fI5M~H4 z^+alp(&j*;_9z`%%*wk4Vx*f(q?Vl;6)LMC+*ccB;vu<&4AZqr3ZXHHX%Wm8Ajf@# zspTh0@M5ml(qo99fx=?P(-Jc7`Ms9T=g$Oq-pPoKUSY>raPOcR(eb27;nX3m6}nVFfHnVFfHnK=_?W@cvC z`TuUKcDGe4?Ml}5wQN~ewq?n_=e*Co{h!RY=QS?SZV4B}u1sCvo0Dv@cP)Fgcd$1* zqe(Yk`I;6fNPAP(ZYf(hilI3)1PVAg2)GhQRG5O~3*5k!iDpD)ej}7pt;7WQnR+VC zHUeYRhP0V-DOLnM?kfhNgS;ds>;Pn2FYyjsLAjqP=*u2WD6^zVeBNZhAgCrRxgj3e zsUy;VK3a#l$Qb0)#IHr@H(^@2fXaO_)AOug@ds-T&m)T4y4bL*SL&^vj!8AR{K4$) zFD(x8#A>A5Tx2iAQur0y6%gzNfyqsDzAm6aP6`L?ZIqDT^9_yGnS;YL7}IsX+!x<6 zqc^B1Rgt>XBGgG5euh*gm6U@48S2WB!#pC= z{=&8lku2VrOR$c`Mu3i4otJ8HWCZt)-P==XbnZ%#kHT+BH)19xDh%Kl{N-%H4i-wA z-kJ#{=9=tcKc8E;G-lf_#3!zXjR3Bb)81JpW3J{}8oSlntZ?50x#uOmU%O-$kCnwe zjg6ryUF=&~TY~z-9@;pvj#RY7fWHpNTT8~PnWvhhc*{P(6%NbVwj$q#9XLbF8BH(# zr&UpY>$k;myhtB4?NoV`bh|BrK(1o3TC#aa0nHGo!LdVU9%9Oc?-W zU~v5C&qvlO+A7XT#g8q-RyS}Mk4^S%ir+`kCNu20r#6RTP^*+^S_zZA8okL6Y+<F65#GH<26i9BnaLrn(Tu@cWw5^pdm}r|x7S9A?*vu3&fkY?$ zWbiA^J=(Pd3H~6|;yDkcE6sw1GF!x#-;e5vWq(duhtCTKx|TMO4T%Xt{jh*h5F~Sg zHmmdM454>3B9o^nfC$P&b-{Ben_Lz`Ea+soR7;E75pfvrYU%pA!)MS^;GkI(V(Ur~ z@9g}}zC@Uy_17*oZ+jY&juzq$-3urBj4`GWTa#&HoPBMl$U0P{OFdL6gevGb^wxmN z-?DV^w9P?4d(a2B;PY5?4p?KjZT6regYqcH73@|3YlbZ&D1WrVyU8iXZ$q_YQakyO zIs`&Iz;x0o9V)Y-Nh5E5xRFtxR$SaV5WQ4@OrX*?=Q0pq>1qu#fO#J`MkT|{WV44% z{f_zVF8GMNIs;gW)De03t9cKF(D6W-(_6m4jePG+Z89 zC%7Bm3;A3}ZBn1=j)?K`e8ffpm^9u}>1n&XW^^cl8gc7(9Hy;r;@p-99p&aH?eiK7 zwj|)n&R5tK5(~nJq*87Ovz9NLv2*L_eq-r~gW8>IRy{w|MbnJ`pny003Iiv0QwKG3|r4=1We&99{E;g2qSKiS0Q*68;UVG5d0p?k0bus+0FwH2m}u~YE(C`f z5Wr4m3njohHA{WZaO_8pn<6C1oQX5|!$zm?^;+oRP_5cwBnUOQWopFv+$VAa*63Eb zSF}Irpeq(t|6$JR+!p-#S=7Pnvqd84>8h!xS>pv?kel#lxO(Ef$0$NC1=^(u4XK&X0%z^>JPL04Vf;Q#WO$h1mdL2K z_cH*8q{*{U9S!z?AB|W0H~li*$k*^?Y*``152Y7E^V=_<(2hLgln%W0?~0t!0t^=P z>Q4{JZU6{y9acC;EjDsbg1Oft_zmP-$I`NVl&M9 zwtQpEd9v0XF_PXPH7U>^K!fI+wH()6N1IOm?rcJ|_)ESpT?P=qFmN;oA;tz2ZS&ts zm1-kh(>9=+ycXuyYhJ1;Yp;|jBEg4lB;Re_97|k1q}U?dNa;MU&XLOfA*sJ+xPdN2 zn1A!`oBFFtR&ZS8O1<@XY@B9_2%PcDTvo$g{>TE5TEG{T#i&J(_Jjp z)Q%|AdGEEz@zuj@wEj{NpS&M5APGLui~GiQ^!!|Cf@YG5zPA)J#*$2~-pMG%Z>1xP z?0S6B2?8cmISINDs*ziS^rZRB%r=jxPNd;t6HjI3O_#_`7ci2#`bzG0qhWSgy${G? z(YESj zfiH5f3Xke3FZ$rLKlA*Sxo#kB4ihO%;RwuK73yQfo6qbueYOzuhJebj z){5yFxgdM&vs;i-@2&ag(r-?DNgZg+RA8^U;L((x=T~m5~j(iNFRRU9G zlOhhhbelr>4s{v8dZ>p3o11;c=KqTkV^sdekr->?2ELyxwrXlCdG6P_A6zA*+I3QY zPL3O+DNVDr8l~>+-aVDJ5jHM0!&gWZl(s>8L|njWkV1x&gboY%2s$nJs*(^!r`(dN zzw?T}4bzc9^&L2BL9S988e|pf4i*(LFAiO?qI3jp6Dy;;xou$>I%X(shX%@{uINEQ zXXWorcvHo~rgBl1bw!kZ2m7_uLIFoen^XPy&XaL!70ehYIjC)KC?kd;-R0Dx?AB8j zKTZ>N2x9lu?gLuUQsy%xhp+hMdU&uEOr!9vTwgJWjPdPvWg~TJ?dn~!&qi)sbCOQu zB_QTqHnK3*JhlB2NxJ+*`1oD;&GD?8)1)8U7{Za7RbAjkHU7sH2$lBHdKDrQ91Vu+ z{>UtPPy1fM{z*A)3%e}i98%Md%6$`o$Bj^%cN(esERvLg20YD308liK_uOlU5hz&u zJlvB=5cY}owHZ{G)VpX*WqBVECIvLu3g8c|DEW4bf|&WEZ-0A^rWX~RoYsq{eFpyA z6%*kE-=7`SW_g|S=~pWP(^&CCy;XHgt4fzCJQoJc8DbGAmTDG40zw%yMcV0y5C|EyNI$@b;AFkyupM+v8MV1KuaGA$prDm6sYLJ7GW zo#31!;KcP5Y1N6BgSx+=zmKuN3?Y6&os83lCnceBpDm6Au&djmY#mr-(c!T_iSzOyt~84+_&y&COdr{lrPV+@As(i2)$T@B9Q|%%Hfc!g?e~AQJ*l@a3Pt z>&(;Sa})`iPVA+@=|VcWi)v6(sR`~l7Ay(|U3I;JiO}&J!SnFmnt7*8_+nT<1Im&- z<~AONyPI}QCltWenj-{s(!a>R+yog|{*xf;`kj$g9ZhBxzZWL8MR zw2YgK0?lkuQRKoN0ZUkPtqY_uMunemOkF4*$rAM|Asiu0h@raPDsqs9*u zZr}rfSwqkyxvFyV5n$sxp#6xHd zWOwqYfCqG?5v$Hnqrx3YV2JRmDIXR1^V6de>1JfNrti@`la?8= zQl-${65S zeJT{4`+j_U*f;4H>g=-5G1Rr`P4{g6uJsf6LkG$v`+67vb6u1Va?i7*x>jjrp(6PX zQ737aScy$UqdfqIqsAnR+X0rL)7`sfDRU<0rZA>bE&iPfDJNc7WIejo!Kx(=T^p)l z)aQ2eT&=WEWR*z;esL1u-vzNJq}&cvQdM`LW}@*oxMnwLiA~sa5G;!}vTjS7VBdWx z7|G&ZCsr3#nkKXJ4VX5iuelLCu}U^aehco-YG{VjsF*JE7rSLFvF4AZ8!eB2JQ zxL5V>-!JScToI|i*FqyaYXnXY4#D@<&XG>oVFL-A%)+&UpES!XHfM`^Q~^|0eyprZ z<|b@qhBNA9Xxfarn{qG}gPzYDGXLFOL`G+XRUK2-1uBnqsQa8@P=)+iNN1;z#yb9RFDq1pB{B zNciufAXL>=l_jO91*PQa>HhO52qroL8is#FLD12$|Gz{*{5`#bqmh*|0n6WPhW{c6 zf*&9N5Cr@N2myovA^=f<7(g5#0gwbp0i*#k09k+>Kpvm~Py{FelmRLLRe%~m51{AZ zXk>5ZU;)qv=-cZVSQt548W}tOYv10?#MBXB05Gtzw6Xr%T3P7<3;~8VmX><Mvk}195@2lOWDhU_m;y}QY)y@< z0cHSmfCa!3U& zk%Obz-yzvK**F>*>RbNHLI2$Pm##g)0pMWf3UIL0b1(%s0vt{4jf?<}E;axsfHS}a z;0ka9xC7jc>}~#IV#Yu6G5$kh1|!|SdmjEZF@v6s@!ut8(9m7*Ype7-x%nh_nSAp*C1v_q8D;Nc#y zLzGkdqukujU*8iR327wf_f5}lEZkASEFGw$eIUQCft>V?_kdtP4HcVOTY>oq5FwF9 zqoieOK<(;4zpaEzmO%$H2@zy>eZWV1dyi;kSkxR+O4yVjDfm_w5qgI}clOYakdYuj zfH(MZXM8|#b^C$T99W^Ca>s#XoqheYW>1Z9aJco5EU;5bSiWCjb?XfwY@wl{Yd_Nv zV(TFX2$GLveaqV-;8(uN3X0lr`PTc8L7Zt&{^0S zv-olj4ngFCJ3|a?^b+*q2LhWPJ?-?Q+U3rJI$9D;`K&hKR%&ic>go0-^daa&2XpZL zRqFY5F?Pz>`8349bFZL+ztAf0RDiH|t{Z@D?QB04uC6b5Vfb@>$TBq4IaWB+1-S`j zEqu`i5#VG~RCaA|ZS_D?1^Ioz(%0EJxehZr(gZIiXtF`RGB)Vt`fB2`JLMsftJKC{Y!k|mJ#4dB)WZ5ALV>|R-GcN=1J#BU!5`xvI&tCl`Eay- z(ecvXJUTntf~j)H0lf=U_R8>{Y)$_|%s1f_opQVXOZn0wMw z!JF2n?6X_)Cxo91NVu2$(hk_y=P#>eaz_G)1zniBcX`Qq{$oZ_Q&yVS|AxNr<2g5n zfCpsbjHeC6$%>E8Cn}3X&_?3U-==`0x z`_w{}`n82&-0R~a>);yCfYJM)@jA@MlY2OizWm+r^)31Oo$!gT^kp;tz3q3Pb$RjS z$oP5s{oOiwN$8yI1Ib0Xx_D?tt%#fL4EolS_qNl+qJ{?N-@5i)qcS%1Va8dQyX5?h zLp-R4w+9Si#;5tq>MMT6$9lJ{6Bi6-$<{Xb<8}#XrOmhZ`4!y6j|*=q)F_nxwAMnMg!veJY60+bo+!|x4roZ-_~a^>7Zh>p|? z{fX{restrJUb32tlVLVEYyD?U~!Bi&#tg)}I+rBzlvPzSCS`P6^}kbV*-l_Gb0T zWbAwmuG(=9&tlHtu=w7qv{IyaH)FD4lVLB39v`vryv3V-E<2!(%&cMKb)`LGA!Xf? z?~_Gvg%9{3R9Y7ad&<-ju^&0!8WREZ{;b37R!HMn9#cZnAkNtt?^5Y2Xs&TIBXP9W za3~4?CLR7em*LT9ooL5*3+I(BwDju~78Tuj+~n8G2p$_FddmC@`+m&A_-*A$H{>jr z&{nX;2K{n__MbzJjVUcdN5kO4#8C7X;sm&@ISc6iWO3=?%IuuMwa-zJsj?%@SLtyXv>0qc^mHRg16?oz$Ad^3*EYF~0MVvVO z)Ol#&@-DA3GSzFi70L3kK$Gccu=5Yp%}o(?Fi1V6X+WJ_`P}UzSzJ1Z z^uS!dcZ;c(YrIh?DaBF0;ME{W{a|J}YX3oK>9vrgs;94|>I}|nsm0E9ohWr4yxiiJum*^M0z zl0ca=<^idD*)OTt#&IcY1!;UN-}N$p4CHmJN=(o3^JVF}-}3g(f1+sExC$X=r)16h zO}OOwY4ZbA0U~B+rY0a;0g4iA?M0*umzOI;@8{ucHpvhSuv0Q2#dGguT&XO3U1!Hh zVF}bKs*}mVxDx^!qf&wswQ1=1u-A0nj7AB()jb{8n_4R01#_0$pSYq=TDix}baqEE z$5Q&UlJ&0P#wgw@iWKCkw{xrG!~Uf${#Tu)>P7C1kinl8Hp!}5vH~@DC@6Q)Hg)zF z%;Txt7&a^hn60l}lQ>mJmbOHq-cj4T`ND#+S5-0;N`Hof&tjeIhJgEsVM)|QNpyw^ux&*U7=EWv)^=mhz#PNmtd{)E* ziFdc{uoPT)1dgFEK=k@2>=s8_EM4#C8ljwiqV`k%3iAUy*LRo>CN4u{PAJxhDl(?1 zLl+pt^u&3OHC)OqMKCgqp_1Ia^3Sr_7pd`VavrIIY!2E|mb&P;SU=rDa+^&|rwi^Q zu_jfmELExT+%pD{r`;V+p|!trlE!J!-{v-_*>pYihD5}9fuE)9aZ_iEugW#avrnuV zm>KB_cbQUD9R^}1w*TPPe;&;inJx50{~awhBBjpW-jgm3jRE0nMMDZ^=NCzNVUdP! z0R|mUu9b*a#HA_>bFyUCt)^f>7*F+PF~AK#nLS$y;9StU=Z(#+dq=8jm*p9=lFIFF z8RW;vpQnx$b)Vni$vzqRH5;i)a&O7ZDm3jc+v_;M!uY-)R4>{_`mn3+BhDu;~VD#Ul#4o#H~Ug?0Ne zCbqK`7SF?kJE+vk(+JJIky_%*i$0vy(MiYQ;PE&;_mo**4JE9wIr3Z_x53BHQLoM> zko$sHkMsHvg(3w5@GXi@A`y53=zDz0eQDC38fNmyR_fvrPss$-ouOFIK;pNlzZ8FG zlpx#}xo+axFOTuy**Z`2ghk?2tA$?HM&Z3psO)|m#Oz;1w&uBJf|g!ej?y@=f{fQ; z`zkBJA`hD!_!x0itV;_J*yv&tyPL$CEgI}&0I{~S=g*nvykDVz^L zE^G+rh`KC_s^*jC&6Gp@m{)Ett34QS>YLRnlbiHXapigmv^N}#n$eZOihM8s6)%4pIj)>n80tE`0^%OS%54C?!}Cf)YqnQcN6UkP{~5-)Jjua{4*r(<7)mz z)M-LVNfx%*T8YVOk#n&(t#gl(MPD5InY#08Z2TubV6|8Ab(W+9G9*XloVr7fH9>R8 zFOdO0rh$$jRfy{Qy~Y2Bq~Sow96$RpN7ER^JI9}}ITVEGA`82T+Uec-lItO6&H;>c zN_hw_surI}CJ+AkTFwDMD2nWVPX7!XE&8&(K`*uJPZyHbxz@ltqkKMj4 zq!jHS(JnAE-1jFI?yc#-w#4=lPmIJ4HzJk{Xia%;oy{*y=Lv^??!TLAYr{xKh&PRZ z3g10Q45morxHYfeN=rZUf+v=(M^a0`7n=M<4l{o4!?qntj=0s!<}y&Nb}&h)zyvIq z#>j)h#w!+6I!`ol*?X7@T=6kos$<-UrFrjSKK>$aqX5p*5a4VhSxfS&CjeQm;XZ)= z>A1-1P7az^R7^|R+0Ej)^MWSSWUE@EA0+=H!=0FlcVGR->Kj|OmN$))DVh6?L23G% z%bbupq61r_o>SI^iTnCRm1Gpt_+wNsZZ<@P=_M%>nUePXHpwwN)(5XPiryWraBoz@ z2-$e~!fjVD4Tbf!3Y!|_PZc})KIaHfyXQ)g3Z@g3Z8xBC{%uZ$b}oC9!Ydk|ha&iv z$m7H9E)W_<@CGOo9roV=6aDx1MT#~|zx)dXR`Y^x_1=|eMWM+WABBE=IxoQq&hNx8 zz+`rz!tx;XkwmoPVCmp2k!#^*VAmUQwn*nGhc8duEHfGsJ4Q34VSe&b*r|!6rYjoE z7_a|iwtn0qE#*9dM{HFcPi>kwvIb%_aJTrN27evb5u<;kzakHGpfu5?Gl*CDK_V3a zFGzZTW1zn@nRRnV992=>!^q&{Hrc_qy8C{oq>X05Z7RL7U@vry>%+?l@jIV;=_f1X`-FtSota!+*;o%Li8Uil^%Q7NEerlzSP!uxZ}{RgV?3N7JUuAy5=i z1UgT4B9Ov9Tp@3lU(xBQvDPH+5@tP;{n$P-JDC0Ml=AjVf4qn`eOc4D`BWRJa=7CJ zAuz3WESZhe&Ak7uiLjen-WYnM;uR$PII0nGfn%oX!qW};F*8b!Mb|FJzkMyWvxn$v zed#w(O1PubDjQGLoie=Vr`__Z;ItS@5ivA$tSKrV6ss{(eq;>#w|uXx&{L2b|6SW+ zG_uN=Ls%LsEqA1#e}AT=ocJn?8+$}4h3&xOM;xfAp`Mv)K7XYfGrnGmZ^bj-s?Ii; z=MUJL`wDZkvyG=SxwBmUx0!9A0Z{5vC#+I-aiPMS{1c80)lk)u0R^Fk3aD%0&pi?< zok|=#61wm7J2(+n2me3&?gXcfwts%%3Dr=)2J%ZI5R&ud_aUdCdR&DgDHu~a5oqz{ z25(yG`XQ8+3oKfpJ#rqp=;y2Q8Op1lZTb$6#QurYM1K9cB6I^CCTjxZ3-@Ee`1`v(3l zFw0Bp7S^5vY$M=F9Z9YcF-MQ15~%ZO~tO+7x|$lVINk4Fjb4XIi=hw==0piv#2gycT+ zfg8j-Q>Znb>NJZQ0x5WWT(>Gx`LU*I>$j}8+EI<|BIHc6PU=`!+XI5v2EB{8M2lbM z=gA0)hOV5OoRBT~@1r=%oondn58C=&j->6jH`V!3zsEn+VaieloVJDgH!f6~&Baat z)gI~&<|R;4<3mh_o&ne0T}NLmbOs(i{Gz=#1^B=QI$$4S{JK2AZK9NiROPs(W{Z=n z$Ub2|-6W)%-4oN`i)XiPcB91-bCANaBLa|L@1b-kI>TV!hd!2A*bNN%ljP2{ZsU_% zC+?G#loYnH6J%q<8!b>0Jl1saL3Ne+)4-2Siv>BcP6S)Y_h+wX)WGB-?tCcA$kKj3 z2GCumC@Ebp-8msWi#zR_jN<%~(M4uY{Bq;*6FE4bu!-yK5bOg)h4g*p^h4agT5eCl z@HU!^wR3h;ptw26(*!vx_^}ulR~c>mEn4}GGLqP_hBekTQR2F8CF5V;LR}r+_%7+c zvTqL31jL%DBu$D;1!oc0^*gs5t?hX^P{R#Rym9b^z{*9aw4mmKe24ICGR9##g2thu zpWr+GS)L2oK7}4fy_J1#<)&hE9k^^XdB2_Ktc0|3vOUq!saCA+ue{zW4r99EwMm<^ zDryhBzQ%DpQAa5mDC4hb`f^Sm-FoEF;KA&k{7LdrA(V1UfjLBhwWtGQe(KPJoJi% z?d_G^k5-!U4UB?JR+ofd`pXI}ULyH1K>i#Qglf=3BCa`l86toZj3=eP{n`qJU_DN1)jGAmaKyt1l6jwj%nSukOyzDxFnTiKI9hZG7@Hov)$c>lIxEt}gHEp?IHH5&>xy0Zi9bV!`r43yM}`@$ zf)DtllIqp{(gj9nD~0uA4`>^b#hweI2J_>*LJPny{Y3bwV&TWUMEd(Go|qbL*BOi8 zRhZ3$aE3u&*7h;tdAL92^C_@Ezc6is`Oh&+a%%3Aj!l(^3FqT$kW>csIBPBbxDnEH zq93ME+Ye5$k6Aa}^Z9`!o3z>yhE0?)Xwo_W4Vb5NnS*hI&lz8dlA8z9$19pV4~~}k z7D&2T`-#(g$JIMB-s~Y?6DgcuI{AGP_lU|$f~RK;LooUYEN&h(Lr`){MR8@Ck(FgBWhBy^3FCFY%xFrFx^p+#1Q@=Y-wvlwiX6n4yamE_kWP#?E*so`En>ny8SSI7fptPA)Y zPGZL(@Z_>RC;+mCGFShWg77he$@J>P@Qtnt6ZRu$m4Jcpk(Cjvh43~ zJD_Fx0vYELNdzm{7z#$+#z*P&VE%jP!;q34@>Y! zV=7o{B`{m?C1)^LSMM)#wEQN+9m17gO(|56i^DQ3OGM*>V~>(a8QLSzqaTr}U+kfK zlP_7(Na&|=!us@;<$Ajtzeh@3=Fn2Fnu=?%%DSkPaZ^HFA&Pu;$Pm-(Cp)J+Polgb zvcrtmBd)T#@{_4j6Qg<>!ZJVMxh?lSesI%x%%q&PvLNs!edzK&1pZ}sT! z(HUH`eRtrI8EH~*eDM%$Gz@M*9~5Fkvr4~L0l(8B7~^f>)5lLCuah_6J6RQ0y*pIe zOckiP`_fFsCG;?jFI1_(2r2#|ckJ-EQ)u)E!^c@omz~*Prv~5d4pcZ-=Y@mi3&tggBl@38_gR=9jSt? z(jiL7r>&gVzo>&5q&~=h&W_7ut}#OeIX!%XpKWBLHaA70 zwy8L-G=!dou~(i5e7KM)P+5?&5<@pVOuR65ag`hUA$Ch%aLXh#bisoUXnauA`!FTo z=wzMk8Q-ApJ7A|ln+=hCz%j;2DN&`>3Og|_BoFZ3UG+$Ds*|m@!UjTEu&{@&Olmrk zf$eJECeoCv5q4FDB6a${sJM~bI{YSuuIfhKfs%X^CZ?yB6oUV_md6L!{ zbB!a4mK-}u?KrfZ92AA8jHh65J)3=IPzafN#Xn-3cmrc>uBL>KFFI`U7C?1rdg|cc+7J#Z^6_tT0R-zaVI*GB974Y<6H(gr0NoT73sKvo&Uvds6L~T zv`}x+VQ8W2Xn#WsuXW&oRip}yhmbqke}vFMe<4QN6It>?{K_Q>fBvu zA=AgznGARi4Eq@Puvug!jwi(BH3V8Mv)%BGjc2p0hOI~MG0ETCZzJ$Y$0VW)4WYA+ ziTW712!78aHcv#cwhqvN0P%9p^EghQ!%8+)7qAG*U&T8eIZ%Z7#y9moXQ>Xv zIq3ZPGhAIzad;%<>fIo(<|j2#jQhSi($Z$e>m42-y?^n->$)7}8kR6l$4awgPKikYzMO*&_7)zaXcS`V`6AD~Pco6lVF0Ds>7GT$AzaB!O{j~&5O$jTlRc98y}a%6e^G`Owb5^Iv!>2<47(eDy% zHxI@!r>Mb<8oJX)by(OOT~bRVUTrEcxJJQ-kXv1&FB_V-rqlhs3$we4oTJObuS(R{ z73GhR7yLcJT`1N4PY+(~s2QYXTIe=e**#Kr8@jDZAxjY&eQMUJO6jJkTJ^BAzC9C| zvE4JSAW7@XATvj#i&lQq;jH}OeDLPkHq~~!+tycp=mz*)`FHczpdaigrS^$=y3S*^ z9n@^OpAJJq{6~CHOB40wt4fUHRqzlQIrP8T)v7Wm#|<7dkDSt~(?$60Fj%8AVd!`6 zm6#xpN9;fV7<_!Mg~jjy2APLlW+ft0i?QCS3&GpGGVFzQq%E$L%{KnK=9HXI=h| zcl}eWhB#a1Z9qVl(iP4{U?k6pgJ69hx}D(Q67?|zJC|P^4{(QB2qG^&CK%{J$kAnu z{FCI7he~u44bJ6(?AA9_^^@j3!*fIzwfiIYOoFh6Z1%w}xVU*XLhFmMTq@Uve7BeJ zuuPWTSV{}^mWo5FUggocN{8|8>0H4kx=YjJjmq=fZ|Ze3)r`Ltq-Qp@o2Vr>>1Fly z=%<$_B9^BIWh-Y#8BQX%*i((A{*2}Gl&#e|5pnZ|J-T;4kO*p`3K0OA59n-) zCw!}N7TwoyHTD4ouOANBt$fzTi5e|W_{9U!tU);1Y|tXn3j_tZw9q^4{Cq1Y+ZhZh zFqRv3SM<89OFgSq)^hL#T|zRvthzy;1(CkpLg6E}{sb%i_)sgJHW#R)y@Ydsr=d3$ z7X@`yr8r2(9!1*`D9|NmGd7kfl%itxTs6icFE4O2!OpGK8r1e)Q>zfe<72`6!+X%D zb&LW1{b8b9BMi$oBJfM6^*mC3$hKO=?`U;6niE>ehJ%ru=q1p3EBlA?= zrU97r)T*Z=l5k-4&6Wkr##zA_yo&@Pwh3XW`<8FVpblT5xH+>{7H|(GKvCzyqD{B)wftg(Hto(TifSc1?@dN9Kg>LzUeEFcF0 z6!++60Q7_B_#qf#CysW_Jx|8U=sFkgMGm59p+pH2 zQ(tNk^^^QmdRGL?e5a3VWYgyAt+E5UWi^131T~?8g;4<&A;E@>eY`{U<1OLWTEk$cIhuRO%QbHRLG z38U4EwzeDbv?{~5MHD9`fp4c3nE`}2q9VLh_~qa&n6l5*Z*mra90q0b0R?h75{>rg z6JmDc&^l+>{y7n`9F3!6qLM~0uRe2IRoSzX=SX5LmfxvnBDO!OR{UJ}E8{hL1}i2U zA*6uc8?=*Rg7WpPO@gsW(!00#NFcZtK9GC%n(BiMkd^q-yz-RbSSuHd28nO zqz8les6-*SHU8F2S!lB9vI!LEBm>sN;0@|!-|9k|xPNeVFHS(W-?yvVjo zy?wwAT_Mt8(oK8lfJHcD(J^C-v4QKvtBUUH-lBFlRo)akvzBqk9qddfkzIj-%D!H>+uA86O&or~|CEt_t73Ya-P-+X4teDuP60e1;mSlB9Q>gZ0-laGms`mQ`gsdA&R-^bz0v}yt5e?| z!sT4AZ;^WBiRi@AIS*ZDPkgI3dto{*_;w(SCT~9E}yPXZB^^k*g6K;(f6{W>%OU@7@9+2pGUQtl&MMt*or9wmxzvP+_1)p~hN z8(%vc)Om4J^m`dr&^%3|zKMRY#yAmjdmN8qJzqu3a--U*FfLJW+nh<@X)KaT^xBj^l2eO zwRx?yLoRjGRqS`R);4_}mfY_;WyjtmS^*kJunp1SJQ}T>&dhZx@<+BvJurq%j_&&B zdhq<2;xV2Vu87herq16T3|dW`OXNtzK38MALgV8C%AIR)Gv9joE{6?JWEU1 z$H%UDm7}l`4#k4PvTL=Y)$kH)YWvLVA7SU7n%2~UJr6Hnjse+LYuwp?j@qwX$~EAcgn!J;ny6?hQL9Gc3x0!RR!xm=2t>8mrF3340H^0WhLRsP7Aayner#*&pHxryT`KN;HOvut$qlh-! zy@V)40hb1m2uGfW)NV+9@DA9)8>wb(v9bz*kgh=iz!s-?VMQZ(zjEwZF^a@SgWbYT^GS5#$rm7`* ztQodpIFKrwy3!Z~Ml6kThn<8DoyxE#G!d;oSF;n#dmF^hjB%Avh_9~s<~3>HXjBU^ z6i)it^MDL*_E*1}tRXAdwt*LT&23o%j(`1ZFvK*u3_Z?G1dgn!Ez>tN#A^U26*g=ng483q!J_2Ai*j)nVWl zIZ$yz!4}d8!vzwUMDp1iw3ouAyE#|zj}hN@JMXJ{jzb1sXYBT#+fSDx?uwczgi3v_ zv3@o37SBd50bDMV+)4NsU13K1>ue_B>h+hEBC~9Q1!ydXA}u)v9TeH&A1LYyM-RH3 zQk-4E2DoV48#&iR6P1PiFc=OF04{*tyLP3qVTW{zn*rI;_aK?Vj83R#?x=fAZ6I9( zd(n8|ji>koWSM>}C9DOmC6()KS1yhdry5>cLN~!7$Yp-^OzWrMi{9q)PypXIHK^b) zpv>c4i>8x?T*9M^o8&yLn$p+a6BW+7q+Jq6 z!jv->)SVfB{YhbJH?FiDenqnI->HAmv;*bZaQp0r)57Jp!VGP=L4k)_8V9_sE`oD? z6#K&u)1@p8hb_{4=@j9=Z4$k zcBJmdekAw3x%jEZg$w3zn6MRaa%uw>#vXkve9)SD_$u)0RBC&E?rWUH-jhIA_W0)h z9E=viYBOnm*mxR+Fbr7yw!sy|h`s>1Old(?$)qiU8b{Zn?JFK@(V# ziJ8&%IV2@+-XfFtSoipR{l=8GZ5Jhmo@VVeYOEh2>4)T5mu)?aZe|#|$Mt$=Lr-g& z?V?`Xxon#%GwL1Mlly&5(=F>bXBoOM?#lBtPiCd)8n7vB8fop`PntfnOn%E|NHN=~ zvYn?)ynFA`!>?nk`tqBEey=KlX{2v^X^OMBY==zBm90yT2BU4MadHhgu-Rh;^G|z; zJ(Yfp-(%3)fN#E7%N0@dDb8!5tGrb?O2c-8vy?=6^bipnoP__!CBQ z{HT#HomP7fo56=>`y+E-5JBvAre$fb7d=ly45YBSQ;U?n*$KCp*8^KZQ@if!@NoNy z@MeDyImEUZiNzZE{Gq=3R`?|9HYD9)V6Q8MzCb-8Se9fFG?mI`enwu+DiZ$LTC)4W zf2b%IdpX4*c}T4Q00~{{c#>dWKeK?XA=DSDtn5SAik`!*i4{OH?Uuq_q&gOnO~AwS zJy^$EuxgKI+BZt7F3eUFuhAQnoM1P~{|hYcPFc|B!b*X4?zugitxU=qY4Kh{l+6?# zP$wCi9^FOf+&bn1>-b65WNoG-z?K-t-RK?-aKEn9l(Mn$1_`i(Qa!PWkq)hS;%^1&5ql?6{f*Va(U0L7jbrGQc(C z|0iz2Ul^Q@z((JkfQt(T@ZY%w>cVn=ry&067BKwhZUH0HKimR(0(LgG|37L0^M9!p zi2fA_RQ{n0{8a<~=>z=31o(^f|C8y7z{*}OIAYf-?X8G5x|G?wZG0`*pPkH=iaK*%PESAW* zO;JYqIXJDkthpj4P&j(Q5Jy&`%_;)YO@hr$0xhCVT>SRu)pdt2pQ>w(YxVo?<*ez) zjk@5YqI#@`QpyDk67V24hK4$zSKz(ya!W2Cg4h6XC_|CFJUK{C^?0OBI3BAZb)h&GJFXTWbmYs6k@q|DB1a>l!0%Ce}cXK zQQZZAlJ#!8fa)6Py_0WjZ}ouq5%y$7NlNCjGz%lK(hcJ1LNr4FZ;4XYvbA$C07nuO z_rOI};^xYH2~P>@S`hD(2W*qGf{2Ed14U*-eMwFC4dPjzpY-klHGc`kJ*uRZXe0-w zh6`F*@*#;pCh8m~0Idf|W>;@UJ=Tn?^XJkcJ@@!wV(6PcMFf^5&{RNxSssJMC%vp6 zhy~u&OyC?q?SO#zad~P2#o_`TnCt&9#@-=Hw4htFP209@+xAJ@wr$(CohNPEww)(! zJ1hTt-?*=8jA~RT8hb})M`y3G){Ob}zf*U0WYM0sCSIkzMg){~(k`LtKZ^hzL9zk! zcFS+!MrR8GhR^jc)S~Y_+9_((*5|^{7_H)R6qQ@2q?;}tn@BB_dfmLHz&ZZZCu#}mC3m} zdS^n3o-SGoe6K1)KdzEc2g>xzvHet~xUhI;!YPEeKk=_ZxW)r@2Fj%L$C9D>HP87~ z-lFVa!2nVUf*z9>?ZHVe1>) z*&T%fd0W!E($V>IZ!Y?025S4cvH7Qf0=alQ0`km1fTRmvDfp@+XMy)oeM>)L-`NAG zoBRlNZ2_oG`^_hntni25Kw^GHy#o9t`^neiQJ4Mkw+2w1!;i=9vwQ~kp0M}^KLV-K z`~++V_`AnXK<~f&t~d6a3~>+cEd}xg%tzYryNI^@{4TD)!A}V;pTK-~PVcZk7ag+M zmsfc!b2kC*mBW6wH#y)y?SV4#$E5|od1|SsfU;^Pg(P%SS%ZPdELob8k5ku9&(m`3 z7~yx1dW)Z_SM(x>9~<>(E2L*LqQ{ii+in+C2tn9}Dp+>B*D!pQu{LalQ?W?SaYt8? zs;&uyNlaBy)*f4%9_H_w{VV(*Wa3FCCqq#M*+E|a7AUVY*HvD97|cDDOfINfdCqnA zIh=~chPZb>B{QuLA1Q^TK*UX%NWij*)uzTDq9C)U62zg}e>T+R+7{GA_lDs}Thd-J%_x0|85z_%lH zKqoj86X&%GWkR`cD)`{N4dE^lGbNdtz7Q7j5a+a9= zebi0O{zrEU$JK#Rs8CQwv8*uY+}gFcn7@p)?>AMf%PDHG6=d8tv`}jsDlp&^Bx~j= zOjR`jPJEx)WB*R~5xNOB9`0gX{vxN4vn!& zEpW=PxCYaQ3}lJ|PIad!gey9D z)#EKU7_#T5P+S41lf%U4{Z5Dd{Hts&?%H6XJMGJ0H9c^~X-dfF)Z3kd*NsD$$R&KA zOnux_*wb-nG8kB4S|xBSn?hr>k#4UD(-HIW^8v*bsH8=|$VpPEad7Xp4hMYTkurjm zMEftIsT=#3dkR=rn+vw03>1Evxdn{m4Jym`@s%?Qyy3U%7wD%`#S2&ioyJ$ADIZa* z7B$}vsT)fzGQYV`isj004Uf%vLDYUcf(MQ7YVW~`L@pfu5E}5O-Y@&!!=t4U!*gta2fQu(sx({wyGKg4>NAk)OsGirU8ECZhA@NeA=L8bVQcqeS>o0q$S{X z+KOi}IX^zghz+sYVPuM4C@g5?ekIbnq6P~ck-pKTw^kCnIvn3mskI_5E>>R7x5?jrs7SmUUaT4Jfy(V#x!~EwzgPq#=fPpejwRFAUS}oCwV1ka z=C`Z8P4NIX*~-m6z$FUh&?sHoGbUDqd79`cHVHq$RRgZtuF$PVW?SVRaNG=#s=t2y zYv0=mT#POMm_4szPtm|zy547Luo0fht6RA{aZb9LLMD)hmpY#Lp5p~3QbOVb=N<(o z8j>Fu#9rsqd(MA`HdqG(uFGe zv*v7OHtV0B(NfO~%2s*lWG%QDK^Rx4G?Q#$UI;t|s9?BXQ)yKIS0-=O1+SlVn3trt6n6~$=Be8W zZFoF~k3(#Fmy+)@3KZQQwKFKR>*?7J@v`E~=|*@n)682N`C+V9!wn5_2{PpWsrgjPu1t-*zgMm|n<6WHDDaRr%H0vDYZ>G;sGLeK z7_!k+p}5zzf+@_0ObVDy&C=1=WE^aOyc?cr<(D`FovR;)8>kv0{;Mm)GhhLAl@Um{ z(yiL4;&g4D67DL(+_;q+MNVW}Ln)&~AS<9zBToTPAc7Cg0pj zOUjORPdT|+51Q=^m17L z?tjmH_(z9hWT{b=Rdv0@VV|rE+|$HQzN?;l^)4=tT7v;bq#LOZL%N2OYaKL9}{(~@&30Ui4d;&WjEE!Uyw85>%A@Zvri%`inLSwsIr zBfL^S?2j^OP)vH8Gjdnu_hVLmLWXIQ4yw`DL9)aY3~*7l}5Gqwt{5enCI#?Ps0A+`w$l~ z&tpsY`PF17r(P%zM;&YS%{!x2o9NOK248Y>RKP%WlK5BG%eX48d$konR(~#|tD>>E zRR#k9NJ6Ajc8qvWK?J=>@XRi2U<#=H=QFx4i7tPBN4<3m?`S3q@yb*VkyyEw!K8S= z)6--|kp}7P(z`i!;2~U-C}U0`nq)!rf!V3&1K_I?9E%=;*2U^hX>yH_VY6Zra&bepE zm76P|Pyz8Lo=)?`D>+VbxP?yJs-*KwM?TCKD?d?{#vU`vRfpGL$b}H zX8#IJ^oVud@eowsGdp`m*6oH7JbD)Q8$Xt~L7j};4hP*^oK2rOcntTQ^crz3$z+5w z%smwzo}Egg4uN74WVMT+%jn!A8WDEI!T|B4m_Z4w)t2?|mWxdQyEYM)2QrZ$*$y%# zz$Xst;+LqUf$qdxxj(zq$OcTnYniP|GpDO$bmu_AH?(0*!j^rM6i8_L9jBiiN zT#VU^=|~Vjd4?xLsuTU>N=IjMwqLwPfwFTgt{MT@yR0f3jrBHJ@*s(khLRrff}*~u z?u_}wNpIA+(J$2XAte;n<{h@ifym3h2ar?bElx*lZFk_p-o3=f%g^&>BNRHOjge}l zA;2T6sFxPCjIbUDCG$x?$>H$U??7f>LdptZRwq%YB9x;PK~ee2`AwWn?`#I61yYdhit6O_u6g)Nf&-xu9$@u}Lo2@h0bix}~Z$R6mkeuAQ`2 zl{}r~{+7MnRbE#m(i~W|wLurq7Et)WbHE_rZs}<1_|(qr?49C$1sKum+fSB`=D|j3 zzhqH{@>NnDU@w*x(bxiyd>@}?Lg7vsb)YnRF-y4ECPP04_87~`lQg2Jk$|Xg-dVYt55uObx!c^&>$QXmq=)dh zNC~+B%j+cR6c(YM#ligk_hEfk5>xwfxEcBPUhCDo>$F2>>ThnY_sZrcq1XA02D|D# zERB$`dEVPOv&KMPx+x<6pXSlERVj_DSIfVZs#MPcB+jLD|6m5F$OJ`^T=>Llzh* z9qgYJT`@Das{W>eDhs+TWk!1PhuJ@Ho4AE$tl7;wv>RJ;#gI^u-FYWNTttQt-tIoIEd45kFH`ZPM7y|71*g%KL984aI7S8 z*|~`nGw~M{vn}3<&kSfwvPm^o30tOpMZBWh>}n_9^-L-`ng(WYQDe9+HS}z!dqPs~ zQL{0;80H62=}xv$dFSUUIW)A-qkxGW``**X79-&yF6CQuhC?J0O-qX0gG(elq>~=v zf(LX}oo)1%K`XmKZH(OPi%N-t7ck7&N8;+BDgHtQu>V#8D!)6Dh*y+3#0W5v#XyD4 zIojCP-SkY}nZdeVP^jouY?u)%LP7=niRg^GxC1Jdh1YI4VhKku;~~c~n@EK&W)*9B zw#L5rq|+|;`O9&*$N3bAU8LmnCA+ytlvNunDQeoU%O9`iA^0t+Dhb_rl*TW=)a$doM>xc=QAEVINB<6S=aud)D`kUD z`h3JoBVAmzKUmC%_~V7uBNPMj=w(YobPHdSobVtlXR;au?8;#~x;P~;t#bJ#oQ*z{ zNv)1b&S-7GRDg7Nq~sepH^U)btRf%20q#Xh=tFM!pT8MY-Ell%wS|d8peX6dzegS` z@m4d#&tR!pzHoI7a-n;#U4u!l&}`$`TqdwKUEl8De3mZ1lZ^Ur!jtLEm`db|@3RU| z+IQEP%+&!t{O}g^PUFz-Ae0D0mL7(TIbe1n4CYRf+fL!M+3*IXu3NPpvb?TmQ1~aC z4k--P^@_H1)HN~|X;k0ZPP*d4q$m^*&x1e9IFa_s1a9L>hDfM)7<2awiX(|oX6agzlP|cK&XTj&1#`+RiHD0 zBw{V&*yy}(iRCGKj)0^H4$i`<7|qYV?oF$3JgAX{j5V76r~M{vD1`Kr%Z4DdSrPUK zD(6vY2GE9q5dX~Jx2>E!>95TK-#+$BJP6rUkX#+CIw9O5+uK5tsJt9U)CVa`-p?zL zm(6igP05S$Npa5~K9AL`!J(7^c+;~tlrK2u2cV9lBIXLBAMd{LjeTp@Tj`B8!!!1z zHy{U3A1qH@nRYA9-zLz!k((aU%zVn&m0fv`50*JJk+?}A zs8$UQFZ!mkI~<-z9&hU?H7nbCFzXq3ku|8g_By-fKwo7GE2E4SLybv&_v0WYPM}}g zv<`E-@aQ&z^G%CX+EY%8Mny4w?dZ>VS}}!OgvGh+9I|s(Dt0WZV@b<&7W>k+WXRCZ zQ``qB(HyN;KSCJCr>Rz>%YUtScDvNSNRKq?r?5D;F8{v~)iR?cr*_fSf}C2$Zh+FG zZU_EUdT=-WqSyh*`8xUjZAs@5=iUlyh}wxpMO}82*Or1TBN@w0Sa;>9P}{OC^-AE| zkP(tUQqg{Jsm%vRigi2LGAu5?lDZs`bx#~iw@?luJPMcQ2(3IX3UQm^V)=ky#29 z5sAoh^-$pF_-I!w#|0VPWBw1YG#?O}>;g&We_s;uxgxe+p6Epq?SAl8WMNj~?uN)^ zDyhk2Lab~bcY^G<-AuXWgh<-*$EK~ivZ(&GI^}SGP026)0Xv1?PIc?O`u?U2OQ?`X zMA%zAxQ6m5;+t4f7-t{ToisO!TB?J9DMs z66fXQj+Vv4dkS#EY~aUI3c*^EU_hA90y`CqW>dm&`Qn@T2s3Dw1OY#!Hw<5^=J!W5 zLF_HdHeVPX{(QAEeUoZq2GrlAQbI7_&_))2!Baxdm0is=7-DYVQbw#ZETw=9I+8}R zVx+>y9aKxsqSHAC#fKa`{Y#itX!PToO`yRl`k#YC1^_{OpqF4-s@l((63lpO|x+Gr1)b| zQRvmKmlib9J`iOe@nBLK{^&*CO;t zhzrI?JqVECiHbmfRXn`vUJIov7BRm4#>2vwz~}vnyUdLJw~WzJvsK**Q{yFX%D4|n z8tr+u#6Zl>QLvOCb~)*e3Vi=Jfg|jy=Tjm9cFey=0jaB_mEghBdr`=6xND?SlPSAk z#6yplE*P^QopHi?j78LMz9@q>8YX0{S}iEWz__moli zj9lVf4l(Y%!5{cdd-x~=5qN4vBrT$Xo=kpy_j;{sF#wqL1LM}h>n3UkYZN$RM;iQ> z{Car=37)5Y?R8OK9w9QF=VStpUarM~zB9Y_*DWKBF)%QRcX^VRM5KH^P{!F^4sBUMV7%MS&5F5e8BhkH2NIBG`x$nhKPVqTc?S=i@~?MUso! z$r^dcg?7m&8WQ#$4P}x-%O@XlOWLpJwhl&WpoFRH=;J2xm6A7#M@nG^CqZ6D?1#A1 z2Ad5sX7WL>A=lDUhAPykS$}zoX#HU-2CoH58+4CLDr04KdSvQ(8E_V@IN41Y1^u>leh@irp_c4^``6w|t3+k{)`7=?Zv z-_KvlyFB6)D@wncsi>W0*3RNu%G7Zo`; z-x`ngOe5RW^7WzU(z(9d^9KYy^<(9cSG#|{2}@mrwP-fL`;WC*gY3o7M3cT{Y94a$ zxJ9#4(lygscyIj6pYQ3!!M?FVf+?Qmdq_Lh?yJ(sp zg367j@+5A7hC6R8BN5-goX8%2h&RL};&8V)>_{_RaLN$dO+k-o=}va5XJ$XoXm!() zW0&!y_jVHrrpTTr4?h>0ec=gnxX_0BIT;zA`UiBW3V9hT=P)H@H9#fyrn_)w4RgW-#cGB&c=csDS6xS zd?KQ7b|{pTck`4Qmzbi9#atrT%%18)8I3~Vly!qXu65?Ym^`^+3VY@aw5)PNv6;9Q zKQ%d_GM%vlq9I?ESl1js@t|Km;tKP)7R{MS++=Ed;YN#B-3;X<#B!+noXsZGM_J9l)e_|@m%S%Adl3h z2hwxHOqXDJly^k2$2G6|aY3`ua!&dv2;1ecs|=fVikb1-5%3;W;{J{cb)xnWoxL~( zID=@4ScYK|0kauuPvdkK0o;Z`hPrD_!LyySrLVzxx~Zv5QkVW}IlI?~)<-B>*HVkG z#qc%6x~fse!Kk_-_o2%)PRJbHJVL^?#_76^eQ?_R=Ph;d8-(fENGUtMpt@K^f%1huxb%xE3#!}0#P%}uvApJ z6K*965O9qYhe@+>MO>;Cl2P&XiUF)Y0Ozs6he|&i`EcExu6!8W*VzVX@874346z>b z9OzOLu77PZzH(zLRlF^sQ=-y{ArXYcl>Vs<@T#X@!Vyr3DY|Hl2fk2|rB-Cw6L>=S zQbIyB`j(L$xY%JaKS3*rQ@N}HBI?0rpE~!Z2EfG4kTgO7FA?WE=Z35vh1F=1Wi+Dw z<7PD<*hF_TwC9o@4Wf~fg_e-D8x=`<_tM7}`|8xrR&c+z0kuEl`b4{o5K9Jv0}u z9?<3)E6iOHI*uXRFt%yBpTvV9<~!0h?RxMA8)zk5S!4W(QTeK>e3M{v@j-rM4z{n% zUzV30elg+8(~=MCuwSC>N~PPzXME86dux{ZA?0pl)0qstdUj5_SlY9MH}8yiZnw={ zrSr+s)!cJF->Wy1<6LCtW6YmtC)(O?K1CJbCM|z5Sj(s5WvsXRz{K8pC7|9bVw_+l z+#K-=VKzhPHGl0#8`%-^s5TBG$uva*fXj6;ZQb_f!1Z&9-tod@_)SE+@ETW~AgNnP z)FYR(&3qZ7YgEFc51V_PpbLw-+B%;CE&CqJl?c{OeeF<5(H~>mU7*0(nJSX}ImZRe zQjVXURfUq?ekZw^^X5hr3c{K@LE%kptQ2wxY2;h(>ve03`6n3X*Ts+r zujq6(;G(Cw*>?`+S0(l*h(D^F1xz5Tw;Y(vHbM4sA~d|J`WlhzU)f{i#JdQyzOLt#F1^bUY-fnHpW60>ewp{c{R*P5 zNKWUXj(Y>9a0V5O*?N=Ev0|qXwgx#7*I}s=M*lEb9^W`c>Y+4u7+I9SIsx01RSnk6 zHson@lCmfkh@sw(kI;TH*9&B(rEekAl$2JS=@D#MB%iw~N|;p+nWEJsr~OyOWV)OA zEZaH>EAgvV$lKUYV9t| zO}GAS>8_0}N7r+05<05cWPgS2mh(L6AKGfLSuAGHP+SrdJVZc-OOxFd>p^W-4iQne z#AeXCIaX3!wLHwgSduHf6Xs(YaoU|N0;S4gz`I40<+#GaG6{gtBCI5sWAehIi7{&M8pT1^=4>s(Q#3sii0qd-ffVB0rGqZ*LeS zoNsaB)kYjo-J!<$0_wSCQPc8Tjh)IrSdu@0xWVmAM4noVv&^&@+i7=ufa@`Xr={{j zBD7_!DSD?w%-Vj7n6wdPt2H|2XY4nFgpcG8DEDCgtyP2;2}YS`H7tEby|HM$ss@Pc5` zoki`G!)L@m)(SgL9j9Q3nJnB{dm^)VfyqZajY!3mRj4gYu2tK>SjbH$7>O=HHAxQy zQTjK@k5Oy~8`n48v-3@E2GUsT+kL?nv$q=4rQ{ORDhh~`M0{FUCW7-~gpm|(#gIxT z??D|yel-32^){E`;;I<| zI7*?`j+-bi)cqr7svCAGU&-vr>t#V!woIZkKTrj`P@NJtvbWUS1$ZFf8G!ew1$A%~ zv^6&}q2L3RzN|s3Bp-J>!|M$Q+eSZDb6{so{xsdfcc~q(a0+Mmh3=eCxTy?Qq0cQSxCsvoj{A0nfbpZ z)|@P?1nexFI#Be2PX7@<|H`O;HwqirOZ=DrnShOh8H!%S|1C))q#B zwr18Q{}Chqx5JwCciaE(u>O54Y;NGFWa3Of@$0Xa{4YDT!7pWM{2#*fzm(Ay{~udw zPyZjUvopQR{~>K={tprQe=?#h|J(Qf4oYl1!w!m4&rDCz#ZtQmS{&b&gdF?pe`}WR$^UR)j z%tFRb&xy#dBklt%3-rwg5(yD#_*drElK_AqAp-@7j0XrPVQj#@hb7~f!-;wfAlR?} zl&Xme_M2zRz($W`oDuE;*wC~4hhqqcD5{D`p@9H}2MRFxVG_wV0I=4vPa)=$gUpHb z733ZXsDL0v1#))g|3(#Z0l5=&0U%;xQU?5jq9$$>P+)+AfS&qI&`Y>!h(NBu=>!A} z6j&d%2t4<6<}8Y;>T9E;;t-eDl)(a=)b~&T-umX~{)|h=k@uloK)(H;r$O5Vy#bI3 zz<{N6472=0WDw*{@ED+=dmy$95GdCXPPc*FLJ9!dw*C>RbbSDjAwLFxKf(e4_GVWA zM1n=W;a{2+aL~moUM|f5^GyU|il0W3zamLIKr-?1zv6{e5};@~j=U97X!J>weOI z@M`KxBP;KCjlOsNe^e{V2^awQ1r-nk7Rb)0=Erp*Z7|}(7Xy9unWTau0TKeWoh&MXzKBn5RdUg%Y-93+Go)#E0oB7_7elGmrBtAA}BIFO)y#H?5?NMQ{l%O6V&&{)38n5F)hSa`kfLVDZ!OqiaKf0vr-QD?>=& zXaIjcxDjWSV)qVF14AtXphm;w0s3VsPv0$9A+hLgbuB(^z^LNI{-7NKK z%dW9Gfu(_V_;mQs&+iE3us#L-2wx1dLp+i_1$$?ktdrE-(`@-?YjF3ofZBlio7zS{ zAS{g~#Q^cDepX9XX0Y?Vy+6DHwP+bj5;wB(-l5;Uks~XtVa7^O{P85S*N@O)%p7P(75rid)Dpk`yNJG-h^hy zbBsl=8L4!6f3#$1nlS#hlIYfoySLh7Oq{~S?zI!3xUok%MhN6tli^|N#_z8ut${Qt z{N#Gtir%29N3xmA9SVbFkPddM_&kD&Jh!2mYi@hPpslyPiED*}rmdhxf>bp!b&(_{ zNiV@^GtEcXRohTM(Y5-t2r@5V0XyS4Frg$PZW0r`dG#UgP<_-EQdb1&hlZH*8Bjk5 zv*ga1mv&x>_PhcG&&?_!-*7lUqB0lto)s|eUrc-Yin3+g&;|rogOnQ1^TcuAqmd%Wx4N(=(-$QLRET62OKFyU5z=_q<9dJv5Xfb~vUV z@7=T`R~MRpHeKgCf#p7C_JK8NYjZ$P_t0R?1_#vMOG%ZyCP*~&qYbJ&yK!fsnT+jB z9lO0$4rhZw&m7Gk zOEIc$^=5kL!o&2vy=pYVhV8v|;U=NFeEzf$(>byXFFf7iECk3H4<7DgfFk?NnHL0Q z3Ut#(_{IX@HKr$m#+9Di->(O|cCE~HB$IGeMeYv8dpX$|~sqSh72h{2l-weFI z%QI5Gc`KZ5yXVVq$8&Q}Blj{C0|qJJ*duNu8fKr{&$zeB_)x8J zuc1rlC=F|fDQd`lAZ=wLV$siy#n)xw%@wV9f0A!(L5Fuz_en0B-o?1j!kb-$8%gqO zQ0FL)m`%-Is7K}(&Om^{NBdVrbT=+<^DFq7Au1YQ`5N{j4j|?i@ntL%vtf_2RMWCN zT{tT@rj?a}d*~g5Qz&%Yhp!eQU5IKQird+!NxtlhRSP?ifr{pjk}>STuFlgtbP$MU zOK+wqHkfp{d@>2^Fn+Mu$W0z47QLBW+L3g0@ z8x^rwHdHFMnV_86yI3rsQ_%FF`$*d5(Z>VH!C1zk%bZfXZbyrU^&(~y>}Kori72Vq zCsywL>9j*jaL=Rwdm7+~E9?#3IXWnsxHP{ALKs=_C%N~hXPQ7+PB^Nrt!`bN^`dH~ zf*@dVKj?WdC)#7zU;%wP#Hfho!9RPtnmKLOA@_6An^ML!kdyVV^b(uhtcR@&Ww{3T z{SK!V2vR{1{GtbE?lg(`#k4U6b+*K*6Q2^RWI^`PS#`zw&*!Qa>`Ef&GF=M=A$rAJD)D z%dW9o1u(8oo0k{M1zuW(@~4d+urzgiX!_2Y*`&nUYRt?;)XXvDDKBd~4b`S_D!|S0 zs*N3++YyKhjItK6H(^xQGNz; zR1I9V`dQi|w!{1MQ5OLfHBvo$xs>FZ5i(WG4ytbKfu25Hv52tN`3dA7b@eT5iD!BF zGZ3(;fLykoi@hzO!?mrqs5?mr0bAFT?frY0s11)j?StJ=bGmg-tyma;OZ1!% z-~SwwPvnhw*c=e#tNMDriQc#RLVw^tk>BjbKSeB2+ux8LL&(s!C3nA}oo{@Zn<_0! z@}3k7RfO71nbWZ0ULW{b&D~AFDkdrz8Ty-l3ve&N8s_sn<2X*SGyCF}1fYjd-kp6M!Hyb%tc*&RLY+YUkM; zN?25Yw!H6aiX@sjQWpVpJz3^UCHU48UO24oYU%>N>wt><@am3k`E}?s3w@d+ z7DM^^e?B@dHvZ9U_qr0b9Z{>C6~>;Who*%b0&OK@bHP^Y(Y3*-^ym}^C|c85n`fwf z0CqKku&YGg)Ty4>Z^U0_bvJ5x%IP9kIZ;V5_1m@i^ONuBc12zrfFuLWI!@gA2REhL z;$H?Hjhb8V5;C+V!atiyIt6Hoxhi#AW!*OPRC+U8!F2^B^Gd4o^TNHJt3|hxCy~|` z6wp*3QwB{}e_`_=GiT=M(SA&s4o0ln^7fJ;LtWyVxyk@v4D*pJQFLz^o{C z#8{LcCGVc1Dlaj(>;wBhT59j5G6r)s=hO;lPDi+uwgkwHiM))Ebby@GbZX z7bnbH{4S2p9guPC!MBC1hf^kV9yRwTQR@@yUf@JDOJ-W9?n!Ebg@UR)J7*`8^;Y)$ zC?VSD>{Z`mUZ{g;qR*t*jc13YR<4#kr`^X?JYuXXUPJ~y7j~_5*HLU;GoV?Ic!bv4 zcBsih4qDN>D##9czl*)XH5ST5N+3%&LRj2o6x?z&i+ZVr@rz8klj&z24_Wy$N>ERM zO*t-HZ@?6an^pFdB`nX&D z6ne;_-wV)>U=>hI>h|2pR3YCxA{Gw+0ww7vS~9kI@#B5DTGq|?f6Mr1vni*R0hD*F zx3p=Mf?M@8avM9PTm9yQ2=Mt~;K#^e>y@ghN3kz%hG|u;&A&vJZX%8-Z3lRnP@Tm> z&sAxp&%^2tb&odfF;cpN7CW@Dmq_m9_E9M9jBJs!HN20*7ZZCmVNRd88IhPaV1hFA zNSjWZMNFFmSNC~V3h09$JY8js%a~+$qYm){?#E=*Xc|qBWxWx%ct?G0K4* zAm8tPV}e=H^vwt@i!7KbKvEvjMWD;gaSX*r&VO^f(awDT3iNL0?RBYlf>G#$=FXP~ zPY~u?D%1}v?UF#T3|vqAXcCSDbC{F0v{I(q_I^UK(Epm3tyaaq_Lij`5n~oT? z!k9N6*e?rf{MZ^R)V8FaSP`oE0}wjzrpg z&9zFjRMtiu#n*R%t7_NN>`;ZZB3BO^%{)OM z5kc*y3*V20QS-oIM7kwo_(H7Z`|k1>uc+RQW6B!&8=3+3kI#)qWJHq#`kag_`G`2q zm&w59*jv&)J4TwcmPXjkE0mkslSC_vHGEF6Uk6Du#h43@`U-_1vUD-_uDUhIR3I>08vA zJA7K0H+X)E@BH?BOjnB%q9({h}u|s_1&i>~svvZkJ>?qQ!6kFm>L=v|)htiLPB-Cb%%b`UP*a*|8+te71*CYj(?IK={FQ`ZRO zb7}r)eqiSz*D3)|>`L2CAN{w+$@V3VBw9ZMgxpZrUcauujdgd$(pRgSbpFh}yy=ci zWtC2lS47PN&FX`=t{tQN(%1_hauhl@e9q6yg0E4PHA#)9aII3{{O^Rw-KQ+h%b13F z;K9XQL@PK)8{0zFgjpwglrTm9sc`eVS_LmMtV>Lq^Mh?MAT>0T5!o-RsTB4!m!GeCLB6zcQjd zvjkV&E%wg?Gqknp(x2ZEhA|2TL6@OGJuRGe)^lXXx@_=Q+8BNBpu32QAk&o-L*di=3$kSntu0knt*xB5BRNW z|2VXNRgT3yj^Pu_<#a5lA)kMdOCA-vzst!8BYXmzH#-okR13DL`xuW99=SHCXeP4% zK=~JFOf0<-rJ-jrWJcoN!pS8iEFCNxk{=pNdva5LULLhOj}j7PjMhO|bOAKa^)OwT=gdp5Ig&&zFc2qWgyX{#v;9#}6(`k&wM7q|s}(zg>B+~{77 zM13xuleU>4%!Sh5IfO+q1*A8h|ng!5cQ7(C|OheiBpqOJ<5y%k*6iT%Lm3pR z3O6b;4OjStw%W|r&P7S>>rvs8c$gvp4jLAUHi`3;i8#(7KlX|_2ITNz1yH27f~u4c z`#VRElfW}Pbj?j1kLeZYUxXkv)uh9C@qqg4b?_d^*;Z%wbIj!e@IHt#%p_F&QDnOx zn5)>WFty421j;5eFo@;V{!TL>0%B((m^fxSeX8K?yzRH@exqtj$Ndh8x4)h)gN}SF zXQVYMdTGn#OVjI?R~rh@k3tdr@4|#KQ4 zjcQW_fopFqGt5iZ1L-d=%usjfR*Fa2ej}(4@u$AhsW;kB$vpq6N3(FkcbLv3Ec_#_ zdR-Xz4UXKFBSi=NWAZS6GnS9h4^<__gDJ>KF@35ifubt!5iDQZQHh; ztk||!Y-=SewryLJZ+6Yhf7g7w_8iPvKV8*b)qT?M`@8P@dd2{keu-rBe&1odrIj=d zN9b4jVs7L{caWyscCMf%OD;j``^K7~RV|D8vZKgg=nP8ZL4wGxAW>K=C zLNhS;wj(F6$T86MD{;Kaoix{vXkmoq-ymvS2SXz=N$~lpdEU0Zqyx$y_{B6#c@icn#02KV4G+d?kG(l?0j2&D$G-pXOH19Qc{sbOjlAM#uXx zCs!^u9e!J*gI@t>l$^%Ng+U&0av`N-TnD2wi2G9?uiTt(t1ln2HZh$%=M-y%^jZ?9 zm}hp)NO2mbwdXlYRis3`J^ZJBnnAT#2V0SeU8Q4a@am1_J%VmK87%KH(!wfX22Ca{dahg^&fcczw_9L2?{ByEB*^FemhzI9bNqSzqZI_;$Z&& z;<5P`h5SEwk?Eg!@&ESA{EHO+XLiW;kB9r;?2v`y`#%4%`uWW{0qp;4^-p#PUZBw7RBxW!Kls7$B4GKo6fWdu!sG>}4TnKsB01*E;V16Q|ygEz*0{`4N zxqCaY)+9`RgngKLu(BJVL3X8K0j^}YdULz^J}oZBblUei7VpvXuVrw;^3@wK3A zLUck*e)!-z;58DtCLjS|PJ37=%$*wos^y$z!XF5Rot?I}w%p%78T{6y2PIc}e;hCa z(7zB|LD|}UDgJuSz^8;>*LH^7t&>1HIN^5$>X5b}_MjXAz~VqK^*{qz3BdG>QgtXm z9&G$#5@>llK%pNFsvmp3;Lm3kK>YaId?%lgpTD3$-tgcW>ipNZ{PppFq_OtGfPjOt zpelR(xP-E;O$#fc4G+2An?xQ9$dhu z;piI;{B6R4K}v(Ymlq@4PW0QEuj3DjI`G>C9(TXg1q2AUAde3XEdl)$)gDUqcJ}Mj zKEhafeX_P5?)V>>N-N;uWI+(@e#JShPN1RKY4W#>>>Tp z5=>w@Vw(pMT208UsOvzvTJ5H?~-`zh=SK^e*}lo~Kdf zcf|36fUUpAH`C_%73+o52tNPc+~aZiHSzEmDPgNFbS zQc%Q0(l=a>W)t?phFi-@)xFv2fVz9=+k^cC^DjCAtqbJZ`K&1Qr}W3*sPYZ)d-Mj< zh1?JK7wA(B_fy!`JI>YogolLza?ef}|1gVl7FuQx_>u|hWMk-u|Fk1U0;;80K0&-D z_|C0n#lIl+goGNuJbgZq0tapMp|>{9*~8u}HLKKSPSX@ythWL}$;i_HIXxyvj~OnO z4sE2pl7_Y7e!tJ1sk7(5BFuLxx!1mXZ67g9PodaV@xx%%B{Wx7jqDfoG34tEg{V9v z9$Uqg9VhnYZ7#)ZU3R!#51{9NvE|p2(;IPhgrQiR#HTmfQ8y|(qz)m2N&!u5G{MT( zHB!TEh4;iUpfD8ajenR+D6trk)}5DeNg*$TlPF42NUuaMkALm4JNUR3;vaco)m)3| zNqf+zoZND?C^0EuDbD6+$HT?eyN_9SDflw(sU-KDv!rp0%=~P!%!LZJt@p4kv&!YN z`C>6Kz(+DFEZ7$zQHl)Lw)IB0(|e}GS0dcg7w}loIVrUdYGY0n<=&SCrPdbFUvx3% zQT=Eh(h&D%K1nid@Dp{E@o7U09PA3M)EQIZcz0NWO`hDCE+$XobEqXnfAp5JJW(3$ zG2zy73XJ3%K*BM0iksVCIPa0{RFcVmS>Zx0cB&aXweA+4OXk`;OO*~fsa^>^j2F(g z%@@%9>eluwyWZaqk}me0UXq1y)yZrPL{ic)6nyfsqg-j~@g#Nl&DH3{s}=j>%QEgZ zVlQC7rF42$3sVpxeW5U8P(=Mt++iIWlSCmLSJLV?cA!(cmLckpK6rqP8L9ta`2*>h zWrm}&#>#?KJ^+vU@b0>1_of}#78imyJL8N)6REM_Rp3ne3AE-W5M6gGwa~x}&Z5J7 z98j8U(eV2Py-MI@EpG8KD z3}FVwPaiBlhufFT2@*DEJcM5brjsRqUT!;mrJ?z``yBS>U$0nT7WTa5;E$`CMfn&x zPmD>ec}MwnV3T9idrDs*H>~8@hra{5L<>sF&kYLPVEO)nekwx3{un_~2TJ%s$p$aQ@Z-FO!62JeP#G$R#I5t-aT41s&fl zJMDP!Vli{w0fFpxUF9fMw!t?&ytD|R49$Du1KJT%FT&F+UytjA8qY|50}AX2^Bs-~ zp5yIM;}|JeXMv)F;?u=TiY@ohPDmgrO4I>;gTzMtz>wzVs>iUHf61o%X3hQd5iOSj zZlEf1NbuYO=$&6f1vjeCa3OOjXKZ zo=e^wnC6cgw`WpIF>FmSt*#pA$wPKbKKJeDsb6%M8l2qYvwAzJd(m$Whnc+WGnh?x0~kNjZKJSnRT zuq=qQINyqtBIikSMg?Oi_B*OsUB*UYyF8oy`b%0jW^HYKiNi~s zeoQIn7cnoqF`%3guB-dZVJTOFj1r?T)el=^*0)3YQoSMRB=@3ZcGc)N-EK?k`;|x6 zQ?j=@r=Br+Sk4P8=mWzfFG4$aziKC$wq z2!gZol}e)_@>ZWZ<~cO*8>V9%{KIOW7Hfu9WPkeko=8|x+;m`+9OTs1S4c@DcA2(h z8C>;N1X$T%a+-ka-Ndgc6g7MLjFaSS8#}hpIXNPIb%QJMYVOC0n>*m^I5jFMs>?q* z&bX}1ay(j=5XFD|63-4l(m-puH_X*^=}oEk@c%<4-;B0b5Ee9|pwjMQr*b~aOQiP> zjn{Zri5S=FaJTd-0yi7Vj;9VLYoj!}RBkE9DxDcXaO;AnUAP}8on$oD-d=Z1qI7f< zw~@Z-yS~>Hh+o?=GNNE&2jiwJUZnu+5}Y%O%buWDF%#?#0;ZbsB7J$Cj4JiTx+*3QT8zT$(|HtcQMYeK`=1YO1A3q3!OpGr*`{iW+_7OfS!XNpb;WbTT$EgO+^L-|6+!glX*c$9N zsZnf$)G}ZosY)ZcG5zrbb}amZ0+}W zd@iTzX++VOZfs~1J6e^wVi!%y@ew1XPS+BAkYwt*1H!3}8}(EZkfH9A2;2_n%sdw; z0WeP8qK|o4dYv+HJyEr;ngfkpcasRo2ql$dy>nPSPCve&-?_0fq9f1scvs?-8{#PAYTUs?}8Fbg)mu>JKPzW#(KUcpuwwAL=iS zf=uNQ_K1Ps=9~@)18y=3wW*v9{Sl};3ERxtFUMFM^cE#Ly`wX0V^P^Wg2on{9p#Hq zd@d!(V1_g=QS{+6W-64?!3zp^-`KgKl(IV1_!8OXw5o~&R3UL8M=&lF9bn|d0KZhS zsi1$EL6poaIfmz@#95ad$J~f=q5W#iU4h9VMI99|?W!WM^@p!g6cicIuc(L!D#zw| zos&7ImQiOVf;7FX*;i)>folyC&i3PgYIk6`9yXzr*pN$GH(x~s8DKshd>imCI=wZ) z>N(~D%fK=d;hHsDNBzcNk`rUA%>)uB=HEPKXv8>$0yl(PlYWU*LwXCZ$X9lEv3EG6 z1|#X#KCNn)GXv2TEyf|^B4a1>s@qA_$K40Ide5%{9ScqKB%jpg&to~`P=9A{^5dP6 z;V6Pjry`#|yc@Dd z>;uFYn)YuupQoqm77ZG{%mv5N(}ujY3G5Ees@d#Rs72MHG#MqT9h9w`R`E(i?q^hz zYhO4bm#$w|i5ZPAw?nt2B6@RXCmkwZB0Mz27N@!GPtgbBW;ndwEW8_u(?g5~3TEYu)l zGeb{BpS3#15($Yr^DHA8=5|BpcklbT5RScCDEc@MZLvC$MIrPHRg6ePf`{J<-EW;o zdkFDA*xpZ2#Ah>g8?!A8Z%Ve`3N5s@5-BAJ(0>v;1$DMO#4`VQ2_HfHE55OJZWn4q zUjr9X0<#|%;#6S*U>{Q6C3ovb=B?7DeWg|}sMJaYsz(dM0i?^#>?(wsf2xx8eQxZcEAXJ1W_=f8 z>dRaDgW46q@x~wyRT2b$));38X8}qvTopviPp!JgUO|`XJdp#o=&>$XnDJ zYY^Frrb8U-ui8xZRfCvE!R&2Akz?L9Cubzx zkXF~2HGfPeLc<3#au&X%!ss~gV)M#2dGxM_xsWO;zDZDd3gXp^qNxIs5WC~*h3}ZC zACN^UoZCPpMUOl|m79jtYoOn&yxSKTmudmjZ-r6RyxiMIwzzT_=G)$IwoPhRA9p*? zr$5EX33p9+kz48h*^YAos8?QiF^NdauqH+jZ@i~5K5`8DuB;F;%DW?4(f9BOEYb1@ zR=+-0-0hs37je}qGigtpdGh4)au0Hj}&O7!*nAt-oTj>8S?3buQ;WaK}m)*I(32;peS+br`EWbW8|2jot^6r zoS>C=AYHY%0r@&cr|B#Tw2BN05yLKuBqDOXZJ-pab_g^yqnWad;1Pf9D{Oqr6yHe1}k;N>73M;}Yk z>1Yy+2Mv?bNoukLt*T&@%of>rV$5SaDfH{H|kRQEi(gEr_#Y{omx;(2l&$xS& zjt9!x0}IujTxX<>89aDIEa1&)5io{93sLo|^T+I>u6&)k5WEDfITq`^rAQ$4(Zbw$ z%guu8?LR5y%_HBh$)k>h@9tF)&9je^<8NS<3JH0g8aanKy{O%Pd*UEd3AbpUQt+f! z6yf$^?+wwxR~t4UeHl!v*Qk8S$8XLi#;qPOnL&RvRf+JAMeKm}sSg$b>SRhLguRpM zTv=iD0QUwaduei3gNFQfQwbO&4(A=KV(Qo>AAxJnyWkgs6Ff;elAsO=RFCUCmx^Lf z~T21Zwgt$c7!YDhDWC|dORl5VOQ?0Bqw&xY7 zOGzicQO?+frbJwzu&veg0>k;ywvlVDUy-u=$|qb4kL(rJx9RpEtN@J|Q|eWy(Bl38A<#lb5|r3{;qS?akdZh_LE zzf3y+*#n!p3>;S3imr7aaQ7Q z%j$Sc#e`NfDOhd|j^EVRkM%I>BquSP=1GRX)7L@)Om-4vUD^+_IYOpu-D$3U@C;@% zft5Y8p=TQ?qLt)shgwr%6BU6V8WQ+wYc{Kt%L>smV`7|B4>JN;h3X^CWRr9}K9zH7 z%v#y9u{c-BG|V8YhLyVCwi>W16mQ-Bcyv|?|>^WVDqDXp@|PURJ|L&&rZ4^6lv z^)o3kugO3x*A z2#*1);8iq-`{WsY6<1r zduJli(q9q&tykHviEQ>Z0&z=;QB*Y=IuD^OidC#{Sr?D^cHm3J_>mmOu}N+O)<#@x zCtdfL{Ret|Q{4~6h6&ge3S!}qqNW=;QhD%dyLf|>*}Xk(Ow9fIN%4hQR-KEUZOP16nZ6T$zgc3%V(~hF`W$(z^^V?p(9-;XCCST zj(Zugf6YsMDN}3!8A1}j$hRR&IgkH#-epg=>9s%X;3<34?ONA+-narSKQ+8A3rSG3 za=#`l2xMDcJLGrDU&7ra^%_hK)!LqDly{l}zhpt2iuJt?RIFXJOC~bBvdxuip9dd% zWvNz0VGBeMv7*#+J~IF>3>+f9meyTjVK zz1m!)C6FgL=SzN_e~ezeD_c&VMCq`=qF5U_vIj$`@~%DJM$#GA*108z8_H^S!dkrWUO0O!Xg-M8p^dzZNd`%dk z!;?M6(06$x6E-+C3rfrvDA=21LuKH+TPRDCQD@Z|7M_;e)!*Rm0xVR}R))UBoP^&Z zm4hltZ2ZYkr}P7>M_f-QPF=U)Y9;UvY7t1-dT^&8Y+?#J5HrU2bcsB(b-~aOptLo} z+ZGoYuq+oxQp*(NRo%ndtzL6~=f&O@vKhKdF_s7o5(uPb?Bq*4+xKLK?-Z1PM3Mw{ z2C!qU>&-ZPtu*@ax0|%zRe$#u)ATBQoO|q+b8do5p|MQd14dR;&3LI?3cXrRc&9-u zYbhXAD>=eIO(ac1Yh&&$r`hYb=uoS#Kg-;Rn<_@Ra}2-65dYFZali;O1~lvmp3d`k z?Pw;Yc86T>^}v^Cm&ZWW`9M|IE=fzla}wy00{TjXDLDPq!A0tI+1LkZt{8^_IS=g^ zL)J-VgQ+rhj}`;D36Z~6^%=9cSUNa7+VkJa^&NjJ3>$noel0teS^M^fXJL&8J*$IE z-d}ZK?US9+clsW^V?8-56^Rl+t{+Z3GNRZCU)AEBXF7{mYUgY_s{iS3wL#Cs$TZz> z+;9nE!MN&tb8Rj&Wk|6SPcE-h7nyVYf#iYtvz|L^iiiG_$fQEX;0j$9aNJwK(9&k> zKi(w}Tt?~j$E0O|kVy`W2EVSjVQ|T&Ot00|IrI2j}m*`c@pQ0p)s;%NxyoPcMmBxmHy%!mLpGVV*|~+sMz0o7ONA~E`P=L z%8oP_fF0~Wf_XBQPN%G!y0gr8z@B2Ey|m>l#h7~90$s`0jY+3DAld^5N-y$@z?fOk z?vRs{A2adq$0aWGlqbEI+z?TN!qZ;W3R_{)A^$EUW-;7ap*%#5hjEJ!h_~r8Uxl+# zjm8m&Hc`UZX)e*3A>;X4#@#jR$U>`$K|BN8P*3y|yV^@L;brznZftG&T-t=aP_oBb zy8CwCz)_A)a&i)m?u_prLftc;{$7PIegw>M+MN-K4uZlDRgO^(v1(X%_5-~Ai~L!U zc*L}-TWFXp#%q`GW_h%Wi-(qv46*mFID=mz2K46h*-{f`AC4vEfA}uAlfCIrpcQP$ z>oXv0F^3x3m81D^{|19a=HmFU&2tKU#G>$1%<4?bJT~F9!DMy)_HvAAK6>w(RO1p{ zVj_8NCn>u2dG|BAY5$@<2wI9r6oD`8eQN9*sy+a#?j2nYDiex~71G_paBL_hS~A&J z3s40~Ns3^vL2?-TgG}<)7f403F>}eS`R?#&AdqFbxuUC95litfPXkYvvqfmcPG-Cv zT{@QFPQU&)aP$E0lNUXBlZ0q;fJIVC5sQzeJUZ%NBu+eYxgblaH-)9 z9ZK*Yd{NVP!n~22uRyb4RF(`=6Pkx zIMlz))olqA2;vsdC#MIUOAF1_Cq+~lTB91F4*H^h1w$ylH!X547>SQQRhUnS!hMO5w^ox_J(nw26RbXB90F+~NerF& z{YU7Ji#RJ~I+!1&VRrMSdr0I&cl+&6&ukb!q2h=Dy8P`}*XK?El@KHBJ`p49@0`CMFEdZgvd+cY5Go zS%LqY9$^2+JNQR>;2+InHdeNOpB`WZF#SKL2izgq*KF3h3(8g-UCVfgDJ`$M0Ic7_ zIA~ zl!o+ZMP~kh$sx3u>boZre~f;}9|?(xsPA|P^0)q;1BCiu{D{%6A)fj)g1z?s(8wS` z1)!e^foh9rF^|dU=#O`Ipn*K{{6*hd>s-QK#86joOd$n%JH0ZLZ448C-eu6&Fzom= zSp8ENp$`*A0nWmY-c5NRbpHWDc`z89-5~owPtdvrU~G zQyU~E2BN?OgSQWE@BK0OH5D6@Kjl|l|M3+10$L@Y{t^Mi-=q8G*)T*s2_4}N`M&ny z78UZq^6;QM3HB-fnW~_Hb%F?mjQk4(NQ-1 z{F3jdB~exaPfX%exK#E+N#T%>EZQSdY-B z-|E+|1HWHieplifkO*HkM;{YAU-dye`q%z^`06}wdG(F?VS}z zuM~EE%y9mKdLkg&kstodvzgCoMj~~b-~ZZ#))nj-#~)HJ7%)jAL%RBYP~x6OeddG`L`E!*nlYlgeIc^sB~u(L6EdGGr43E|KGl!v;RRucSA~8IDeE2%4MIDqIPTQem3A>yv)Z zou+uV(M1ogHMKy`cbJC&{6Y+g)br!=JpnOs5&YRMEonMpr-)yKT_4Y-zNd9pq&2B0 zD)ks)!}lidxe&D4P4OG{8YnqevCfPspMVaj@>*zVnGF?V@ zhu5Dho63#sr#I|!lk7O2hK7donyXhs0Jd}fzDi%nVp+i(63w2*;n zTHgxAU+MjQ@`p$RU6DtGZLdDf#%0Vd>XW4_B6?)+B?8ClQF0`T-nun)b`RkzzBF6+ znT#jZ%}wrVeXrKCCN-QCS#t?lL7YtP3VghHH2!(@W-q0iv<(Hflad%uGE&3_=0#~6 zVdYv!2#9xzBEmMz2itC8TRaLWjKPhbv7B0+ZOMPYMo9Qti!>e}oO9_l#{cu8?XaxL5Hi|nS zUfutBwFwzQFNdeA#JVa~V!qsIG5>VYt`k}KlwU`gkS(h)&7&3uT4cEj0GBKzu-8YVbJ!E1ykd3bBX6XM@**m$E_GGP(mYZu&SIdacRt=kTnL9c2W^ z(a^lEA3*M~xySTwi0YH*_g;ADJ)@X1R%Z#BMyHU8$@frk(i5s`&1F_}e*67+RV;jp z#Gk!pif&NL9y}Z1OxCfOg}91LiNnCcjVSk)u2#l{ofh&t43x;s-2~~>t>+Cpvdf3U z+Jf+gnjd;)?V7{cZEdkXN`h6eHk)wjbV_r`K^n&-LglAv)!?lBh5VDG^PFze$Kl)~ zb&;v*k9w%CFF4RYXLvcA^aP>XvZN<3Cm|ucI8hEcn!^e&zP4Vsw3lOUm(hQ4*)w0| zI5Qb_B(;sy63nVjLt^#Db7e!J2Kyycrfh%@OeTCfg%u{dr!b9+{O|UwLAo}4nup_= zTS1tE{a9o7?vy$h_f`>`7x0<1P@U=`DYGqumY5~ZH32BO)4X5ZK4+Co2Z&zxRUy*0 zSIenc1_UCTYYXO|^)RO^nWk~Dfq{S?Usf34s4lhI;60N^+^vU^S`%X0Y=Ke>O-hwV zo{e}5V?U#A&W9l7VxwU4S=^PhuJbj8*3^=}OKE-NNeX`n0k5jMjF#q&1tlY)g@;;F zruZLCH=izgM!zP9e!hc{sHho2G-!x;_4OOH&w$+8x>2`>#ZFz@kX1Vgajl;YYxfj$ zpE^=hFJ%N=cE&T;i+^2FRYBJdJV}dA!u`h14ss^182+9|k>-w6pSDLng*6+sqyOq*Pu1vk)CEQJSd3x-T*7`?DSQFf$Sfch`E?p0)C?61&B^in`p>er{ai zJ(*TssumlnK!~+vd?`)JX=%h7UZlxzX187E**X%aJ{%);T#PkfJIa!{8eC$^H*JSF zsvD_TK+!Y76!$s!^?CV4N&Y+;uejoD4P~V|F>iex{$O$@`z1aKLr5xwQo#)W*Pj1E zjOW{qS>rUS4N;Zb9L|sEL|yI#ID(p!L7hzpKz!lWmqH=C9fWwLH!OxWlW+x(dhyqG zELZA;9J$1Ph}lPIw*J+5fs5hIUKM-;bH8ms<1en8kDCO#108qMTUDBhY%c24V*Byo zP&_^Sj+3{5H~m?o^@r7IDW#Y*=ba65+@YUi1k4OR=l0UO5x)lG9LbUoC{v}pktW(o zGKJ-wl5og7*b7RhE6Qv_poc^H1p{|W!gOiS|CmB^>rVwG=yX&B`crTt)usY6O}7jJ zD{l@sAEZu*n>Uv-dR8(pW6#0W4pwr!m3yHQw=W4e3ZiyS zIBHOl%lY7Uz2DAhprZL=SS5?ofX=Vso>pSGr)@i>4LGfyQrOQtsgxGo8P1HZ{-#_J zS0-~w0GS}`G@5Gqm%O93dqqn#-Xkh)QwvCOKOihx7KbYMNzrP!%R!Z9oyJ)$n5o=NPv)kmZc$e> zRC*ZG6d8@r?zGfm-t1Xl+fDhVz){3>mgKeP$hVVm!+V7@S(JTDi~$a%c5-VuO;UkE z;Sl(a!o5s_%<*Pfdx{V=^MbH6LHy(ogOQHZ_-!*rS(+DxQF3MCx|4x^mWQSx)?t%tK~`6&s1m=G)$PYbgA!mF8-ag({toJ$p3H?Ep2(#reyRNZn()32G& z1|0Y+i?qL;)Xl?8@K0hg$G_@?afa^zJfVV>i4)lqUiRP+HVD zl+dZeY2R*CY^RlCz!KM1=5TpcC^TZ85SJpPlVOb-p~mx5V=;1ACk2xxVq}7?i|HF@ z>HMed5MD1%AlTj!NG$Qg-E>dv=n{_By$t8$JQo?MYoXsWgJfesi~TiNIUU9y z{P@CkqT=-kJb~2ZU+)~akZxn?0d0%MHi`(dl02P#cGogp3X)DIwM#o& z&@J;P13GMWJJ8zgZrmk0HD~; zDW1c}lU^13GEf^Hc(ZfUM0$smPP+BGwx!ziTd)-zB!4X-CBEn}ky=1%xcpg(nnX3| zmFqwKB`saMCMH0pVZImm5DTVF2-!%GJoqaiKXvl@)95>-7j`sbcA;*ZWau*>s`@PV zHh@>0&R8D_PqHf4HC}Z{k)IW&Xi0|WOl9jhh-i%l#7aN_{-RUcNP&UDMWgg}{&Q{3 z{V2ila-{m5r+6H@;=#7|C@HLP-`a{nwe*Swg}iP!r9|2X-NW?Q+v-yEqJFz`Og~|8 z%yh}+aAdO>ZLyq&!3S?M!I>4{?I-Rxi*x8#()ZFBPE}!ThK#AW&gp5yG=$T2(n|Oah0M>xcm|g1N&#ZAL zXoW$dtyY(@jaN=}R~y4Rmba=fmkfuVoYSKz#ozo8!RIF*=qtN_f$-yalC5i2O6{rS zT;K55VG3&idM)nb4|l8?2#d8xqe(jmsxKSG8Rv3`fwB?susdIdB-HR9D zgeD%C`yyB7Lp0O%&Z%E}K{-o%m%o4wk49sHow8c|-$rgSGJT51DtvJ+j+%>~B-+yz z&E2x`AEhX01gsoKkYC zT+=n6#)-!DMDcL`c{C2fS>TZcyvF0iUA5{;(42dCSHC2YPOPzL*&f5d_id+Pn0PB$`XOenK`veJ zmcW=G_^S*ORBz|F=uX0G!}su2bj+jIX7djxWDP)IK^hh9Tt~DDyr0l^KEv-V;;z{- zhM#WutuJ78HGtLgH6|(m;ZCTKA`2sH`oJ7>ON17c@|>M2Qs9}=dZ+@canzM@5)+r+ zx9f+@q3`gzoJq(}YFW8Or<$I}$8*y%jC_X2KKFW;oPr8hAP0 z&vGxa(7ve4jRy)T*R1;PYYev&8Fr^9EZzIMxcd>el8WQr?EcYh)$mU(LpS)u%(ttK`k(5AJ>%*9T2 z#)>UZlyp*Nv-GpW9kop7iAcZC)tjgJ3s74-=I0-KF|^Jcd9GR8d%~ndHzB61(gW{0 z?z`LPj6Y*5hBH>C8}{oPqlN>{wh}BExKHz9B=Vvo2UD4QCt+1Tt9iX~bFoe6H#3Y) zA6{JJ@O6Dvply_o7h=y*WtEQN89^6=_FJIs<-j&iG5?4LV6uyvT9q8Q4)o;lR$q#} zlKi$=!l+mod8a3XQ}ri8gt;no6B`($LX?^Wh*n~QTT)GETIF`P8Yf7bvj~ao^JLay z!z}yq{fw72*Gw)W_ATGJXfP0EvqnU0=`SN6ly}Q0V&Y-ooe=*3=ry zKmGK9U5mrhPVDFe&;M%D0Cr=-x8>UJ`WMP=a#yvf&yd`GC0s#ll_#S|HO zkL9(Ih28=i$8ST!01F!kpaD?cgKg|tXjjHrXb-hp%ezrA))GRV9NPV~x6g%M9jfgG zZ;_*BlET`b!i3V*YWxBFzui4>0otd74IA>lFguQpLQ+0jn)!&?^=X3ohNg_bSj0{! zDmQiXUTQ{!R0Nl{4m-N4iVHDZmKq}{FYnA!96G=pHn~+ALwDdG2OaI=6fGw6AnBMQ zRooJnHsr$$8gu6O6Veo#RKTobp+X;YAO+f`gB=1v&0-Pw7jeNxShfg0`IP6{;stb0 zhW94!`XM+%`oCOWgZ?0%Nch}RrShoR^j;?vwS(L)?)zsFwapLDD8;^~(w~e&$01Wd zq{8u0WRFs=VUgh|7f1P=9jJ9vEn=Po9S`nV>&#&juf1p(+wlW^>@bQ=rVP9o{vjg% z-Unq-+&%BSOPA!{H@|;(VrPkq`Qgu!I@P0g%e6JiI3A*xowm>EdU^d8(ywe@f@y5z z-qK|u<|maUEje_SK_+vIud<)=v_v;*(ZXN^vbzd z|3N=ls8*{kjNkEzZc{Mjmf-Tz*@#V9;rT{dmcFj29V#QqPmoT^EI#ZnSwH2pS>9JO zTvY*mzo7tQk&(>_c1Tq8C$b%nBp+;QnE9p|@Ui;UU&7bW6$l4CdL~5MCb7MwTY`Y%j{JzSN;A&H1kGKIp z^qAKpZ_iqCBh^63>dvYnhvZ@$m%DO54|gAgVCJ{0*am6##)zJb2C*7|Cf%0!FN~B$ z-39>BB;bXW*%!OA~bJXn= zWFzG^&Yv8GM&Zhq>O;LFa`=PrRYj>(f;ec~1czP<0@9n0DVM3olBs!5f}e8w zUO#|`WVZi~vKcvhwW1K5#;d)K$S#1r-cUt)F`7q>uD%o;o;eEA(09GRW_UAU@sVtzS)`iFjGu z#N1>YeabF3vPJ4TloG^szu9cEc`!t6Y7*RYe`EQ|aPigeHO3A_A)r?5IFCh|cKxZk z>a>j)tqLcZ(1EW{wB?1_LgtsC*@Bn%Y;bMXvGNK&bJc_T%4!lyB%l%206ZR>sABJG z`?ViCa2Baj?*y4HEGRqlJh8#6#l^<%v)4+%?$|%&?#&wqHrFu05ak2O%2RZ8U`Am_&m*ZyCR?YsctEBx#_%vLt-@b-G87q?I*8I1`cEFrj=Zy7X&I#ms*kt8zNCvtj0VW4u-X3O;8?b^)UCJ!U!syYz>pyMZOEv864(7poO^Zud;kbT>X~;- z%s_5$=Wd}GV*$5CIMXNGX+FY*&sON={Om<9dtLwPS{?Sh#g>SXE{c_VrV(>#jv$~vSqsl?0!6VfkIhuxds`}t2^k` zbm?ek70GU{C9M4_8n0{rwdU;kd1@~vFM-Qc@Vg`@o=Q8j6gcxf#7`03 z7($A^r2m1zQpYt2umFG6U`l5ZoDmq_Zfmc{WqLw&aLYU{+t97ScyUwgi~hB?8Ad(c z?F?+RpNUSA4%@sYq9)260BhiE37I6I?Y0YTw`!#=i#l4k>Fe$+x1`oxyPT$$OYjq`ZwT?|h=N%_TXsny9I zQEvsBD9jgoM6d0D#uQ{UGFC-<%X*Nr_Ea@763jvP+2PmDQ#jhYPAZN&Grl3n6)_E;r)+>XCr` zM+?*E%Rpv%PpDJXQ@6lfZDf=>_?Nw8!(WBl{ z`j680w@xKG&KRF2LIM^5onV6W^ z2mt`r|D)jsu>Q-T{ak$XU`&JcyD1h)sVGV(s`6Apt@`ke?J> z7++Eo%mNxoSU|9d>tov8clzt4>x$#b%XRAUWBsM=@~yplZ-?WmX*} z6fLAOGvn_>;K06JLPmAC-T|Y~!8XFrG+=IYC^+;8(Xo$OAXYe#$bq%_e0J|FU~KUD z2YcYiNKldDec|GRUi~~wOxia$LTnO9H&yKf#I zPe2ZY`s>#(^w(bq$_^s>@r;x(=0HOn#M(D_2J#qrRM?@y+uollfqLH;I3=MV-Q3=S z2 zfk6rv(7(&fEpHD75pIXTvM>XQ-A*Lm6ZGH*`9C;2rx;OyC`~tS+q`Ytwr$(CZQHhO z+qP{Rx9#rjoy{b(*_~{%^;(sx*UI_M`9E;LpQ%4&kceNh?Y!%}Q26q_3HfyB8_O^e z_xuG|e$QfPAainxxIqsi5Py#MOx zpci05LG|Nlc=01XsRDBw{y^4*xHt>v*{Su-ev}i^gQNRg@euT~UPcLc=6`-;UB#2N zeaXVx!LcGZA}?$M=NEpHg4hCm8andr`6cM7laoWJ;|*Yk{R?6Lz0mgLFy!?Z`OAES z5d5E`U?<@99UeTOm?y|L*j{L`2Z0}36c|C@tuN=dH&9pv(7qTttQ+pWpAg`8c?>Jz zm2d9dD{oOLq%m_PvEbh z;eI}Sb#d{$va%>5ISma|^nbSuKY#mn_k7i(^Tv2nfqxX`!Hi@7Oni^{;qL6R{l;$x z{KOi8`2F12VMd=a0FC|p+By3Y^w7U0AAd9fdKJEHyMEMJo_Jbs^C8J%V76;NCnEbiI{n1TRazUUD|b z=4u)yRCg2-+jk|(eque*8e2wpRPF?-YF*CKWq6>nGwjb&wAnMASuf^bGNjggp^N6t zcjt8wXYIOnZQl5`0g5)VL5rIXQO#NL(DleT!~J?bJk8kcQSrC&d$ih>oOU9#TT--v zJAfkL%Gejw?I9@Kt1X4>Rj{^l?QN^A%8<9_nX-i0Ch` zudXt;a(-K7vw^y2D9R(mI7~crwPU)zlXOf%z}h=t)PQu9$AOzo&BwE*WVH$1Ps8%J zvlrplM^-D@$Q*BqgQmeeGhi~Xh$gDyR?6kI_1*fus&CL5LsGK^&4e>o3m^2!NgFde zDnFl$bdv$A6~e#05&sB>Pj@~bKBHQ}A$u;Djgdd7AMrvnd9XHfrZ<(b^%W)uw+Bod z<-90+Nlk_8KPaDbJwDc~lNMH#L`EqxvF7Sy{>dWQCXmqWpWaTk#yvslT?nTmx!eClTy$R`?O_>|sY?^pGo|}{8C-`<@a7VhfOs| zWMYY3V|rb8`RQzViQ_lhUKw_A3#_~QGv$=~aISPc%9fcoL9W6=dW?`s(TSq0r#T~v z-JO>Z-Eu7vnLl_WO%~r2X-$nIq+|Jl!7WA15xU7#FDx^x{%6C134sMT|G?*7B;EX7 zLJv7{#9elxuXEz=^VAmPMvdxighA6`5DFmczvf$g&3V_AFKgeHTvNNB?UI{W?k&gv zoK?H;N+<9ujjMsE!p4x;zq|S4hl?3TKmQ#vgnDAaZ8oI8Dw8CljFILJ!-Tt9c;ElTmV^So42u9 zarB-TXTjSA#slGs;2PLvujUJtpw{~PkJHtHDB)NlYzlgJIw9n~;!^`bf<1g`U2`X^ z41F3u(q~HWmb7O0CTW$+?iyK}WY+dRbj&!^PmYz7pbW+4o~X+v@p{;cg*NIHzeR3U zAYwnB=oB+4wm3&qq{Y9(M^@+}AHIsfxlrwz!}Z8-P^shjg-YA4d>E z8lBD+W6Ma*VN}FZOi!#2?gbb!PcfV{Sxug=utKNx>o7|bDSh}H1zQUTJ_)Plg=xfy(gQF1}p8O`S8SNgJzW+$v+DpO}JVf zry`8?oUP86orKR^YdCLG;^x}&3#XV+)w5cCv!j&1Mc^VW<8hFSG&2d@(sE_Kmt|LM66}Q3TWU>+?NE9 zHc$j*bEY#r4XS@8JGoVGd!@{=6^=Ni@FCfgQq`dC8#T*&yU$%TPHHM(i;532BiJ+a z_awtIJX4W`97&JcDEr%Idd9RghUg)>1)2ON~5?R05L%Gpg`yFrPm(BD& zQ^xK(gLSMdNL7wb-4agb9q5KRo>4jKKE3#C$ot+~DTKWQ6N=6{tu>~-mg}cDzu>y` zVJHAtcJGiEPYft7@R>(`-`(9fEi>H;-p|eRAObtnmm{<+4ili}S~#sxws(c`$CSBY z$UK4Oab;7k&e*ts;qoh{6l3^}kAO{jdat?T^>t8*30u12$CS^XAKH%{ybQmMK_>>n zKUYjttJY|CiPP#luGI*m6jBWe)IJSBqUB25v*;!taQ)D~={@mzH{9*otP$&s%OBQ5CVSaX`MS;(V#5*95x|TAfE_^~rOcBEgiqDrnVqaY$fi z0LR|90h<)fIMr1ZC)I2-nEXD{*)|TMa3ab%@Jd^wW*zTA?t5;9;u_?XUi!?`qID8s zwF$+WC)NWuX#oJ<q+^w7)c&i!fOQnlwPBg=|WIx9-{O@wMF zxVIf&8g4TvxFLi#sKwHHP*8obaQBWjjx53hV|x$9k=!71+ujg)QNOFkHK%rh_3#(F z4I(<%0wz`@wls<6GC{L%lWi`$dd&7V>Ca#{V{F3;SJJ=dhUkkCCT9_8VrdVD7(sJ~T<*_mb6eh+Sfw&dhd*~!1zQ+(=k@Zs z7yqGrJb)+3#yDp*9ui=6PRj!AX56*NvUyGW5z+bqRqlD=&vNYK%vx4^M?YzYA@lBQ z61Ca9dZ8#5&^HfT_~{sge8||z-p4#sXbpQBUmLi{vrn^~X~MNGCH@O4bYos74k4Oh z(~r{@ItD|c0pMA*VVo~&)gLctqcUHAgt&sD|J0DC5gK;FM6+>x%!=EOUO#C_E9xZ3 zLqM=UZK+@}==e#Vyb?;9`(!+NL$OGw*-ps=VeouI&`y((+M*Dr|0++?T5hm^ zYGU`^J%gg>K3Yh>m(!{nOj?zL)XdHR^(=+u3%lAw4;&?KnAMzv5EAHf8<<1#&N-^h z)11dr8ePQ4qZ?AYG{I8L5i#FxdE#~tg!0fv7!JB9(BVVksLgDRZ{k@5x=@jS^JOpA zzQfLxZ>*$wr)X~#44ybgTrEb&3t?*kmjZCgkbMTf_V>Ae62kPxV?XB~;F<}qzbRFH z_>(SD+MAXggkW$YaLh1nr*g+3e}C!YEbOQ66bKHpUai`BGN1-l#d_y_c=69y zAoI%&(l?dLMg-)qU@*dy;0~u<+d=T}V|%D<&3h9wxE;&bC|NkkI}qyF8gPyo;|>^R zLt;EL5~}_Y*W?HDnfBP7sHD()*wJ02^L8m679Dcxeg^1Cv{w&ye*+wois&sA?J+dg zNg|u06f?k%p9(qjeGTmozlWm@Tr@6#juzgAS(H4z);M@&wzVQ{xmd*^7&mUokp=3& z$m$`O_nNh=Zn$P?nMKRgj5ET{$QBhz6X>_So@o}jt^7F9X?0Q)cb)+RKoWbd30bLc zN-`+QqlYO2N1KqVX67=jqO&c+boIUs>Axs0`72&01k(Fs@ONWQc#uq-D3;qcV`rF^ z@jD3hcRfKZiVcSiz(^o<0y%!-?zrbcS0piEW(LOjYg5m|5ZGx ze1EpT6yy1M+;|0>;AVXkf6rfZsi&uvpAZQBK@wGZs?zhPzGsEUMg8_C92X0>!I zE`DE?tSHd&=L1IYQQwEy<&WYf#72fD7<1W$Oz&_lg0{WHWr^--Z=UG+>3vXmb*#& z1VC1=gFIR!XUm3Uac_)%maJ;NAyoYS1SsRL)5IF(#>5pJg+dlP{h) z?~!(GIgj04I2Ff))2OE&(Gax1`q3#(tsX{vLmcqm1KrcymiheY6XtRm9CTPa^!No! zTX7_qPUpn1=z&no3iFTEk=C`}D}0{H75d_s&yPERhi{x>KRffM6>719XlR*OFw#1m zUmC$z{dkgu+E6FjP0-xuR=6rGE|E?gHn0A^>ZIpuiog|Vuk7K~a(A;o2@X&^ z48rHu1x05g?pJwxd{P|eBeAarE|H+o_BNS{2s)*ldF*a|(jAC`?|2{MIiIMrjb-MIV1)q<*^YbP zU2mfOH;;n(h8oGCGUtJcm)MxXtxs1)WZN)N-AJ|C=9&ENAbPC6V92O-xIdD9lS9;m)K| z1bC40kcJIWu`Xw9e(=b?fYE)#W)FM@0x`;V?V5*kB!^$p5qscvjVEPv=J2GWBZ~)s z_3iP{4r>X<;8#%E>JjFy)O_*~a(u#i$F?U>(7BO^=z_g?1IGaOQvi*r_7;Y|F zv!E24Y0WjaMUJ+(sxmO!*Phdcc!E_saun^LfwIo4=&+mZMm=4Ee1DDM8&7k-i>>n+ zkfg&trPyuUxkC9<>KQYtagyWTu7BkxF$$}HD?#`zH;i(!23g+Z8w{YQN2)I(uWoA| zK(B&aU~NH7;nlx`>iClNY+)gK6VCA;IuAi*-ElPHlgQ9HYD zO7Zml&NtOZUnJhV>)WUa-3S0~@Oxz0)M02&y9o!{kBVg-$xVmm;NQ`8gtdn?B0CjB z*(cJ*mSrbEj&?CD4vXd8jdX8XHtiQ|6MVq3<68GvmCLfS_eHFtF8lWTlpNpDj6+VQ zMfdd@)g6qXg z)$doKFTX`;P7lTL#$`K$Bb~&NUFkGpnrU0iY>(zZ1_hdC7b2(p-aO6l3c>y&bmkht zylj1eqlT^)5wC!FK~q7r{-K*nxpH2hY>W=y#Ufm>98NrKs)C!1LSWJg0dgHQCR4#% z9^f=jUplDc&}%~2P43n;$q5MkhyhR33$^f4=c6smR>4S;#9Og5sWuY#(ap}Gr4I|w zlCHSRpTX*f)vcJt+l8#WjBnt{wR_8J9;Iyy4=zyp$B6m_bLaESSaQ2hh}CY%1CT1F+f3b<&M)h3x^+cqouIvteFFDidqV|Mml?+l zwF?Pra`%v4cHVp{sz*uH4wLJjY0C>*IN--jA2(-dMlZ-$D2d*jFVrs|McRkzL(3Av z{KOG^??z_Ga!HrlrSFT)LtPP}N0aT-fntQ-Z4K{|p;Ha`fzZD8IEye(=hk!65%I{- z{-@2ytT(O%SJJQ^IyW0uiTKo;?6Xb86@*fb$v+hKf0!QXR3w4HD`Ab4^AJI%2t|j2 z74rdkT4kthlV?5YeqKEUTnhCPPTc$^_1RrR!ds^g5n7fcz%a9y5R&l1_gT015dG7) z@f0=7(%i>+mRv1$OS0=W{@FN%B)hJqktP~ZxIzr;kn{->YaCfA+vhcPB1Z5t2wXp& zRzca^p3ALLrmQ_Bfz_JqM3wa5#a897p%FaMdeo5d^(^tY?G_x?cGz;fYvX9_9&;#o z@qr>numU2XIc?tpJ19VSU9x68wc2RMjoP>sD}Z25+tlcE)Gl;s>I#U&ISaF2$v}~A z)Rx=~UoPUY$&{mnEEa^^jspYjFsXQ7kzzGP226KRRjW{Xh!VdktxZT zx(}_e^(f@fUQxOvHO5tTEVxg8v=2;@J~1YSxbk+PWj%R8)N1N_bl%mpnlT?q-ikms z;$hb2mm7zq$S? z>Dxy?eJ?OB-o zRSw@eK#H`y#0}az(=e?KF{G_IX~&fwAd62*O*>_PQqn&DOH3-i0JG#8gYl(qurROP z2&Fzl>RD$1=WOxE5N+V{gZdLypR@l-klzb88b=`rE7UT^?2_?M7VKJCot!(@t^|o{ zTx<9m;tcx(il3^`M~q6Ms@XiGo2T!XC%i4}IkLgOaHzkqwMNH*O<6P@E-$PzN=U1( zz8!`|2*<9yAl6sZIL{o#t}7RO*YEQE_prk=)Z~n-wZJwnqYThZf)Cw<6<@ASlvx-^ zBPuT7oA(r{;^eA$%A?1~IGwZWK-VIXY$@dlJmc~^e{Qwe)D>;RwR{~xt>W0t4?~Vg zRkVsrLZ{#`VbWAASboK6{7MSYn-Rn=zHW}1BY-fd%!IL6JxS#9t};3sC}Gx8u`d`D zj0UA>N0c@MxL^*<7n|{`DTt3VSo7SDC@%?=xTJfQoAfH@;&ybF+wV(6>{`Pka_8mF zNJ@`_oy*fxemdTRHj~S2Dq9`58be{uDR#WS89LfS z=;mHQ^&ph`b!G=p0ThF`)PRO;Xd0%6=^KBk4_^!D@3^L!x@XmA=&pcVA&Z_3@ zd8zFd-ot3dqA}Zw$$fbr$^G=S&jK@?F@ii)i)sw+!WpxSJfD9Zdz;m9KY)*I5`X_M z2$6~Yzo4`K7eZ8$78DYY{ttxs-;LD%CT+7bGyf7qwqKDi>wgjX{{Iui|9+_U|73&z zK?47GHuyi)y|xAxcwAinNdxKe80hH!OV~C&Gd(@Se{TL)I7rXJ$oRihy}!Kl|7GfZ z0hPV8WKdaHV2La&sNvUOUvb$H zn_=gMQI5{={?UdMLCrybk|Z(!_aY=?V*^0ixB$4w0C2_vaMl7~V)_L}NB{5&iJ}4e zC8cwYA?8g1$=NvpbP&i(a&Wk}`&C)@+1h_Ufaf*lfz>@cJTQEj!@{?Mb@)+DVF65- z=war4X$nCxa{84Nf`WrTzvH4g39#tZB?3@ZhK7Pgrgu|D7DhIMb0hTugR}se0ciWv z-0(^E;SvKYOrj7&%!OS%PwtpATIW+-!rnLhA+5&OLfzI_mO%F}?Bc1`dMZ(S{ zsREU80Aha=P<{#P0ex;`0dPWn_-=n$e}xjp4d#xRprXb+%b39G;DK5Cp^U+T%O%Sj z0D1a%}xtN^T2JtGg0*{4N0#EHwe0K7vLZQVWttAhm7`=!_ zSNXQNTQ)WY78ezEbI$=@MLdf7DBz*x4QuXptNrk3X@ZHuf#v?-QN{%pFXI}kb+Ff4 zaQbC!``s(}I_?OG{ft%l>jAK0Vq)Tg;R2jN19)hx)qNxIO-@3*mL`0`-D$%3@W{l- z093Xz`1#;b?rowa#8#$r!UMS21HZq0YTosNhi7B!K{NmWPx-Ilfff07^@jVa`0lqp zxB|KZ?KE~r<8u04$IklZM(vPHEzI}NT;jgxicVEjRaN8HOuV{||0qj{v3US_rLngI zPGN0X0l2up(g56U2JZg6zuAI)D}LoFFf-2Wu76Dyb_FIA`u)@r>~y^33T*x4KzH=6 zhT#0`MNq=pJ^2fs_hI@8v);B&wewx~htvmYjV?uQJ>+3AdxuG5S ziQSpPF*J+#i*?z8R8zj|%Khy6*dfcmt|Pxep2WBvH4Oa{yBz7A^(eA>)nY;>%z zv;QInYoGAr@=vkAs|%jiZG6lfbc@sna{#Dd?+EyAbKR+0Tl%_u_H-p}gvjjlYF(QD046{S5B`)M8}I8ZD>(caL=)e8&zTuM`h7l6(P52B)>z=%C^8t@#hmf)Jj^z? zInWF66P|ef2jxt_nekoD+t=9#brn*~!YZmJHy4ZMq4aK(8DQ6KGaGIz`Q!%$g;9O5F?>8&3WBkTPsmc^ zksif6#d7ov5xQkNiRpAP3VpPx9&4q!&Kp(ztQua7C|KuEKpGK;xC<~-0Dgnv9xv5; zdKH*-;AImO=llF|T>1EXAq|eWELorvWVp9`i7ctn8^3#7IZ|vDc2iX~p&CRLDZFzj z$lzBBTzgF9m8u|c$KgCl0|IcQn0NfTvkBRa1hS0DTm~HZR59`GeKlOh;8$Pj^`-$2 z2-CRn?&E1qqZHwBe1Ny=gEqY>pNivbb?4CGzDO-TjDQ@%ZCCDvPk;`i!d1hJv!bq` zc+(|G)j?q#n zD0?}T7NqU4L5wpyt3tgb`dkc!BuD6igTk}pt>F$=Fo8NC!pel8j5|i36wkC=v48&M zKP_(8Cp2KDm_0u#G<>W-u&98UfY{4R^8q=W_<=X1t7%BgX{ooc%V8`Yv>O3I!c>7K zMqM6*ztvQp?|&2KJ75liW7`^=XXC555sAXUcVIZ;EsOh6@u*2w6%~=V$Ng?T=tO;g zU$wC^YJf@Xn@>2MqAwqEDRcz<_;B_p%rL$kN0%P{F=iObP~@Xte2ITQj+KNT#nsjQzO`@{?_>!P*AM zo_4@nF4GbNuP`P)@5`t#Rlr~>%taP?<(@jKIv}3nNX8%E#!MtqnzYZF$yGvA(JD7W7+BL2$Y69VJvb=fqJRpCAjB=QnRiR_@21jwFG{WUO*dTA z5p`cb>7`q$M&g!DM*4@%<{SNU5gDL@e)?&@H}RIeXLbM>F6>^Sjn`STtqU(s8i2kO z;vGX0WFfQ^|H>V*lmM*=U96l3gPHu(ORi2r@QF~FAP^%DfvVWQkCCdvrllR^;v?^+ z5Xxr?iA5VerE<29-K|1n9M01cC>dUAc?1eG!NIZdSCgOSgGQ5xNwEYUlM|X!8=)-J z)ebbgaZA>J%4LyF0rSvx3W}C%n*aCqNm}yUVrU0Ynd+*wk6h=!1r|W0>b6}SfSclq z5}=EIo1%%`I93QZA$it~s1_AmhhP%psB;=!t$gJKLK7o+6t{|V25FBoX2K&^@6{7K znxZv~i;~{m=(Ij~H9z}sb10ROM8H&nSLmrl`yxSxL|v=yZCC9F?wAbe4pwtQa7+@S zO4QSt>Fdx!HbFa2{=VRF&`Qsh*YX?V{84~!-MGR6{Us)`g#&)hcjKh72WD~mZFEW{ zs+op|2s(Uc7oD;YE!Rs>!(p9@J|GWRMqVW4s~wUU5>$nnsO8h zmk;TM>`T;hoxalkBC9wC1aiQ$QGQAQ^fsi{LEOsTM%}Z`-+7lwQw5v1{vvZ=QDf2Z zFe(`r0)6Grdfw?7Y5SN<0%@xU;Oix-*1I(xbptHsbVgP8WF;#$L`kn)xbUwh+BC=~xnEmLv_6-8P2EXpT4h@N z(CHXwqL^lnrRsIK@PV~3@TjZT^JSV~4S}E&Ukq=#${%8xGHePyhwle_*Sr+5?@84A z_U+LLCWp7@*bUCbPSh(`vA%9FjVud!8&u*mr%p_^Z$8S~2=B=CmJ8*k6kLdEKmfUE zowCH90#+qL7ygV*RRxfkoy*;5=@Dbe@Z{2KmpAG7&qE(++8NWJ117 zM+sTWRIh}0RfiQr6*S_?-VpAvcO5eRs%~}!_r9%aj9hJKri96|dY#o;O^A@%t)W*u zn_A#Nb^9uD9z;qn8Z z!elI%fAyeZbqA|2ak$Eq^haIGR+U?PtO4Nx0&2l zNZ&c|!}r6ZdP!x7Xpeiu&5xR>zxKw3R+XUL-t#81gbQYJm)aZO?SU<0gTGTh%op{w zvrdfM8U=SC{pN{OY-J`_5_DA2IMYaYjdgP{?G+KJg_;uM=q8Gm`T}0B7M0E(MAbtc z=IeESqjp|;AzhhFGIfPz(DBUoSgsnil)mm>T7($xd$+a??=)ZhN|Ej#evMg_#oamm zoLMqGLYV%Ea71`RQsua)L;GGWLsYJ%F1;4-bKcip^z?`F6BufgH!BOE=8I=+OHo1a zt=KlF7bmxISI}TYxhcS{Adm^Iyv7Uf472Tj+=CBj90Y+}M~fvA#{AM^7vdKapRy>+ z&4h>FhQ?iit=_iAVU4Vf{cn^B?4gfR0F>CqNJ~vbV9OwWsvFO3Qsq7PLHk!8)5EAi zV@eLyX$euEJ%hBtHT1qoHCh6J!3P%%sg7mp0PMF!FLS2z^9BEkeB>FX63qyAy)*p5 zqEnNNACm^w2&Y1GK{zBb>uNHSGsuCu2a~!A%HS4R@slQ+v$-w)@J?p`SzC?vM2Tid zjdKC9U=bduZq!fNj#3xmYFC&lZ2w_;OCjm>@r1QlDBeyV| zsP$+~Iq}+U?AWbwFAI{hHP0Z}L4sprNh3XJOotHd@ z?DP_4Vv}u@24r!#T{!8&a-Olg{(x@UW)P$M?e&0Tvu#fOfFHj({oK;gFBtJZ?X($r zX*65nHSii}(XsvrnY`;+J37L{IwZY|srv^fwS_)Z*+lRX_4fL&68$$CbbfkSyob~J z=B1j%(QI_AoAFV!*WYg7*>DrikRPaaR(Ji>kZwvdPp&xPE%)wg#8_%DAFZ=;&4wCQ z;~DFoc_qN}$d(`rqnj_I0BL7yrf=wvwB+fe>YlCK5@m%)N&u|vm5Y8x7~yMpX2{{e z0TFI(;V_?T#znEFx;CG6hhf3!zb4a(!q<}QrwQ$=LDl{8RcfSSqx!mnO@~;YxR zd>;nO6psM#>N`XEQk?n04^zb@Ym+#XMOX}#5#b86(B+evbs^s;XaOlCtz>`OyJJ#OBO`eK{(-GohrqN>MH;K%~#m`(y zu|OW9nfR{2w)94hN9HzZE>i=dz>iK>;|^)=JuXF-_%teg%g;e|u)TO<(u#W0-mA>S#O|ez1MI8AiVYS;l5j){p38 z*93#+syMTgMpm|Y%^+dlX>3HDx@_;{S{25y<)H3NT$pYpeO7?AqgiN>aCpFE{5m~p z8T)Oeq|Vk!ApIQ?@v)|FQJ6rR_28q-=SM+(3SHH80S?gIFuVoDVr*rov+DE~BWNFW zzSf2(6Wv@e?u6xq#1l7>xWFu%Uj963`k$ds8kaWnn$}7U0=2oU@U-LAOF# zv9ovR+1{Tu@YO9|L<|hFj#ADb!du!(OdQPQu8rP+7Ol)Wqbtg5GuvK<9RP?Cwo9!( zMZ0y2K^v!DElvDEAtRY;I5?~i9jMYT{H2NyfJM|ejwOnHZLsvIe9Q#LseTLg)Sh2X zX`sk03iraeKy=>)yADHPGYly#-R9)B>>7!#vV9wb9LL;HO#@0-W_nK6vx)aJ$9CQ5 zLDb&nJSPTM+>mD%5uf;Y1UK+|k9or#uV0kWJC;|UX7e696)IGTX)1PQd7_~Alh*58 z{4?g(?Jr`ZTH~lYkM*o}`>22(+bsP8Yo4#48&Y(P^3eUho*-*guIAGh|LugwtNpyAn{wsK5gl3k0`j8>8I24;?gc;G?{rQ10qxq<|76xE9M~j z;Hbf4_=HzVt^;j`Z3LC#r4!IAmfmg)_T8L&wNdU-A5V3MUi8 zA6A^l?MNt=BQNB1>uXm*z#k+UCG;4PRAHKjb2|+6se^~4{*7X+R?fz^I17LzJF=Fv zb@$WCO+1^DOXuaM$^?fMA9EBU!Nqys>h~_ViSJCe2-iDIO4U@01!Q@l0CWr`uN9Td z9Nnq?Ul;D z4q~9zRi56+(VF5{-3AW^&kVOj_|>F#FU7OCLn~ctLrR<@q9(6z6U?fe z2rsyi2hct5dbs)XUb}%*R8rpMWa<0b_9g+aRSO*b^`;bvl~udyNWA=cL&uZxete)r zdqqkGHK{Gjahh|f?mV1r^5G0=-zv{fLxLF{6jSK=NXsB~ho0jWHQb#THt{~wB8u&e zQV&=Gbmz%(t8E-0lbW8uNgSk>w-V*wp$%}@4eZXx-m={Gap&TWV&5^h{+X$;Ow>_} zX52tnlq_TZm9@9$d$ltb=bKNeuA%s;m8+}g756HcP%)xGY69{@-`!e{)iDb8QhoT2rEH2IX?x$NMs0X-C7Oi^gA1NU%% zQ%es?sZ@u+?EpGs=Uy$t&N06RfY)vVjHn=nV}8b93%R`ClEKqb_O*$(T`_pC-0~cc z3S#vBoaNL_)j(Vq!Nk@ z?mOGS@qD&hBW!sHRv5a&c?zx1Q&yH6X^cccvWk!skEN-dagOF#O zlhDnw7tYxgnhAk)79M*DnuW4KqG`x^#mSbKQ#2r=gtspCFN+!7*Nj^O|M`=N)PM#< ziB>l~4`bputl`d6R5}0g_q$uNe~dRm?Cc{0$)SK}l@`0y@)Rt{^qH-KF-5)@=u!U- zSm1SeC@&Tm^oUR;fEFzo>d#KFqgGvU61UgY+X&q|41TO_9~>-9!M|ysky^Z9m(RW_ zH{r%=;`AOeo!7tM-Yr5GBQQ?K7o@M#f~8J!!`WXGn@2=FC$l3ki{m$*)Q&Zi*qbKO zm`H1#>v7BnfHYWu-}%8oj`OFA7S10Xhl=Y!Y?1g*SOHn8I*>LKP^mD2&(p`oi>P;W zIu=`mUsxpvxmP9=t*TucC+1#|(Rce;=z7BRSS>ozuDFzSgho5C9dJ9T*h;m`t_ zMi=<3WEZ9cS{V*$bl8`hsPTj#v;4Hd@EUt*(a+@bgwoa+=OEFPF_<754Z&y#`*X*i zd@yx3tVx6+6{1(r08qg+DS)52Y)r4m*o|qKqueC0ze)bl{E5*^C0;`Iu@*I%!XV^dk4bjN}`1)e?f2mnj!;eJZvec>oEk zE7hVgeO&=TFr|A>Jvb-mW7VD+2`%(=JJW@b~B9X{A9uno_`dcV zoglM{Yy^gkcgb&bISS)v^MbdNYN*)*O-`sSJKHr7+3XbwVaZXXq|#zM%ad@?oL4jL zWj%5K$=q=d?`!)H5X0GSbFyo%<jz3KIuZZlyXtxyH<8^_A?4j^lM;%*U7F#8LD)L>(Y@V4 z^B`=`Z{Z{S-_OqF-tad=w6`|eGZ@|*E}H}rnsvt+ycpCp6(h>{oP5de2AmPzJeRaz z&BiivoNQoK!pxIuc@jyYEL8EQn}};Rx7`8~vS!^0%nOmsq(SmHrlYDMOM}!$RK=w@ z-N*@nWK?CyTa`Qt=W+9kAHbr0X3(|WaNi@-y6Ij}2xlc7mwx6f(re53)3LbP;F%3M)3cJzBl z`~<|_G9&?vFEa%dPZC1Nn_Gs(qIwJrz-0i#LoFi{&LHL``o(1|RGpy@_h;s|M)c_V z(R7c++WWDxp`KqVePDuzr#@>Q%VKBIGf6x(dg!mORE(1di&xN&z1PyI+z-qRU!kN7>%NU&+!EDj>ZVL5HlN zU!*>v2=>}+PiTUxyj3chq`ZxSa?vN*yMK-XJ4FJg(OAl$f1_8-LI**dDOjW(3OkN> zxS_iuQN|L^khwMt#E7Jh{uH=MPI<5xo1AeP;LcjqEI1kK{E|OwLC~${PFxi4op#bc zDK*Q~;xOsYUJUL_OsZhgxvzC9bwgT{oOHkCOvVU*Yg*48wbd-(;Y z@XJ;me$@g`OZwZ4E)F6Me((dj(EYVay2e|h+}w#NQKsg6;zTj=lyk~2EL)vQ;irL* zCohG~x_dq^jvUR79maV43YPQ~Ih!{=mJW2+b(!aWZ)e7elcObZRlkvrp!vB8C*82r z2_=E@aL39w3{j{6l`gkCS+s&YtLvtPbX^ha!UA2uG>?ysVQ4O|R;C~GOdrS=IL$Af zUMDiSsUuV9_85}k>Y55LXPMS(2Aj6+Lo5N`!3iwC?OD?{f|I)Y3A|uFFWfX1rcS=Q z4P2NAQ9!CglrXlIo3?HW_9a(vRT$|5iv59M3J>&V*b51AA39VxH2WM~r{C;NtL zXAS0peWjF>wvV7eB=i(Hp{QExep8!WHt%sgOzC%6o}LC~
?YmVJO=fGT1FjzYEu_cUymPMfi=t}A3J~W=v95{E~X0EZ(W}6P!hwC=2ygZMgxhkmYlE! zLC*H%$?K5AHvr;>6do^6MrP!OwWAZ*rv`2>=u!8KFwmgE?R48V_~J(1S1u4j_%8q1 zK=7&AB#JLlImw?&x5+9v){;zalgwQ>KhYA)R@n)+&LMA}lKr6pd%+aa!hSqjr%|S* z0N1O|5_iC2u04#Hlq#zG;J->mFiQJ(l4ZwB4KU>3T*5J9Qx8!JCg`lZs%*pk^U)RY zG1%Slyt&$R`{GD%nSk;c5wB;2 zIVK3~W}dMifT8TENumwqkYPlAJ`aHj!B<+uz;W8)tMI3NcB%`>!&KPYOtxnQ)BMTJ zJs!W$>qP;<55R^`j^|#h?Dvy8t3nDl<$? zdJj!_j)kl7JZ9V1X&|?}DlgqWB@2qdQrT9=6jc80TIhR69FS_-CDXq(4pZroqE*&o zHjnlpnof>hHA+1vv4qQv8c=7nBn(|5q9$~eMWBxjcoPjdaLv|KM{eL&hHU5#l@D3q z#LKDrj=&4*;QR$sD;zBxpWr~1gYC!YbRuFc_JZ#`WPz!miq`Pav&PEcZh~z%UHYe% z@A-PBSuE9F69rQQzz24?5)@?+EB+Qfbt*o`NzhghVVqGZZp8yhF`i4~+d3?}mF4&i zApt>L(jdAKd;96hRN{^{o2Wqb6=llb%br)7rpR~dceVH+g*c;mQ<|Spp{uwmYPyoG zA>ii+5nXV4$2^3J1dZb9-86K1a@5p#6Ck_P6l^IaMgCByH6QVK4~mL5glGh_O3*WI zDZ=*XURtI(qvD|n3%-{puFxH^T?N^;(~m)A7B+MCR;N}?#Equ>Dz#FX3`&Vh&3RCq zbn#Osnn*3XXQs&OBZ;B8Hc{^l58~M~hq21P{+=h9V72{7oz|9huOl0>lxrawB$l{3 zOr$`FkXNqSDfT<=5{SsAPs>QZp1*-GC8{3_!QPF3bRPDykE40;)+zjh)CfjkBN5Q} z4+C?@<-yw;`a&som_M*)(JT$v4&UhNt7Kb7agT+Q>j71WEB7R!ghCQl11|Xc&?f!2 z)*l;br+TdHBvC_YQDo-bz*7~uepog@;f3YT5%?i4}r#AoD`rIufo0sqP@ z#_IBsR2)aqVO6lf92ufX#a#-A{lhJveatv=am?>ns)59=krKaYr$ zJ%dR5KF3p^^&%j}TuO}|{vV{>Q>-XqxR~K(+qP|UFWa_l+qP}nw#~h4+xF@{P1~F% zr)iU3&h2F8V!r>I=j8}-(Cr|&`c|G8=d^wtxKp~qeX$#6{T8o^O-{M%{Xouo6S!E# z-L+&At>(mhL(RCxQ3{oE*fJ7gIb}`^Y4dxuRV1_Qvu0R1cnM^VD)w%VW2GxkBRT7h z%uT*&J5y6w>h~M>NdsEE6Mens$=q+miFJs2f&VT@hjvSw7(SI-=Nd?I zL>`3#R{nvJqmxL8T0tEJ-#NEL?CB38jW}~RJ8t%*J>$9)vE+BJ-CShQFpD9aPR#I> z3^T3=O{?L5M&H^2Np6NI(dfxUy#f1}#tGISRvnKH!?{oIuh71;@D?r7_Er?zNgEJ* zF_1DZj`_k(e7ADDo(PQ#evh}}YieCBA#LrRPOf%|9dXrkwQulncsfU`Y#zvxe`Ue% z;ZPn5e=Rk)(w`HB2=kP{`Yt-kY9w9KJk8V|%er?#JJ6}I0e@fS;c?21IFZaP59|7F znbW#`)?r4fi^QR!`xXSF>wI}%p+^{GpGjozkvJON)4v9v~=A$`)f^l?bU;{Zzn6}TlMzYvXG z$-7x|)h+K<@9(6Yx;GoECmS?ZP$;ZlK#7hOdO`WT`CRW`$1Vh9yO`If?dxzDjyjw- ztIqjto0fY}(1XX8_q5G1BMqa3v69F%pGW+kBTxGsvw-7-3IbgI?Af!e%!1Lu-w`ZS ztC%h&Mh&ugfncres-M50g@JjKw4rjIo?B-3;h)wjKEcUn;*)x)XrB+SJ)9%>N)+lz zSu@?1v(Obp<#*OO`{&D>-ouGqtHP9yj2!XpG}JUAYS?ttYw4_97Dvsq@%H>wn8#;0 ztWO9kp2aYgmwhC7cP|b6()<% zG`vA!4nAY(6X{eOkMC;Kl=x_6^vdsn%TBI(xIv6&-VXRjANl24p*yKkU*UE9jp%W6 z@L_LV3qa88@MJ8+czs=(3sO2o1ynE7w`rgBxe1qVnCd&ynTskszigLT$KcrV2~&}v zbIUjsdiO1&ovnBFD0A8<3mPqZ9X60|_8GWpN_lI-^%2jF=#rH!C~T{$#MSl-u|U(w z*nCeA!xjAG_v%OMpUW|ZIF#Yg@wPRw9`o67O84vdk|BUeI2l#81mjDa5QgN(t)Hc! z)9BFaFgP9)6j5+86R8k1(K8F{r|RX@wLkRBZ4?O%!&4GI?eZq$Qy<>_4vAdRarW{O zmdxpm@E-C*1|*A)Q~z97vcQC92B-fb%|N%*<^33Q<*>9Iq<_R#@A>Ay`i`8J!%LK-E|q0dek=}nWXofbCT7+8r9s^J_2u6Sb;!^YJ9u5&Je`movV zvb|OCAI=Fp%|k)K)mnV)FG`QVAq}{N7kf<)BwH>ny}(GGKN+OecF>Z1EBr12%W|La zMI~==NHKcdV4R0-5x)BIwJ{c>LZn7j%B-_@P=CtvODn}Yj1Svw!J1CGEm>qH?aw`| zD$BIwARRDBA}mn#8!_=;+Oq{cj?`mL30}9n{)hn1UNOnYyjhYQ%FG}<9W-)c1V2yJ zbR&8?WKUlFoCCub%@_#5^-!T~&1OFT`{(fWbef4741DU`l z$hLPUfwksGmBG4wtEYB^zsNJft`rN{l)5R<5c{866@0gRO)BpFuGE_54mC6q85qrH z2)(Si=(cgnh(@cfZCXHuI|k4SjL_2=9zautrKGRiclC<_&+((n@UZgNk+%2=cNJTK zv9uQ@b*~x&aAM$7mQB;!Nh7>RrF`+e!EY=U#tZ>XEAd`ype&sv2;)D#Y%XFWJ+=7^qhXIS=ED;;c=D-&(|OkY zXRQij3EW<6LzWHn-_nf8bbZWLnxXQ2*r!sNA@r4lPBdVa`?yAV9qcVFoM#8&160T< zIKcopr?$uqt39{=0?e)mS3dbq)A4ROI_rIY)u_7gXgseoNz(>Y5A;YKgdBmCl+X$u zslA zK53GK=+(-OIoxrIXW@|H#;|St*lM-UTF=$e8i?2uF)q)HQbw14_H}NkZ+)qT5Z++d z++yt)e#MPhN`w>vzs31Kl*@>hz#MpZ?O=z} z+v{?tdd&Rc_d`gobX_<@Q+2$I{Eqg%bx5$$z;K$;YN3QChZoLE@pHL%XD)50G%L~( z91NJ>Te00DbAuatpz()1$3*o?e-o{UQsvFGK8&pmnrIB z+U7-Q7LcDvPc7H>rVCxqK}ld5hib7fB8uaTDunI^Z?uf%yg#8JIk?D4vK>sqfpO2m zi1P9JtC7{Sp6zx#vt%8_Hvy^U)mdltPR_~5q@%YrIG@g%yxLIYe>tXLtL+s63UwcJ zN3B>ke~RGyb>?db8_&qwpXh+ky)!7UAz@}W0kgimu*Bp4v+J|1;8FVPh7yf zOk_vrnw9y(q0lpMWb+*=7%U_yctD`o8uGzG7MUt!HkZHrTeC<6!wroh@G zMIjdn8|;KJt>+>>Y6qh5)?Q|-u(tF_p_&M(YfDaqp$1dr8MtDPRKr!zLe|BHuKe1gB*w(rE`W=)td$n5wXChfa0UZ$H>ifcVsA1d#0{wZ zJ9C91{)jnFSoal$j))6A@@llt6v+;m*w`M$O~deG>cP*KAA<#ccMZ)Sd8*B9456Au zUT2!_(^n-0`pUYctjYNpZ(Gs+*soXKFZ_utZi2HB1rNi2B|jCeS3iZiPqhXTPVq^E zu00ahukhpko4HEcXh3~4yY`O2gFRmvisbHtY#g9F{q+&~Z1ZwYm!^vK$w1Bql{XUI ztTvu>H^v|#UgrnQg_q+(D2LSf)i2^oW|aFRY;*6$8)lY}*UM7%RMbWtYz${8*iy{Y z$2gPB?}?bdad)U!J)>0ccqDD?^=YtHd?fO1uR~UR!VQ55g~X=1M*WEs;O<1^2hZF6 z)bR{Q_}T-{GpnlYF-W;R8H_|6VSHvBXRvgq^j5Gkcw2uslXNGCJi6kY`VF_p*L~WE zx#bXZS*!wV=nZXPq()S_H~M@SF~F8|g2oRR=T1+Ep-xx43#5)uI#v6jBAG#rpQq#j+Ff;|7a}cY zIHYErwNE0&BH7F-p*YvF8CCZLhPF?{uf1atqW)vz}Trs1CR7 zd5z{|3*S0b10BV5nvfub*7Wh7kEF{;$)?OULHLzXra|eAo-^;S{y{+M+KT3Hl^WvM z?k6Pyf8Z%$8!dWD7a(w_<0t9@6%=`}1!^LSnp7c^edY9CvDc1XYi}X|Hfm|(Nqm<4 z^%y8>=?Xi`up`ye<`~O|%0{f)_zs@+-}~N zJz3N@VGc+iMdZq886xm??LSgvin9y9Py%iuc)>@E$?F`x39&p!?qP%?ZC2TtC9E~)e0ZpC^sYreCRs? z!^)G1Z?eCemlkc}>*=c}0wcLq7*#M^_j0J&1Q~5mO2RFpeiZhyE;X3^v}_4+Ml~d2 zG@teEpA{>1+nZ0MtqZrPqzl;tv##wyI6B-GwVv<$cn*-z!Bs`Tp8V)!3^!&(`IWlW zwz4UPhPx)Y3Pf@>1ejW0kB;+s96?hZG0}#l$y@Oc7R>g&M+pTZSb@aT{Hb&HJ@F3x zLdv2!M~Cc)CYx?qUP0kH!!w5)a;?a5eUd=tw|_wh?a3iy`5qsKEpbrS))e(1*^eG`CFjT7w2>-qi{4pP-+|RCQKqnq(P=xAlpSZB z>=;4C%DwOr!_BMtbY0GteL&%<%kg7bbMhy+`kN|CgWL<-48@lCq2i8#L~mGzb-m7j9##K&n~IchnicNGnBHcA77jZZd2ix7!4m*4nJj# z_1im=R47%@US4ThAPa_BNjxf3@3tS5e&rqnCRW#@O1JdPoE1h1J%3WW&}qOd)MmF& zbvBJFj+0yOAowVqS@hgNiFV>Y1)B?2V_?%fC#4|}r|_5!$?Lo8N`BW;%1*cyMhK1$ z?Uo%QDQa-?JzAMs6jyrCh=-pM4ru6)yImD@Dj;PH(GYMfBV_e&w213y;B?=pV42); zhub(^mOW!4c$pd$K&U$cyJ#;66A3A4BeIM=sm~)^;ST6j!WJXBp;ONgGWW(>oJl;f znLu|&Kd9&4AA-~Ep0caDCykBV%k@y4cl_0ae-~#njh3XxTK7&S9JA-+G{UVUH@p-y zN1hlF`ZM;fPWb#H8`ScMnAwGNl^9|xpkS<;UbjNbs?go$Z-AtOp`-XSQVgfmFWbR; zxgbv+jSMuO%Cc2p=dt_&yb%m}6oW`-b1d6q6!ge#ckEU_fGH2{uKu7j#B=!i=uir- zebtXIXr1{;lTH-l=0*-;F;=L$OrRU5gB&{^G;#f-&4$>Hhv#-4&x9t#`Rld6*h~r_ z1TiAjBU3WPoruRDeuCTqU*)l!wGf5Q{YE2S_1PN7koa=R1UHfy0_!) zv}Vh%8+(QJ!7S~VsG8wL)f4@09U9xBgadJHOBz60prUjaE3f^gieK^VMA)tndY!G%- ziR|LrpzyKc6aKxW3U$ohYcWyu@a#zN<363d$3VuTY)LTLiD?#Uht+Em+w14NP36@- zh9QLnx@c&gw9QZVX+AdHDX0**DpD9iqZU=j`XDgt%w{hwQHxIwF6e8r^Hnw%Z%Y+) zRe^Z}zk2J#Yf#|9-woL;Jv=rV{>(aIG?kW|pLin^Xmz!9pcEYB_ z_m*7(d2ykS75H+4M;EpY4CG--)}k!ypTw&$hY1W{J1TMxw_zw31X)2S7#C z_$(J4?Hw-c*6MQ991D9fmFcT?DvhJ!lh%*l7>nusMG;6WhS?A!Bs58W+Oe7~YM3I9 ziy&TR0b!)WQ^dSf_9d7EG~VEwhx)gZx<1F-e+POwsX~e_ChVp?ywRqGZUF zP7%w3O<0)D#)8bkK{YL~iI?*sG#5vjX6Ki3oo&o>C|cRVY~9s_>M3G%9X z_8zR|v~*!8$M|0EzGRU41S;!{2`tD2zn%?-%tV9bw3T{QpRWPP0IPTqiSuNkOOUX$ zLxlB=JPvkfes|NL#;J#JMpYpjZCG!`C$y+x*Ov1tqfbREb2x38M!n{r^XWWFiP1c6 z0sn$Dbq1w%OyljQj_|_k!Ew~IZQRZVp)OVPihjw=Ju0595Gbp;A$xOEc&MF$>e3Jn z{IX7Uv>W-0_nu*DLP6_8&jjIa;M0(u`{Sl@r>aiFn2FQR&S^IQWn{!#B>cuECC$)I z-1Cr&8Pllk_K4xqJl+gr79rxpuhAt2kx}4JVSiF2N|rWDDDVMgN`5Cdv2B8Bo?Ww3 z5!!&kL~xC{wK(4(>03gGiB@i_=A*A@wS%k9`S)b_OI1Hr>?wAb1k_cxgB~}54>+Y6 z0v7HG>T%!9m>?X4FG)`-m8Zo3jK3AyM47R`%d6RtY9~OOI%+yIkHlojWJ$0pdIkAz z`X}f_zbXARHOi=mCxXI^K0Jo=L6lXw{4*cwMXuOWuYpr5EfsEOQR6r~zVgED?_!`E ze}LjQ{(y~mV@4ad?Q(3AQ5rjye1%ckWsS$MI(=ZzJ)7Ql6|py-t?2@mRLf$*kX}>O z+Q(&K$jnw4L!p+s8^E4n0;!fAm%vs1g(B&T=JmM9rd3arW>sEg+>jD^dh8b+Tu2O0 zY24^}A?FoodqKI~<210=R_ML+9p?OCD2ox|n&celUI!m?)~8T!ph_rtk4YJ43uGEumzln0DBBu+tT$wtl; z*aIguK&)1URo}TA&h3!9mO@7okPtcT5esE3Rs@sBqB{_A&QU1;ozW*6>&f*~*111~ zRky;0Z&fUyu=Mry>aVJg*?l_852^wjJ2DFi6QQW#r%h&K0Eh{2>`-4`84$4u8tVH> zu@8#T;W#eSuFrnK)j4un32~YaktEcWC(5?l4?rCQm&Gv#^1jl{Mps+M+!W5@c7uu* zyG7X__=rnT+33j=lg!~OKB#N#&YI$pestuwR!kNh|z6U+Zke*8aa z>;IAc{y%8zLiED)BJ?u!vh?!w%Jk~=2K0vXM)bz?CiEumM%D&4^rrNt7W8KH=JXcy z*7P>?w)A%N|2AUl$;pA~$;nt@krLB=W6*!|>j+8Uqdjv2tD)bpkal2*GmumX zfSmqNs8%)r4Kr#0Y;gaWth|`8ycE>_*~!UQJs~Y{Uw@GKkwK9Bewg@{7C=rSg^10K z4sP}I4DJArpHEZ)D`{~3!^1;^uT5M6OIXKx2CxkP6o1(h0xO0h#(AiGODk(YN5|hh zgyz5#Sy|UF8k*YL+GznRF;gvYWez0hNzf53# zBhydzE&d%p(8l`rO-yrZYbzV@W{0+VM&NW!^#A}##fNEGTiIxU{Fn*7PyuQ&t$O}> zP;&!N79i}e94-U`(hooY5VbcspV(12G*{W!=~y&Xzvb}W*%df_C_3OH8v`hyU!ezQkWPO9 zS-4pOyE%T;->CStH2^ZSQCR@u_>2(P#oIG|#_=b94DTN}G+O{2)w{O_K=t2`&(|zG z_d#iEo9ZpUtY4pD8Z5`fi^xcr-{h}4Md|4k*u9BiNPWZ8Jpg-$JAn50cEFuq?Bm^! zU#-twMU(sy{*G@%xzW)jwEovTr2d{yJ50LYY0ztaDIxGTJunfiJC-1T=Dx6BVruj% z#xW;vhu_GDU#_oTc4A61>Z-oy=3mCQ-v!_r+Ul*}1^~IHCS-SJ6zhRc zgGWCZR>5BlGtl^mkf!I~)4U2LZR)(@Ty0CZDK4e}Z&K!`#ILA6U&t=RblDsI z0Vp%Yujmy3TFSrc{15B^%q3r9hM-Y95YzcD^!otBJH27R6JX8F0JG0JtIIw`Sq9{J zL>@S_*gRi!_)-9_?^xg$mXDZzJW+u|xmZ;Ju}8lW>#IGI7##o6f7nOGUwp$_zu{kv zWWS*LZ?P}PqbL3sZ=B!B-#Fkmp6Fi@?Y-z|o0@*1XFJ?%KZ)uZztzvx=7#hyz=7oa zUBrGL;BR=~S3OTJv%AQjO-6gBy@f^~&0j=N?Vj^n3VmoL=rsPppORJ=*S8@+Yr~f; zkZShN%MPfIzaZJ4x3Z3b+@?3SW^j$~LqIf5Z@_^`ZC}8FbMJrg5w@~-MeKvR^q*Hl zzgL2^-o-@rpi__8QPDY4VcnU3=Yu{CKe@T2H>~&r8|C8HP(I@3-{nQG&p}10N+ePMt?L1jTV;REhS%2mZN7`9 ztoQJKVh2E79YHj-zHU(*zD1kzK!y>iPw@fBf}TU-=2%3=?H!9g5>F^OsE*RY^LG*-Y`em|%r&nBDM z-)&PZ<(N}qC!E#`hTZ{Df0%V#O#4HJYR*m*bf1=SB{r}VP#4YSl2Se2=2wQ{ZQ^w0 z!0xG-y==s#{dw9BV*TXhYY}uAS2$khcqpXw>3=(3r@2;P zQ+)E_HP*ix^kr(@%qXq1mzqD9$Nh{rDSL=&JiZ;-%SsPJJf)-Cnme(#HKlVZ)fG41 z!-(&cE#QRYa%EjHzCPkvp;}(WZi6I)aJ>!Bv!@?2FXbABO*Fbk<&ughVBexOX`H7M zvWfAoMdZDVDCM&MEzi7zjY|M0CcU8E;q)PqRi;4u&zh#Gp#;U~cj0>?M`6&gB zydySb*3Ccw-5bH@+&~OOCV#k@eolR(&o*^C=KQ7kn>j0)#w2ZkgtbzuGIp%69h%2fV4zAcs|BuDuJf8z-=`G6TFWiFoZdm>mO4c4qJ7pnZZ`3=eAC`V*~WY(zK^UW*!JrRQ5cNXbV&EI z8-NpEL94#;wa3luOH^$a=FW5=aedE&iObF8iq~Q&bH=y%=e|yGbuB?7q*TL`{qn?P z%jdch<;tPpuL_E37;kkX2e*=(YJ@GlZNfuPb`cF=k5TG{tW#Zu#fjbsRUyMAvEK1X zehqVt?Xy}1tJ?P+(P}72irRH-@6pp$56z3KPT9E~anS_zyTWtE z;K`~5;*4m97X8!Iuza$wI9X6gC}J|evHsCsw7svN^Mn7^lwxPPBK>p50apWphs?nCDAs5`v41uswvtgm zdMmtFRWBER{>-2`B1Zjm32o#N;$OKMz}A@0TW}59+>gY4x0jT93#}yWrhN zhH;#N{FAk5tsD5&wnsLNNC)Q(&cEf}P5izGcW-b{oVj{L+=UQ!M!Qm-ucx?VXXyD- z3tYM`?h~jarWYSGqxFg2ZASPu{b(PI)5%br?OayC6fZtQI=zt9qRY3B_Nd#qa(mBkEr8~Yo z)zFjr-@`gez}l8+AQP*F4ueqbm=T4zmW8ii7$faPd2b;&A6DgJ920bsi#EN!ns>P`S_BSG}-kXe2xpYMs4oyy8UOR*KVzui4TWd7giPjo# zQjQ;9$A145S?(qhP?2^P!~luDv0hI+dDDVDYHuRJ>cK-x8tfIBzj(s3&phvYCM+)* znoQd4gauW*V)yAgOOt4iY&{=i8P;yoUA>ikY}3^OnoEjb4YJ8w><%PbHMLyrriPtX zy3Hsj*Jo4l_E!=rU@GPzd4Me(Ou^nUN9AcskKg;8J9_c=2Ol@mzO#&-oA!$!wW4Qr zZGE65?9936=vX(}jEESqm^PcvrGNdTV&*5mJ;%H0Ln|mOoXD2xeL$h@?05tgTa=p$ z5<*r!c8*=$o6iP=Vnt%^yiAAn_7P(`Rka}7G(!j5yjoQQMqG>4w9#hf;S5vSJam+u zZCZ$h;2H`U0Dw8V4yCgLcA}rCkdc9yM*Os;7;cQAw$i2HfQr|Ykt$4aFu|th1?08w z;KD1KnV;rp#?y5Dz+gTOQV+~QIUv@>Dua1ki4QDQi{WERg4#|EQYW~i^|`~Gz&;;K zG5x(ii8AHFWGa^4z@x_}CsbA`d;|5=$G%DO=y_8GIKjdfKkiGrs zp?w&-?_PsBWnA}HDR8#s5~3$8lvL=#SEr$rU5+52p7>OWbbtspNs$TWbUT6|*Vwwn_Tl>@pN zrQXF+sDs;@Y16YqhPI`PqKR_TwV6P10~W2(+u`mZh7Wms6Rhroj~PVi8N7^tG;uvr zl-iI#e1^nSFu)d1=M;8Ak=;7vtJ$D(9?J8u@ZV*hSO?RD=2-*{!Zui_3uVe=8bwO* zQ7mfVQ~UbUX!-3rRacB2s?Pr%9MK= z=T^T>hDWS@^zxS+_BtR>h(amv^cer^U4peL3Dp@;pbd3A#*DS!v{{k1$S#4NMWPX} zQV?>qVxm~Ye@HSFo$Ig~%22Fe?p_+=s}v#c!&d39QcEMrXpVJTCTc5*A_7MY(<$Y# zKvgO$e}0vQ!{t$=Hb{5thO-Di02|~@X)QY@#Tz?B1SZT5+bttYGGt`}Yt?T5$4(Ie zCp>t?Fy!e>e>4B6blBp-_h}VnOTTHWY3*d6&%N~Os2Whvx26slCwcOgu~Yh_g42(q z*=Ap_%hT;#W{W_BU-eH{5f>NRz-0EC3hq#=?Ca6rMC z33M%#@#@rR+0a}K(|okV(a<2K#=qB%Thx$KDQQS9s#~{ex1_9bb#;~>s<~H8^xtuO zAhRj_X1Ocza%S+*tO+sl$?ov_pt;13(3ndh!TIJeYN=&L$EP(KO2G!`;B z7qBS%^tmD)iEKgvZ3bQ-V&I2dN?^N=El)P|fp9bsA~84u?bbyM_$mx;uaP3RGd@B= z{$w`ZkijU@aBVXNgaN@@QGEqoRc61g(B7?u(hme%G4)wZcgFdc-ceXg|M$W(rqJyS zJ*xCS03m~_Ma~u-Gu2dd{T5jUA>HCV!LxO4ia8>^sI)+_9O~+-YqB=P-iJE)DUN3g zLyhMdnJoGlhpDy0rYiFfmZt4P=qh#g4tZrwB)=Rj5Fa(9^rqeC<^7J5VHZ1lM9BIi zcmA74FY~o+b$&6R_&3&FX&+>9XIY%^h&P3oJ(I&%U=|@<#hJm@TB`0BMnCB_^M2RT zW;QGkPLmkYTt+go!5`79GfYm;d1u(iTNyxBk;|#YV2*pt_}qfX_H6c@iNtapUS+ag z_@RI!+JzmN`nV6tKVn;`0J;S8LjtomWc}dQ>lh(t!=ZNk$nx+!dtCr zcYIzk*ql{e7l%Oz3GB$aidan!&q2eyKo3v;S?)EEV2a5^Hk>|TS)CHzQ%M!y%5oni zaIfVG+8Xj!g1~efb1_m?_0Wd`e_wc;s!lya3rK2)`n>gW~ahL5tW~#jl=addQnyZdW zciyXRbS`qz2_k|~|9wR{&Gfl#!MJy8j9~JZc5K+j;QST~HlK9cwO(dDWutf80dHr8 z{=Il~Ud$c$aY+kEoEC+K7aT>2GRx+R4&zRW7y{|Vj-)iu9pg9$CX2foogO@{%O6?4 z>GE8zUc}AJZVSfC1)(Jug$-#M%}b6!@CN%POpRB6wDkP+MU`LQ4cm&Tc%yixfo3w*6F+DjmFkSt^0$r6lOA{CDo|SV~j##B6G-i4tOoZQDE_ zl={?+S$JKCdH{Wv)#$AW`7ckT1-iQZz5F^-Ch|wI`B4bMiR4LhjIBDS=?_^4eosm) z1WCqnG?p{NiI(>wBMb)-OYhPz!FWg&`H?awQ5@+gZF!C@NAKDn5fRE3*aVq~g{y*_ zL5usvrGg%Ku3TUGI1Zvle69(j!lkr6ek|iUOiZBYKB98nn&GJvx8b5dH^KsPH3Xb6 zVhI<1&8^lWrQ~;rEUs}>8@|5K(I-a617Ee=VRN{$u!arkiO^7Vvm=Z4>c&Wz+nOV7 zh!}u-DF$ph0%vj(r=_&eJ#u+71br6)WhO0$DJQvHc8jC37a5X_FJObjs_kMEFxi9d z4zx|39Do^_2^Q-f-vr*wJ(TNrx!o{4y7L=$K>}UpAdbD_AM8Jhz`{u=U{#K+j&exQ zH+5iia9EPN4t>D{0;3s&r1(c5$r<3b=?%plEyq48*__zfDrV@tOvt|h-vfO(S%YvB zT3TSbvg~`l1knvnFS0Dp+9Dp=D7x=SA$vKcSVy{sf;f{W5eDghixt%aAM`ty-LGmg z$-l)^TiB6Fl!pwdy*eU0##;vKt0gF1LF&xtAJCsAG@n^1s4riUBm_j-c?t9RONF>k z4G+2@26`mSG$iE~1Eg5dU2&HjtjN$I%Jc@6LkcF|avDLGs*K*QZ3d#oiYx6#;9FtQWZ9@fr<(dBvBC4F;lF~I43XJY8-@8wH>8B{Y1JIfo*{>XXi zm$-+vp;!f*a3X0&!X9tzTQkVR#K;YI2Fxj#&zo$&!et)Y54{c@yW}*TKfj$coe1!F%SQR(`((7?5Nn4Bae8bRp;*ae7@&c zGW<#IEjxhkNpx|yK+!IvWlvhUy{@Z!tZ-H03;g?g*xaX;bkIYPdiQ4heL3Go(v9nIpK zn`zt-qz@M`Ty_>LD3FaXjXr;3ZP0zo(LjB98fjd8xV#nwD@Dmy%`Iez*Z|Q9;r$r% z1$WTk+TuvC0J;O`SAMj3vd4sl(Pa z5k1hbXCJFLaOAHzReu`E{y=ok=^>85W9WBvLdbyh4EHi8;iW}U$67Y*b2lC+3v4nj z$HnTl4ydxLg0J^y5h}uI!U~NPSi*yN=Iz}@dtiQB>!Y0l*-klqmcszm_1nzxgL*D? z3!6!|VIdZSdK~dY#h79fJCSlL)Z>%^ous3bKxH3N6?cH?;Ds9W+geMaye8z41Vylh z0hvG?PGr~2ylEm1Faf5;NoiiQbA)tbJ32+KygfHN_`3Y;%81mw@lPqD#xkOju(W6m zrKRueF_aUg^IE)EWclLD#7N{~)#AZT^7772A@F$+_HcC2_3URDyn%}a9bOtZCU5|H ze*Ll3tol%5frEU-f{taCeFvBf>-;rP7)VE&uN4rw0|k8J47s9#oc7m;l)K6z>?ONn znDd{pXbF}3N}qDKp4~061bmlMywfMpiS)=diay5)@)~M={c#4!p1oP}i7$VBXx4)9 z;pF2_!5lJVXk2Lp;B+j8sC9FeQaj`!e`AV@VU3iSX9<1= zG&TmMx8V|_O}nnp9x3HSCG@u$7Iu&gaJxh4PBrrzi;8_?qG(2N-Zmnav8%t~c*!L6 zs!0sama~b34AKcB^Ki8o*ZPj1;W^ttoks%}FbSz5ZFF_WC0Skh?uz&Vhv^VRI`sG&ysy&m2yWMAh9w4I7Go!W)6q;&Ud z4bQ#^hRUfc#06ssK+i0UsnZCX?3j!2j5npvxa>r|M-t|l@vl+q7A@pxq8$`uALS!k z;VVAs^{Jck?;G%cx^hPXGuQ2nn`;L`WrGGPOdu3gex#7p1YICwi0Y^_|6ri<1d;Sf zp(qYhcpx}GTCaOl+^Q1QkHf0zOJZ}5*3V+S*P1#ap!m4>>Pp%kwObg_53l{Ij+rL6 z*O3Gn^|3>-@XBhb8?m(;f2s%ng>x74sC3+Y%KUrRsCf^dl_Lb)Lpx<>tud;AqCXj1 zoIc+_M@WZ9o*&G2@rUj#id&nUYWlU-iVh{6A&UPh;`=V2VFhi$UFw>)&+af=c!B-2e z>X~&kww~fKP(v`8jHe;)eZoLAM9GzriXZL*DKm`v_TPhxi6lI2v+y8Xf`yYuk%6t0;|~ZvL0Uq z%>c|rYI$x1M#qZBwcb5n#z?GHQb4$S!3!6Rhn>_6MsNn&<7wJH#Ua&`UXkY+sBv6* zB|3yt?~r2+$AO`X0fa-8-<-~QVRYfPLz!HPx=vq1IFqqFazr{NIqNlgNq*x8b8iuE zqK+r^H!o^R0vMgfqs-rINE>QAAq$%TzIcTf*i&sQm=*KmCdRNVA`CifIJCBF-@$>M zaQ^sR#|->~PLQ(J2P;p1akRwVoSu|Wcs}1qkij$S&BF6XJiQwdXxrQdvj5Bx7ahCQS-|$vBq7>D~ovOk3lM>esIcR z^#2OYsG#L>*rV>r_oA~?!@h2dZ?%vcx}{=pJ@Zf9`jPx3x2XYwKW8f2Xs-&TgMwN~ zhDRkjYg6t_T~2G%S|*<{HkAYG37ZEegVS--*KKWj@M=`+lt?NB~L5)E!l`FvSPVM!cG; zTSh7638+i4srVd7&mQ+jx9fgtWwAf0T=?$o*xRi6F9hj2GSdUR1^<0d&)SE8z4_t!w)zsv0u5! z-%gssv`HlK5!oHmh|VS~UAsNzDj;j5mdb{U+bD>EB2rGwi#?uiD0OfC$$!B_t3@Il zBKiT?Ihb#B%91+ZVlUnLG09B~N^;xfMwMco=B+ zOQEZ=FLf6}zy70ZO~KB`ccUgXPX>bp+-6{&P{9+mUX^>h`JoYze{fOC;EN>)?QHbhHzEk^AQ2m&IR3&_5wcD-9flGMP z3{eRC5B+QZr2P4#gu@Z4bo=*^8}wnGLi$<88y&2beDaeK4RU^g9;Ep@uxqA`O~%Y1 zMmK>`!3UgE+F1fv{zxCB;9B&;Vr1ejL8dZ&EY0^~K)-^tEAI zsXJcRLKjcHcCmgy-_clKOoLxPW0gk`Pr-Oz8Q!Z9a};R41%X_`{+2pR%~_2&uP7o{ z>!<6z?(a`EkD24xyVCAk>NMBKn#ttXn9u(7LAF{c>I%Hn(V#sXbw=={nC0WSE)5@K zbZ6;jjo8@(Sl%$_xsYC6h(l2E>h5ItVhecp3!0X+`0r;h;3vz?=5>To*{>}{KoG1vlT?2P7c6OQ_Ty021Sd$q2Hb@$=M zbMB|fxffbG5V+3;;pwNY>UYasPiqPMh#6Vz@H1$;1THw^q8-w3-lp@2ccC3;@G>JS zKMvvukZ>-r`q%~+JS>JAQVbOjFKt(+L&!J1JmX{*?D2t-umg7fAv+ZMJ`{xLm;`>* z7f7D*d+_IeCnNHCd1B@}bNwyu5w_<${lbtN9H zIdipeuaBHth@J{?iNTkrWYhu?$luIa5>}Gp=y$e2e%S z?OI>6mKVpzt+SChsSWNcf$e4-qXz<3Ujf+U$m2(QO!dTo-D66Rv+x|}K=97lLzjw{ zneLSZu@vy;;NjPH*)1rU*EWa>cSyfoT0!@*AvabB@$#TjcRB8hYO^BQ>Wfk4?0)Y% z5j6Jmpt>v;LTV$T(i)me6a9swTp16`aCaEus6J<33aB=yUkg~Y|Ffi&DQt)9^ohL*UqoF;Un z;6KZfm?ABTnMfeI_(_KdeK7Y-`~)v#!x^snlq~VKwVH{%4QkQ*FTBLoq-pRi@*6i~Lc=7>Yx74C(@&Vg z%Iy{cXtNMI1~Lm2^=J*2ZZJW>3yLroJ!8c75w+A;?j* z^~d2awYjH^|4`jb+ePL$9DOm2L?App15-1(fIZI^Nh*KuFInrxoDOT19?hv!#34~V zQru+F#73_Nd!MjF+~qxEyC+-*Myy;;vt4#7h`$Yvy!MLXth(mVu}nBM2;zoYT@5S( zIRGS2RHXA0`%yV1H40_OkA*0^f;5`7pnZ(Is;vr>M4!tV%jXt9I*i`+Xo%pbG?ID- z%eO=JP^nX(5tw~OgoZY)FKmHhUNBv;c~4Gf4ddF??~I+tFiC)Q$Ihzj7P_}H}dU8L*e;~`P< zIeT~4{_TU!jC#}4347WddLtk1kxb7=orFbmEeC8zx$o){uPiGX+1rKdgXzp8?P#rD zr;}US6vr5>T#4cNGS=-(nWnRcm%_2#$EOhViPdfYc=aKvdlhUln2Kxbp=O0igkJ8N zLbRJ?Wd?6k-(^x6u^sSyh#5(-M0gFZ6D7_o%dfDgrAFVKZh?p;y?z95n-Yt}(z~a1 zd`#YLH=bmN^!B|ye5Xl-Lm(PIOtG5nsl>DB*#|y0zITp2`rFd-Q#%tHGH#7yd-Zg> zPaYldWFok(VY8e0{E=qCk&k7ava*U&C)eI%&CF?3;&2@84k!)6n7YlY_oA#^Y3r|v z@af8d@GMPUu8>Up@QCuHJ7#*SIbkv|71C=A-BQ1ew90$T;zj5DAiv7@e2`t8{hd1+ z)`?b6jP6c)(G+i4G{=5Ao$n#y+-y^LWUWn4(WPQjCGUHZ64U3ywYE_kJ#O|zIq|+v zZZPZj#Iaq!jr+D9sYIi*eh3;`<65(Fg}Y{j#J=ij8j0Ps%L)gtM1{b`X;^*51ov_k z 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 NhT<|Yi7ANV{y*A#bcO%` literal 0 HcmV?d00001 diff --git a/odemex/MATLAB_models/addTwo.m b/odemex/MATLAB_models/addTwo.m new file mode 100644 index 0000000..f837e85 --- /dev/null +++ b/odemex/MATLAB_models/addTwo.m @@ -0,0 +1,30 @@ +function y = addTwo( in1, in2 ) + + y = in1 + in2; +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/MATLAB_models/goodwin5.m b/odemex/MATLAB_models/goodwin5.m new file mode 100644 index 0000000..3a951ac --- /dev/null +++ b/odemex/MATLAB_models/goodwin5.m @@ -0,0 +1,26 @@ +function dx = goodwin5(t,x,p,u,modelStruct) + +% Parameters: +oa1 = p(1); +oa2 = p(2); +alf = p(3); + +k1 = p(4); +k2 = p(5); +k3 = p(6); +k4 = p(7); + +rho = 10; + +x1 = x( modelStruct.s.x1 ); +x2 = x( modelStruct.s.x2 ); +x3 = x( modelStruct.s.x3 ); +x4 = x( modelStruct.s.x4 ); +x5 = x( modelStruct.s.x5 ); + +dx( modelStruct.s.x1 ) = ( oa1 / ( 1 + oa2 * intPow(x5,rho) ) ) - alf * x1; +dx( modelStruct.s.x2 ) = k1 * x1 - alf * x2; +dx( modelStruct.s.x3 ) = k2 * x2 - alf * x3; +dx( modelStruct.s.x4 ) = k3 * x3 - alf * x4; +dx( modelStruct.s.x5 ) = k4 * x4 - alf * x5; + diff --git a/odemex/MATLAB_models/goodwinN.m b/odemex/MATLAB_models/goodwinN.m new file mode 100644 index 0000000..85bcfd6 --- /dev/null +++ b/odemex/MATLAB_models/goodwinN.m @@ -0,0 +1,15 @@ +function dx = goodwinN(t,x,p,u,modelStruct) + +% Parameters: +a1 = p(1); +a2 = p(2); +alf = p(3); + +rho = 2; +order = 24; + +dx( modelStruct.s.x1 ) = ( a1 / ( 1 + a2 * intPow(x(24),rho) ) ) - alf * x( modelStruct.s.x1 ); + +for k1 = 1 : order + dx( modelStruct.s.x1 + k1 ) = p( modelStruct.p.k1 + k1 ) * x( modelStruct.s.x1 + k1 - 1 ) - alf * x( modelStruct.s.x1 + k1 ); +end \ No newline at end of file diff --git a/odemex/MATLAB_models/mymodel1.m b/odemex/MATLAB_models/mymodel1.m new file mode 100644 index 0000000..3b6dccc --- /dev/null +++ b/odemex/MATLAB_models/mymodel1.m @@ -0,0 +1,33 @@ +function dx = mymodel1(t, x, p, u, myStruct) + +dx(1) = u(1) - p(1) * x(1) + p(2) * x(2); +dx(2) = p(1) * x(1) - (( p(3) /4) + p(2)) * x(2); + +dx = dx(:); +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/MATLAB_models/mymodel2.m b/odemex/MATLAB_models/mymodel2.m new file mode 100644 index 0000000..983677a --- /dev/null +++ b/odemex/MATLAB_models/mymodel2.m @@ -0,0 +1,44 @@ +function dx = mymodel2(t, x, p, u, myStruct) + + p1 = p( myStruct.p.k1 ); + p2 = p( myStruct.p.k2 ); + p3 = p( myStruct.p.k3 ); + x1 = x( myStruct.s.x1 ); + x2 = x( myStruct.s.x2 ); + u1 = u( myStruct.u.u1 ); + c1 = myStruct.c.c1; + + temp1 = u1 - p1 * x1; + temp2 = p2 * x2; + + dx( myStruct.s.x1 ) = temp1 + temp2; + dx( myStruct.s.x2 ) = p1 * x1 - addTwo((p3/c1), p2) * x2; + + dx = dx(:); +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/MATLAB_models/mymodel3.m b/odemex/MATLAB_models/mymodel3.m new file mode 100644 index 0000000..3bb5aa4 --- /dev/null +++ b/odemex/MATLAB_models/mymodel3.m @@ -0,0 +1,37 @@ +function dx = mymodel3(t, x, p, u, myStruct) + + p1 = p( myStruct.p.k1 ); + testThingy = u(myStruct.u.u1 ); + + dx( myStruct.s.x1 ) = interpolate( &u(myStruct.u.time1), &u(myStruct.u.linear1), 6, t, 1 ); + dx( myStruct.s.x2 ) = interpolate( &u(myStruct.u.time2), &u(myStruct.u.linear2), 6, t, 1 ); + + dx = dx(:); + +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/MATLAB_models/mymodel4.m b/odemex/MATLAB_models/mymodel4.m new file mode 100644 index 0000000..057eb94 --- /dev/null +++ b/odemex/MATLAB_models/mymodel4.m @@ -0,0 +1,43 @@ +function dx = mymodel4(t, x, p, u, myStruct) + + dx( myStruct.s.x1 ) = 0; + dx( myStruct.s.x2 ) = 0; + + if ( ( t > 5 ) && ( t < 10 ) || ( t < 2 ) ) + dx( myStruct.s.x2 ) = 1; + else if ( t > 7 ) + dx( myStruct.s.x1 ) = 1; + dx( myStruct.s.x2 ) = 2; + else + dx( myStruct.s.x2 ) = 0; + end + end + + dx = dx(:); +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Parser/CVode/chooseCompiler.m b/odemex/Parser/CVode/chooseCompiler.m new file mode 100644 index 0000000..8eb00ad --- /dev/null +++ b/odemex/Parser/CVode/chooseCompiler.m @@ -0,0 +1,164 @@ +%% Mandatory Settings + +% compiler = 1; % lccwin32 +compiler = 2; % msvc +% compiler = 3; % GCC under windows +% compiler = 4; % GCC under linux + +% Don't forget to call mex -setup when you switch compiler (not needed for +% GCC) + +lapack = 'libmwlapack.lib'; +blas = 'libmwblas.lib'; + +%% Common Settings + +lccLocation = [ matlabroot '/sys/lcc' ]; + +[junk,parserDir] = strtok( fliplr( fileparts( mfilename( 'fullpath' ) ) ), '/\' ); +parserDir = fliplr( parserDir ); +cvodeDir = [ parserDir '/CVode' ]; + +%% LCC-Win32 +if ( compiler == 1 ) + + % O2 means optimise for performance, not space! + flags = '-O2 '; + + + % Don't set these unless you're having trouble \/ + compilerLocation = [ matlabroot '\sys\lcc' ]; + algebraDir = [ matlabroot '\extern\lib\win32\lcc' ]; + lapack = [ algebraDir '\' lapack ]; + blas = [ algebraDir '\' blas ]; + libraryName = 'CVODE.lib'; + idaName = 'IDA.lib'; + extraflags = ' '; +end + +%% Microsoft Visual C++ 2008 +if ( compiler == 2 ) + + % If you use MSVC, adjust these to the appropriate location \/ + %vsroot = 'D:\Program Files\Microsoft Visual Studio 9.0'; + %netroot = 'C:\WINDOWS\Microsoft.NET'; + %vsroot = 'C:\Program Files (x86)\Microsoft Visual Studio 10.0'; + %netroot = 'C:\Windows\Microsoft.NET'; + vsroot = ''; + netroot = ''; + + % \/ Base your choice of optimisations here + %* P2: G6 is fastest (official builds are G6) + %* P3: G6 SSE is fastest + %* P4: G7 SSE2 is fastest + %* Celeron: Depends on whether your Celeron is P2-based, P3-based, or P4-based. + %* Athlon XP: G7 may be faster than G7 SSE even though SSE is supported + % + % O2 means optimise for performance, not space! + % + % -ffast-math very fast math, b + flags = '-O2 '; % /fp:strict'; + + + % Don't set these unless you're having trouble \/ + compilerLocation = [ vsroot '\VC' ]; + if strcmp(computer, 'PCWIN') + algebraDir = [ matlabroot '\extern\lib\win32\microsoft' ]; + else + if strcmp(computer, 'PCWIN64') + algebraDir = [ matlabroot '\extern\lib\win64\microsoft' ]; + else + disp( 'WARNING: Could not identify computer. Cannot link against lapack/BLAS' ); + end + end + lapack = [ algebraDir '\' lapack ]; + blas = [ algebraDir '\' blas ]; + libraryName = 'CVODE.lib'; + idaName = 'IDA.lib'; + extraflags = ' '; +end + +%% GCC --> Win +if ( compiler == 3 ) + + % To use the GCC compiler, obtain GNUMEX from + % http://gnumex.sourceforge.net/ + % and install it in the subdiretory parser/gnumex + % Follow the instructions, and set up cygwin. + % Copy the cygwin1.dll in the directory where you want to solve + % things under windows. Cygwin is used to run linux stuff on windows + % machines so you can test. + % Use gnumex to create a .bat file (in the gnumex dir!) with appropriate mex options + % and reference it by changing this line: + gnumex = [ parserDir '\gnumex\mexopts.bat' ]; + flags = '-ffast-math'; % /fp:strict'; + cygwinLib = 'C:\cygwin\bin\'; + + + % Don't set these unless you're having trouble \/ + %vsroot = 'D:\Program Files\Microsoft Visual Studio 9.0'; + %compilerLocation = [ vsroot '\VC' ]; + algebraDir = [ matlabroot '\extern\lib\win32\microsoft' ]; + lapack = [ algebraDir '\' lapack ]; + blas = [ algebraDir '\' blas ]; + extraflags = [ '-f ''' gnumex '''' ]; + libraryName = 'CVODE.a'; + idaName = 'IDA.a'; + copyfile( [ cygwinLib, 'cygwin1.dll' ], parserDir ); + +end + +%% GCC --> For deployment on Linux stations! +if ( compiler == 4 ) + + % To use the GCC compiler, obtain GNUMEX from + % http://gnumex.sourceforge.net/ + % and install it in the subdiretory parser/gnumex + % Follow the instructions, and set up cygwin. + % Copy the cygwin1.dll in the directory where you want to solve + % things under windows. Cygwin is used to run linux stuff on windows + % machines so you can test. + % Use gnumex to create a .bat file (in the gnumex dir!) with appropriate mex options + % and reference it by changing this line: + gnumex = [ parserDir '/gnumex/mexopts.bat' ]; + flags = '-ffast-math'; % /fp:strict'; + + + % Don't set these unless you're having trouble \/ + %vsroot = 'D:\Program Files\Microsoft Visual Studio 9.0'; + %compilerLocation = [ vsroot '\VC' ]; + algebraDir = [ matlabroot '/extern/lib/linux/microsoft' ]; + extraflags = ''; + libraryName = 'CVODE.a'; + idaName = 'IDA.a'; + +end + + +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Parser/CVode/cv_src/include/cvodes.h b/odemex/Parser/CVode/cv_src/include/cvodes.h new file mode 100644 index 0000000..f368530 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/cvodes.h @@ -0,0 +1,1968 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.22 $ + * $Date: 2008/04/16 21:53:06 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the interface file for the main CVODES integrator. + * ----------------------------------------------------------------- + * + * CVODES is used to solve numerically the ordinary initial value + * problem: + * + * y' = f(t,y), + * y(t0) = y0, + * + * where t0, y0 in R^N, and f: R x R^N -> R^N are given. + * + * Optionally, CVODES can perform forward or adjoint sensitivity + * analysis to find sensitivities of the solution y with respect + * to parameters in the right hand side f and/or in the initial + * conditions y0. + * + * ----------------------------------------------------------------- + * + * 1: CONSTANTS + * input constants + * return flags + * + * 2: FUNCTION TYPES + * CVRhsFn CVQuadRhsFn CVSensRhsFn CVSensRhs1Fn CVQuadSensRhsFn + * CVRootFn + * CVEwtFn + * CVErrHandlerFn + * CVRhsFnB CVRhsFnBS + * CVQuadRhsFnB CVQuadRhsFnBS + * + * 3: INITIALIZATION AND DEALLOCATION FUNCTIONS FOR FORWARD PROBLEMS + * CVodeCreate + * CVodeInit CVodeReInit + * CVodeQuadInit CVodeQuadReInit + * CVodeSensInit CVodeSensReInit + * CVodeRootInit + * CVodeFree CVodeQuadFree CVodeSensFree + * + * 4: OPTIONAL INPUT FUNCTIONS FOR FORWARD PROBLEMS + * + * 5: MAIN SOLVER FUNCTION FOR FORWARD PROBLEMS + * CVode + * + * 6: EXTRACTION AND DENSE OUTPUT FUNCTIONS FOR FORWARD PROBLEMS + * CVodeGetDky + * CVodeGetQuad + * CVodeGetQuadDky + * CVodeGetSens CVodeGetSens1 + * CVodeGetSensDky CVodeGetSensDky1 + * CVodeGetQuadSens CVodeGetQuadSens1 + * CVodeGetQuadSensDky CVodeGetQuadSensDky1 + * + * 7: OPTIONAL OUTPUT FUNCTIONS FOR FORWARD PROBLEMS + * + * 8: INITIALIZATION AND DEALLOCATION FUNCTIONS FOR BACKWARD PROBLEMS + * CVodeAdjInit CVodeAdjReInit + * CVodeAdjFree + * CVodeInitB CVodeInitBS CVodeReInitB + * CVodeQuadInitB CVodeQuadInitBS CVodeQuadReInitB + * + * 9 MAIN SOLVER FUNCTIONS FOR FORWARD PROBLEMS + * CVodeF + * CVodeB + * + * 10: OPTIONAL INPUT FUNCTIONS FOR BACKWARD PROBLEMS + * + * 11: EXTRACTION AND DENSE OUTPUT FUNCTIONS FOR BACKWARD PROBLEMS + * CVodeGetB + * CVodeGetQuadB + * + * 12: OPTIONAL OUTPUT FUNCTIONS FOR BACKWARD PROBLEMS + * + * ----------------------------------------------------------------- + */ + +#ifndef _CVODES_H +#define _CVODES_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +#include + +/* + * ================================================================= + * + * CVODES CONSTANTS + * + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Enumerations for inputs to: + * CVodeCreate (lmm, iter), + * CVodeSensInit, CvodeSensinit1, CVodeSensReInit (ism), + * CVodeAdjInit (interp), + * CVode (itask) + * ----------------------------------------------------------------- + * Symbolic constants for the lmm and iter parameters to CVodeCreate + * the input parameter itask to CVode, and the input parameter interp + * to CVodeAdjInit, are given below. + * + * lmm: The user of the CVODES package specifies whether to use + * the CV_ADAMS or CV_BDF (backward differentiation formula) + * linear multistep method. The BDF method is recommended + * for stiff problems, and the CV_ADAMS method is recommended + * for nonstiff problems. + * + * iter: At each internal time step, a nonlinear equation must + * be solved. The user can specify either CV_FUNCTIONAL + * iteration, which does not require linear algebra, or a + * CV_NEWTON iteration, which requires the solution of linear + * systems. In the CV_NEWTON case, the user also specifies a + * CVODE linear solver. CV_NEWTON is recommended in case of + * stiff problems. + * + * ism: This parameter specifies the sensitivity corrector type + * to be used. In the CV_SIMULTANEOUS case, the nonlinear + * systems for states and all sensitivities are solved + * simultaneously. In the CV_STAGGERED case, the nonlinear + * system for states is solved first and then, the + * nonlinear systems for all sensitivities are solved + * at the same time. Finally, in the CV_STAGGERED1 approach + * all nonlinear systems are solved in a sequence. + * + * itask: The itask input parameter to CVode indicates the job + * of the solver for the next user step. The CV_NORMAL + * itask is to have the solver take internal steps until + * it has reached or just passed the user specified tout + * parameter. The solver then interpolates in order to + * return an approximate value of y(tout). The CV_ONE_STEP + * option tells the solver to just take one internal step + * and return the solution at the point reached by that step. + * + * interp: Specifies the interpolation type used to evaluate the + * forward solution during the backward integration phase. + * CV_HERMITE specifies cubic Hermite interpolation. + * CV_POYNOMIAL specifies the polynomial interpolation + * ----------------------------------------------------------------- + */ + +/* lmm */ +#define CV_ADAMS 1 +#define CV_BDF 2 + +/* iter */ +#define CV_FUNCTIONAL 1 +#define CV_NEWTON 2 + +/* itask */ +#define CV_NORMAL 1 +#define CV_ONE_STEP 2 + +/* ism */ +#define CV_SIMULTANEOUS 1 +#define CV_STAGGERED 2 +#define CV_STAGGERED1 3 + +/* DQtype */ +#define CV_CENTERED 1 +#define CV_FORWARD 2 + +/* interp */ +#define CV_HERMITE 1 +#define CV_POLYNOMIAL 2 + +/* + * ---------------------------------------- + * CVODES return flags + * ---------------------------------------- + */ + +#define CV_SUCCESS 0 +#define CV_TSTOP_RETURN 1 +#define CV_ROOT_RETURN 2 + +#define CV_WARNING 99 + +#define CV_TOO_MUCH_WORK -1 +#define CV_TOO_MUCH_ACC -2 +#define CV_ERR_FAILURE -3 +#define CV_CONV_FAILURE -4 + +#define CV_LINIT_FAIL -5 +#define CV_LSETUP_FAIL -6 +#define CV_LSOLVE_FAIL -7 +#define CV_RHSFUNC_FAIL -8 +#define CV_FIRST_RHSFUNC_ERR -9 +#define CV_REPTD_RHSFUNC_ERR -10 +#define CV_UNREC_RHSFUNC_ERR -11 +#define CV_RTFUNC_FAIL -12 + +#define CV_MEM_FAIL -20 +#define CV_MEM_NULL -21 +#define CV_ILL_INPUT -22 +#define CV_NO_MALLOC -23 +#define CV_BAD_K -24 +#define CV_BAD_T -25 +#define CV_BAD_DKY -26 +#define CV_TOO_CLOSE -27 + +#define CV_NO_QUAD -30 +#define CV_QRHSFUNC_FAIL -31 +#define CV_FIRST_QRHSFUNC_ERR -32 +#define CV_REPTD_QRHSFUNC_ERR -33 +#define CV_UNREC_QRHSFUNC_ERR -34 + +#define CV_NO_SENS -40 +#define CV_SRHSFUNC_FAIL -41 +#define CV_FIRST_SRHSFUNC_ERR -42 +#define CV_REPTD_SRHSFUNC_ERR -43 +#define CV_UNREC_SRHSFUNC_ERR -44 + +#define CV_BAD_IS -45 + +#define CV_NO_QUADSENS -50 +#define CV_QSRHSFUNC_FAIL -51 +#define CV_FIRST_QSRHSFUNC_ERR -52 +#define CV_REPTD_QSRHSFUNC_ERR -53 +#define CV_UNREC_QSRHSFUNC_ERR -54 + +/* + * ---------------------------------------- + * CVODEA return flags + * ---------------------------------------- + */ + +#define CV_NO_ADJ -101 +#define CV_NO_FWD -102 +#define CV_NO_BCK -103 +#define CV_BAD_TB0 -104 +#define CV_REIFWD_FAIL -105 +#define CV_FWD_FAIL -106 +#define CV_GETY_BADT -107 + +/* + * ================================================================= + * + * FUNCTION TYPES + * + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Type : CVRhsFn + * ----------------------------------------------------------------- + * The f function which defines the right hand side of the ODE + * system y' = f(t,y) must have type CVRhsFn. + * f takes as input the independent variable value t, and the + * dependent variable vector y. It stores the result of f(t,y) + * in the vector ydot. The y and ydot arguments are of type + * N_Vector. + * (Allocation of memory for ydot is handled within CVODES) + * The user_data parameter is the same as the user_data + * parameter set by the user through the CVodeSetUserData routine. + * This user-supplied pointer is passed to the user's f function + * every time it is called. + * + * A CVRhsFn should return 0 if successful, a negative value if + * an unrecoverable error occured, and a positive value if a + * recoverable error (e.g. invalid y values) occured. + * If an unrecoverable occured, the integration is halted. + * If a recoverable error occured, then (in most cases) CVODES + * will try to correct and retry. + * ----------------------------------------------------------------- + */ + +typedef int (*CVRhsFn)(realtype t, N_Vector y, + N_Vector ydot, void *user_data); + +/* + * ----------------------------------------------------------------- + * Type : CVRootFn + * ----------------------------------------------------------------- + * A function g, which defines a set of functions g_i(t,y) whose + * roots are sought during the integration, must have type CVRootFn. + * The function g takes as input the independent variable value + * t, and the dependent variable vector y. It stores the nrtfn + * values g_i(t,y) in the realtype array gout. + * (Allocation of memory for gout is handled within CVODE.) + * The user_data parameter is the same as that passed by the user + * to the CVodeSetUserData routine. This user-supplied pointer is + * passed to the user's g function every time it is called. + * + * A CVRootFn should return 0 if successful or a non-zero value + * if an error occured (in which case the integration will be halted). + * ----------------------------------------------------------------- + */ + +typedef int (*CVRootFn)(realtype t, N_Vector y, realtype *gout, void *user_data); + +/* + * ----------------------------------------------------------------- + * Type : CVEwtFn + * ----------------------------------------------------------------- + * A function e, which sets the error weight vector ewt, must have + * type CVEwtFn. + * The function e takes as input the current dependent variable y. + * It must set the vector of error weights used in the WRMS norm: + * + * ||y||_WRMS = sqrt [ 1/N * sum ( ewt_i * y_i)^2 ] + * + * Typically, the vector ewt has components: + * + * ewt_i = 1 / (reltol * |y_i| + abstol_i) + * + * The user_data parameter is the same as that passed by the user + * to the CVodeSetUserData routine. This user-supplied pointer is + * passed to the user's e function every time it is called. + * A CVEwtFn e must return 0 if the error weight vector has been + * successfuly set and a non-zero value otherwise. + * ----------------------------------------------------------------- + */ + +typedef int (*CVEwtFn)(N_Vector y, N_Vector ewt, void *user_data); + + +/* + * ----------------------------------------------------------------- + * Type : CVErrHandlerFn + * ----------------------------------------------------------------- + * A function eh, which handles error messages, must have type + * CVErrHandlerFn. + * The function eh takes as input the error code, the name of the + * module reporting the error, the error message, and a pointer to + * user data, the same as that passed to CVodeSetUserData. + * + * All error codes are negative, except CV_WARNING which indicates + * a warning (the solver continues). + * + * A CVErrHandlerFn has no return value. + * ----------------------------------------------------------------- + */ + +typedef void (*CVErrHandlerFn)(int error_code, + const char *module, const char *function, + char *msg, void *user_data); + +/* + * ----------------------------------------------------------------- + * Type : CVQuadRhsFn + * ----------------------------------------------------------------- + * The fQ function which defines the right hand side of the + * quadrature equations yQ' = fQ(t,y) must have type CVQuadRhsFn. + * fQ takes as input the value of the independent variable t, + * the vector of states y and must store the result of fQ in + * yQdot. (Allocation of memory for yQdot is handled by CVODES). + * The user_data parameter is the same as the user_data parameter + * set by the user through the CVodeSetUserData routine and is + * passed to the fQ function every time it is called. + * + * If the quadrature RHS also depends on the sensitivity variables, + * i.e., yQ' = fQs(t,y,yS), then fQ must be of type CVodeQuadRhsFnS. + * + * A CVQuadRhsFn or CVodeQuadRhsFnS should return 0 if successful, + * a negative value if an unrecoverable error occured, and a positive + * value if a recoverable error (e.g. invalid y values) occured. + * If an unrecoverable occured, the integration is halted. + * If a recoverable error occured, then (in most cases) CVODES + * will try to correct and retry. + * ----------------------------------------------------------------- + */ + +typedef int (*CVQuadRhsFn)(realtype t, N_Vector y, + N_Vector yQdot, + void *user_data); + +/* + * ----------------------------------------------------------------- + * Type : CVSensRhsFn + * ----------------------------------------------------------------- + * The fS function which defines the right hand side of the + * sensitivity ODE systems s' = f_y * s + f_p must have type + * CVSensRhsFn. + * fS takes as input the number of sensitivities Ns, the + * independent variable value t, the states y and the + * corresponding value of f(t,y) in ydot, and the dependent + * sensitivity vectors yS. It stores the result of fS in ySdot. + * (Allocation of memory for ySdot is handled within CVODES) + * The user_data parameter is the same as the user_data parameter + * set by the user through the CVodeSetUserData routine and is + * passed to the fS function every time it is called. + * + * A CVSensRhsFn should return 0 if successful, a negative value if + * an unrecoverable error occured, and a positive value if a + * recoverable error (e.g. invalid y or yS values) occured. + * If an unrecoverable occured, the integration is halted. + * If a recoverable error occured, then (in most cases) CVODES + * will try to correct and retry. + * ----------------------------------------------------------------- + */ + +typedef int (*CVSensRhsFn)(int Ns, realtype t, + N_Vector y, N_Vector ydot, + N_Vector *yS, N_Vector *ySdot, + void *user_data, + N_Vector tmp1, N_Vector tmp2); + +/* + * ----------------------------------------------------------------- + * Type : CVSensRhs1Fn + * ----------------------------------------------------------------- + * The fS1 function which defines the right hand side of the i-th + * sensitivity ODE system s_i' = f_y * s_i + f_p must have type + * CVSensRhs1Fn. + * fS1 takes as input the number of sensitivities Ns, the current + * sensitivity iS, the independent variable value t, the states y + * and the corresponding value of f(t,y) in ydot, and the + * dependent sensitivity vector yS. It stores the result of fS in + * ySdot. + * (Allocation of memory for ySdot is handled within CVODES) + * The user_data parameter is the same as the user_data parameter + * set by the user through the CVodeSetUserData routine and is + * passed to the fS1 function every time it is called. + * + * A CVSensRhs1Fn should return 0 if successful, a negative value if + * an unrecoverable error occured, and a positive value if a + * recoverable error (e.g. invalid y or yS values) occured. + * If an unrecoverable occured, the integration is halted. + * If a recoverable error occured, then (in most cases) CVODES + * will try to correct and retry. + * ----------------------------------------------------------------- + */ + +typedef int (*CVSensRhs1Fn)(int Ns, realtype t, + N_Vector y, N_Vector ydot, + int iS, N_Vector yS, N_Vector ySdot, + void *user_data, + N_Vector tmp1, N_Vector tmp2); + +/* + * ----------------------------------------------------------------- + * Type : CVQuadSensRhsFn + * ----------------------------------------------------------------- + * The fQS function which defines the right hand side of the + * sensitivity ODE systems for quadratures, yQS' = fQ_y * yS + fQ_p + * must have type CVQuadSensRhsFn. + * + * fQS takes as input the number of sensitivities Ns (the same as + * that passed to CVodeQuadSensInit), the independent variable + * value t, the states y and the dependent sensitivity vectors yS, + * as well as the current value of the quadrature RHS yQdot. + * It stores the result of fQS in yQSdot. + * (Allocation of memory for yQSdot is handled within CVODES) + * + * A CVQuadSensRhsFn should return 0 if successful, a negative + * value if an unrecoverable error occured, and a positive value + * if a recoverable error (e.g. invalid y or yS values) occured. + * If an unrecoverable occured, the integration is halted. + * If a recoverable error occured, then (in most cases) CVODES + * will try to correct and retry. + * ----------------------------------------------------------------- + */ + +typedef int (*CVQuadSensRhsFn)(int Ns, realtype t, + N_Vector y, N_Vector *yS, + N_Vector yQdot, N_Vector *yQSdot, + void *user_data, + N_Vector tmp, N_Vector tmpQ); + +/* + * ----------------------------------------------------------------- + * CVRhsFnB and CVRhsFnBS + * The fB function which defines the right hand side of the + * ODE systems to be integrated backwards must have type CVRhsFnB. + * If the backward problem depends on forward sensitivities, its + * RHS function must have type CVRhsFnBS. + * ----------------------------------------------------------------- + * CVQuadRhsFnB and CVQuadRhsFnBS + * The fQB function which defines the quadratures to be integrated + * backwards must have type CVQuadRhsFnB. + * If the backward problem depends on forward sensitivities, its + * quadrature RHS function must have type CVQuadRhsFnBS. + * ----------------------------------------------------------------- + */ + +typedef int (*CVRhsFnB)(realtype t, N_Vector y, + N_Vector yB, N_Vector yBdot, + void *user_dataB); + +typedef int (*CVRhsFnBS)(realtype t, N_Vector y, N_Vector *yS, + N_Vector yB, N_Vector yBdot, + void *user_dataB); + + +typedef int (*CVQuadRhsFnB)(realtype t, N_Vector y, + N_Vector yB, N_Vector qBdot, + void *user_dataB); + +typedef int (*CVQuadRhsFnBS)(realtype t, N_Vector y, N_Vector *yS, + N_Vector yB, N_Vector qBdot, + void *user_dataB); + + +/* + * ================================================================= + * + * INITIALIZATION AND DEALLOCATION FUNCTIONS FOR FORWARD PROBLEMS + * + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Function : CVodeCreate + * ----------------------------------------------------------------- + * CVodeCreate creates an internal memory block for a problem to + * be solved by CVODES. + * + * lmm is the type of linear multistep method to be used. + * The legal values are CV_ADAMS and CV_BDF (see previous + * description). + * + * iter is the type of iteration used to solve the nonlinear + * system that arises during each internal time step. + * The legal values are CV_FUNCTIONAL and CV_NEWTON. + * + * If successful, CVodeCreate returns a pointer to initialized + * problem memory. This pointer should be passed to CVodeInit. + * If an initialization error occurs, CVodeCreate prints an error + * message to standard err and returns NULL. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void *CVodeCreate(int lmm, int iter); + +/* + * ----------------------------------------------------------------- + * Functions : CVodeInit and CVodeReInit + * ----------------------------------------------------------------- + * CVodeInit allocates and initializes memory for a problem to + * to be solved by CVODE. + * + * CVodeReInit re-initializes CVode for the solution of a problem, + * where a prior call to CVodeInit has been made with the same + * problem size N. CVodeReInit performs the same input checking + * and initializations that CVodeInit does. + * But it does no memory allocation, assuming that the existing + * internal memory is sufficient for the new problem. + * + * The use of CVodeReInit requires that the maximum method order, + * maxord, is no larger for the new problem than for the problem + * specified in the last call to CVodeInit. This condition is + * automatically fulfilled if the multistep method parameter lmm + * is unchanged (or changed from CV_ADAMS to CV_BDF) and the default + * value for maxord is specified. + * + * cvode_mem is pointer to CVODE memory returned by CVodeCreate. + * + * f is the name of the C function defining the right-hand + * side function in y' = f(t,y). + * + * t0 is the initial value of t. + * + * y0 is the initial condition vector y(t0). + * + * Return flag: + * CV_SUCCESS if successful + * CV_MEM_NULL if the cvode memory was NULL + * CV_MEM_FAIL if a memory allocation failed + * CV_NO_MALLOC if cvode_mem has not been allocated + * (i.e., CVodeInit has not been called). + * CV_ILL_INPUT if an argument has an illegal value. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeInit(void *cvode_mem, CVRhsFn f, realtype t0, N_Vector y0); +SUNDIALS_EXPORT int CVodeReInit(void *cvode_mem, realtype t0, N_Vector y0); + +/* + * ----------------------------------------------------------------- + * Functions : CVodeSStolerances + * CVodeSVtolerances + * CVodeWFtolerances + * ----------------------------------------------------------------- + * + * These functions specify the integration tolerances. One of them + * MUST be called before the first call to CVode. + * + * CVodeSStolerances specifies scalar relative and absolute tolerances. + * CVodeSVtolerances specifies scalar relative tolerance and a vector + * absolute tolerance (a potentially different absolute tolerance + * for each vector component). + * CVodeWFtolerances specifies a user-provides function (of type CVEwtFn) + * which will be called to set the error weight vector. + * + * The tolerances reltol and abstol define a vector of error weights, + * ewt, with components + * ewt[i] = 1/(reltol*abs(y[i]) + abstol) (in the SS case), or + * ewt[i] = 1/(reltol*abs(y[i]) + abstol[i]) (in the SV case). + * This vector is used in all error and convergence tests, which + * use a weighted RMS norm on all error-like vectors v: + * WRMSnorm(v) = sqrt( (1/N) sum(i=1..N) (v[i]*ewt[i])^2 ), + * where N is the problem dimension. + * + * The return value of these functions is equal to CV_SUCCESS = 0 if + * there were no errors; otherwise it is a negative int equal to: + * CV_MEM_NULL indicating cvode_mem was NULL (i.e., + * CVodeCreate has not been called). + * CV_NO_MALLOC indicating that cvode_mem has not been + * allocated (i.e., CVodeInit has not been + * called). + * CV_ILL_INPUT indicating an input argument was illegal + * (e.g. a negative tolerance) + * In case of an error return, an error message is also printed. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeSStolerances(void *cvode_mem, realtype reltol, realtype abstol); +SUNDIALS_EXPORT int CVodeSVtolerances(void *cvode_mem, realtype reltol, N_Vector abstol); +SUNDIALS_EXPORT int CVodeWFtolerances(void *cvode_mem, CVEwtFn efun); + +/* + * ----------------------------------------------------------------- + * Function : CVodeQuadInit and CVodeQuadReInit + * ----------------------------------------------------------------- + * CVodeQuadInit allocates and initializes memory related to + * quadrature integration. + * + * CVodeQuadReInit re-initializes CVODES's quadrature related + * memory for a problem, assuming it has already been allocated + * in prior calls to CVodeInit and CVodeQuadInit. + * The number of quadratures Nq is assumed to be unchanged + * since the previous call to CVodeQuadInit. + * + * cvode_mem is a pointer to CVODES memory returned by CVodeCreate + * + * fQ is the user-provided integrand routine. + * + * yQ0 is an N_Vector with initial values for quadratures + * (typically yQ0 has all zero components). + * + * Return values: + * CV_SUCCESS if successful + * CV_MEM_NULL if the cvode memory was NULL + * CV_MEM_FAIL if a memory allocation failed + * CV_NO_QUAD if quadratures were not initialized + * (i.e. CVodeQuadInit has not been called) + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeQuadInit(void *cvode_mem, CVQuadRhsFn fQ, N_Vector yQ0); +SUNDIALS_EXPORT int CVodeQuadReInit(void *cvode_mem, N_Vector yQ0); + +/* + * ----------------------------------------------------------------- + * Functions : CVodeQuadSStolerances + * CVodeQuadSVtolerances + * ----------------------------------------------------------------- + * + * These functions specify the integration tolerances for quadrature + * variables. One of them MUST be called before the first call to + * CVode IF error control on the quadrature variables is enabled + * (see CVodeSetQuadErrCon). + * + * CVodeSStolerances specifies scalar relative and absolute tolerances. + * CVodeSVtolerances specifies scalar relative tolerance and a vector + * absolute tolerance (a potentially different absolute tolerance + * for each vector component). + * + * Return values: + * CV_SUCCESS if successful + * CV_MEM_NULL if the cvode memory was NULL + * CV_NO_QUAD if quadratures were not initialized + * CV_ILL_INPUT if an input argument was illegal + * (e.g. a negative tolerance) + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeQuadSStolerances(void *cvode_mem, realtype reltolQ, realtype abstolQ); +SUNDIALS_EXPORT int CVodeQuadSVtolerances(void *cvode_mem, realtype reltolQ, N_Vector abstolQ); + +/* + * ----------------------------------------------------------------- + * Function : CVodeSensInit, CVSensInit1, and CVodeSensReInit + * ----------------------------------------------------------------- + * CVodeSensInit and CVSensInit1 allocate and initialize memory + * related to sensitivity computations. They only differ in the + * type of the sensitivity RHS function: CVodeSensInit specifies + * fS of type CVSensRhsFn (i.e. a function that evaluates all + * sensitivity RHS simultaneously), while CVodeSensInit1 specifies + * fS of type CVSensRhs1Fn (i.e. a function that evaluates one + * sensitivity RHS at a time). Recall that ism=CV_STAGGERED1 is + * compatible ONLY with a CVSensRhs1Fn. As such, this value for + * ism cannot be passed to CVodeSensInit. + * + * CVodeSensReInit re-initializes CVODES's sensitivity related + * memory for a problem, assuming it has already been allocated + * in prior calls to CVodeInit and CVodeSensInit. + * The number of sensitivities Ns is assumed to be unchanged + * since the previous call to CVodeSensInit. + * If any error occurs during initialization, it is reported to + * the file whose file pointer is errfp. + * CVodeSensReInit potentially does some minimal memory allocation + * (for the sensitivity absolute tolerance and for arrays of + * counters used by the CV_STAGGERED1 method). + + * cvode_mem is pointer to CVODES memory returned by CVodeCreate + * + * Ns is the number of sensitivities to be computed. + * + * ism is the type of corrector used in sensitivity + * analysis. The legal values are: CV_SIMULTANEOUS, + * CV_STAGGERED, and CV_STAGGERED1. + * + * fS is the sensitivity righ-hand side function + * (pass NULL to use the internal DQ approximation) + * + * yS0 is the array of initial condition vectors for + * sensitivity variables. + * + * Return values: + * CV_SUCCESS + * CV_MEM_NULL + * CV_ILL_INPUT + * CV_MEM_FAIL + * CV_NO_SENS + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeSensInit(void *cvode_mem, int Ns, int ism, + CVSensRhsFn fS, N_Vector *yS0); +SUNDIALS_EXPORT int CVodeSensInit1(void *cvode_mem, int Ns, int ism, + CVSensRhs1Fn fS1, N_Vector *yS0); +SUNDIALS_EXPORT int CVodeSensReInit(void *cvode_mem, int ism, N_Vector *yS0); + +/* + * ----------------------------------------------------------------- + * Functions : CVodeSensSStolerances + * CVodeSensSVtolerances + * CVodeSensEEtolerances + * ----------------------------------------------------------------- + * + * These functions specify the integration tolerances for sensitivity + * variables. One of them MUST be called before the first call to CVode. + * + * CVodeSensSStolerances specifies scalar relative and absolute tolerances. + * CVodeSensSVtolerances specifies scalar relative tolerance and a vector + * absolute tolerance for each sensitivity vector (a potentially different + * absolute tolerance for each vector component). + * CVodeSensEEtolerances specifies that tolerances for sensitivity variables + * should be estimated from those provided for the state variables. + * + * The return value is equal to CV_SUCCESS = 0 if there were no + * errors; otherwise it is a negative int equal to: + * CV_MEM_NULL indicating cvode_mem was NULL, or + * CV_NO_SENS indicating there was not a prior call to + * CVodeSensInit. + * CV_ILL_INPUT indicating an input argument was illegal + * (e.g. negative tolerances) + * In case of an error return, an error message is also printed. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeSensSStolerances(void *cvode_mem, realtype reltolS, realtype *abstolS); +SUNDIALS_EXPORT int CVodeSensSVtolerances(void *cvode_mem, realtype reltolS, N_Vector *abstolS); +SUNDIALS_EXPORT int CVodeSensEEtolerances(void *cvode_mem); + +/* + * ----------------------------------------------------------------- + * Function : CVodeQuadSensInit and CVodeQuadSensReInit + * ----------------------------------------------------------------- + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeQuadSensInit(void *cvode_mem, CVQuadSensRhsFn fQS, N_Vector *yQS0); +SUNDIALS_EXPORT int CVodeQuadSensReInit(void *cvode_mem, N_Vector *yQS0); + +/* + * ----------------------------------------------------------------- + * Functions : CVodeQuadSensSStolerances + * CVodeQuadSensSVtolerances + * CVodeQuadSensEEtolerances + * ----------------------------------------------------------------- + * + * These functions specify the integration tolerances for quadrature + * sensitivity variables. One of them MUST be called before the first + * call to CVode IF these variables are included in the error test. + * + * CVodeQuadSensSStolerances specifies scalar relative and absolute tolerances. + * CVodeQuadSensSVtolerances specifies scalar relative tolerance and a vector + * absolute tolerance for each quadrature sensitivity vector (a potentially + * different absolute tolerance for each vector component). + * CVodeQuadSensEEtolerances specifies that tolerances for sensitivity variables + * should be estimated from those provided for the quadrature variables. + * In this case, tolerances for the quadrature variables must be + * specified through a call to one of CVodeQuad**tolerances. + * + * The return value is equal to CV_SUCCESS = 0 if there were no + * errors; otherwise it is a negative int equal to: + * CV_MEM_NULL if cvode_mem was NULL, or + * CV_NO_QuadSENS if there was not a prior call to + * CVodeQuadSensInit. + * CV_ILL_INPUT if an input argument was illegal + * (e.g. negative tolerances) + * In case of an error return, an error message is also printed. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeQuadSensSStolerances(void *cvode_mem, realtype reltolQS, realtype *abstolQS); +SUNDIALS_EXPORT int CVodeQuadSensSVtolerances(void *cvode_mem, realtype reltolQS, N_Vector *abstolQS); +SUNDIALS_EXPORT int CVodeQuadSensEEtolerances(void *cvode_mem); + +/* + * ----------------------------------------------------------------- + * Function : CVodeRootInit + * ----------------------------------------------------------------- + * CVodeRootInit initializes a rootfinding problem to be solved + * during the integration of the ODE system. It must be called + * after CVodeCreate, and before CVode. The arguments are: + * + * cvode_mem = pointer to CVODE memory returned by CVodeCreate. + * + * nrtfn = number of functions g_i, an int >= 0. + * + * g = name of user-supplied function, of type CVRootFn, + * defining the functions g_i whose roots are sought. + * + * If a new problem is to be solved with a call to CVodeReInit, + * where the new problem has no root functions but the prior one + * did, then call CVodeRootInit with nrtfn = 0. + * + * The return value of CVodeRootInit is CV_SUCCESS = 0 if there were + * no errors; otherwise it is a negative int equal to: + * CV_MEM_NULL indicating cvode_mem was NULL, or + * CV_MEM_FAIL indicating a memory allocation failed. + * (including an attempt to increase maxord). + * CV_ILL_INPUT indicating nrtfn > 0 but g = NULL. + * In case of an error return, an error message is also printed. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeRootInit(void *cvode_mem, int nrtfn, CVRootFn g); + +/* + * ----------------------------------------------------------------- + * Function : CVodeFree + * ----------------------------------------------------------------- + * CVodeFree frees the problem memory cvode_mem allocated by + * CVodeInit. Its only argument is the pointer cvode_mem + * returned by CVodeCreate. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void CVodeFree(void **cvode_mem); + +/* + * ----------------------------------------------------------------- + * Function : CVodeQuadFree + * ----------------------------------------------------------------- + * CVodeQuadFree frees the problem memory in cvode_mem allocated + * for quadrature integration. Its only argument is the pointer + * cvode_mem returned by CVodeCreate. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void CVodeQuadFree(void *cvode_mem); + +/* + * ----------------------------------------------------------------- + * Function : CVodeSensFree + * ----------------------------------------------------------------- + * CVodeSensFree frees the problem memory in cvode_mem allocated + * for sensitivity analysis. Its only argument is the pointer + * cvode_mem returned by CVodeCreate. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void CVodeSensFree(void *cvode_mem); + +/* + * ----------------------------------------------------------------- + * Function : CVodeQuadSensFree + * ----------------------------------------------------------------- + * CVodeQuadSensFree frees the problem memory in cvode_mem allocated + * for quadrature sensitivity analysis. Its only argument is the + * pointer cvode_mem returned by CVodeCreate. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void CVodeQuadSensFree(void *cvode_mem); + +/* + * ================================================================= + * + * OPTIONAL INPUT FUNCTIONS FOR FORWARD PROBLEMS + * + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Integrator optional input specification functions + * ----------------------------------------------------------------- + * The following functions can be called to set optional inputs + * to values other than the defaults given below: + * + * Function | Optional input / [ default value ] + * ----------------------------------------------------------------- + * | + * CVodeSetErrHandlerFn | user-provided ErrHandler function. + * | [internal] + * | + * CVodeSetErrFile | the file pointer for an error file + * | where all CVODE warning and error + * | messages will be written if the default + * | internal error handling function is used. + * | This parameter can be stdout (standard + * | output), stderr (standard error), or a + * | file pointer (corresponding to a user + * | error file opened for writing) returned + * | by fopen. + * | If not called, then all messages will + * | be written to the standard error stream. + * | [stderr] + * | + * CVodeSetUserData | a pointer to user data that will be + * | passed to the user's f function every + * | time f is called. + * | [NULL] + * | + * CVodeSetMaxOrd | maximum lmm order to be used by the + * | solver. + * | [12 for Adams , 5 for BDF] + * | + * CVodeSetMaxNumSteps | maximum number of internal steps to be + * | taken by the solver in its attempt to + * | reach tout. + * | [500] + * | + * CVodeSetMaxHnilWarns | maximum number of warning messages + * | issued by the solver that t+h==t on the + * | next internal step. A value of -1 means + * | no such messages are issued. + * | [10] + * | + * CVodeSetStabLimDet | flag to turn on/off stability limit + * | detection (TRUE = on, FALSE = off). + * | When BDF is used and order is 3 or + * | greater, CVsldet is called to detect + * | stability limit. If limit is detected, + * | the order is reduced. + * | [FALSE] + * | + * CVodeSetInitStep | initial step size. + * | [estimated by CVODES] + * | + * CVodeSetMinStep | minimum absolute value of step size + * | allowed. + * | [0.0] + * | + * CVodeSetMaxStep | maximum absolute value of step size + * | allowed. + * | [infinity] + * | + * CVodeSetStopTime | the independent variable value past + * | which the solution is not to proceed. + * | [infinity] + * | + * CVodeSetMaxErrTestFails | Maximum number of error test failures + * | in attempting one step. + * | [7] + * | + * CVodeSetMaxNonlinIters | Maximum number of nonlinear solver + * | iterations at one solution. + * | [3] + * | + * CVodeSetMaxConvFails | Maximum number of allowable conv. + * | failures in attempting one step. + * | [10] + * | + * CVodeSetNonlinConvCoef | Coeficient in the nonlinear conv. + * | test. + * | [0.1] + * | + * ----------------------------------------------------------------- + * | + * CVodeSetIterType | Changes the current nonlinear iteration + * | type. + * | [set by CVodecreate] + * | + * ----------------------------------------------------------------- + * | + * CVodeSetRootDirection | Specifies the direction of zero + * | crossings to be monitored + * | [both directions] + * | + * CVodeSetNoInactiveRootWarn | disable warning about possible + * | g==0 at beginning of integration + * | + * ----------------------------------------------------------------- + * Return flag: + * CV_SUCCESS if successful + * CV_MEM_NULL if the cvode memory is NULL + * CV_ILL_INPUT if an argument has an illegal value + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeSetErrHandlerFn(void *cvode_mem, CVErrHandlerFn ehfun, void *eh_data); +SUNDIALS_EXPORT int CVodeSetErrFile(void *cvode_mem, FILE *errfp); +SUNDIALS_EXPORT int CVodeSetUserData(void *cvode_mem, void *user_data); +SUNDIALS_EXPORT int CVodeSetMaxOrd(void *cvode_mem, int maxord); +SUNDIALS_EXPORT int CVodeSetMaxNumSteps(void *cvode_mem, long int mxsteps); +SUNDIALS_EXPORT int CVodeSetMaxHnilWarns(void *cvode_mem, int mxhnil); +SUNDIALS_EXPORT int CVodeSetStabLimDet(void *cvode_mem, booleantype stldet); +SUNDIALS_EXPORT int CVodeSetInitStep(void *cvode_mem, realtype hin); +SUNDIALS_EXPORT int CVodeSetMinStep(void *cvode_mem, realtype hmin); +SUNDIALS_EXPORT int CVodeSetMaxStep(void *cvode_mem, realtype hmax); +SUNDIALS_EXPORT int CVodeSetStopTime(void *cvode_mem, realtype tstop); +SUNDIALS_EXPORT int CVodeSetMaxErrTestFails(void *cvode_mem, int maxnef); +SUNDIALS_EXPORT int CVodeSetMaxNonlinIters(void *cvode_mem, int maxcor); +SUNDIALS_EXPORT int CVodeSetMaxConvFails(void *cvode_mem, int maxncf); +SUNDIALS_EXPORT int CVodeSetNonlinConvCoef(void *cvode_mem, realtype nlscoef); + +SUNDIALS_EXPORT int CVodeSetIterType(void *cvode_mem, int iter); + +SUNDIALS_EXPORT int CVodeSetRootDirection(void *cvode_mem, int *rootdir); +SUNDIALS_EXPORT int CVodeSetNoInactiveRootWarn(void *cvode_mem); + + +/* + * ----------------------------------------------------------------- + * Quadrature optional input specification functions + * ----------------------------------------------------------------- + * The following functions can be called to set optional inputs + * to values other than the defaults given below: + * + * Function | Optional input / [ default value ] + * -------------------------------------------------------------- + * | + * CVodeSetQuadErrCon | are quadrature variables considered in + * | the error control? + * | If yes, tolerances for quadrature are + * | required (see CVodeQuad**tolerances) + * | [errconQ = FALSE] + * | + * ----------------------------------------------------------------- + * If successful, these functions return CV_SUCCESS. If an argument + * has an illegal value, they return one of the error flags + * defined for the CVodeSet* routines. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeSetQuadErrCon(void *cvode_mem, booleantype errconQ); + +/* + * ----------------------------------------------------------------- + * Forward sensitivity optional input specification functions + * ----------------------------------------------------------------- + * The following functions can be called to set optional inputs + * to other values than the defaults given below: + * + * Function | Optional input / [ default value ] + * ----------------------------------------------------------------- + * | + * CVodeSetSensDQMethod | controls the selection of finite + * | difference schemes used in evaluating + * | the sensitivity right hand sides: + * | (centered vs. forward and + * | simultaneous vs. separate) + * | [DQtype=CV_CENTERED] + * | [DQrhomax=0.0] + * | + * CVodeSetSensParams | parameter information: + * | p: pointer to problem parameters + * | plist: list of parameters with respect + * | to which sensitivities are to be + * | computed. + * | pbar: order of magnitude info. + * | Typically, if p[plist[i]] is nonzero, + * | pbar[i]=p[plist[i]]. + * | [p=NULL] + * | [plist=NULL] + * | [pbar=NULL] + * | + * CVodeSetSensErrCon | are sensitivity variables considered in + * | the error control? + * | [FALSE] + * | + * CVodeSetSensMaxNonlinIters | Maximum number of nonlinear solver + * | iterations at one solution. + * | [3] + * | + * ----------------------------------------------------------------- + * The return values are the same as for CVodeSet* + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeSetSensDQMethod(void *cvode_mem, int DQtype, realtype DQrhomax); +SUNDIALS_EXPORT int CVodeSetSensErrCon(void *cvode_mem, booleantype errconS); +SUNDIALS_EXPORT int CVodeSetSensMaxNonlinIters(void *cvode_mem, int maxcorS); +SUNDIALS_EXPORT int CVodeSetSensParams(void *cvode_mem, realtype *p, realtype *pbar, int *plist); + +/* + * ----------------------------------------------------------------- + * Quadrature sensitivity optional input specification functions + * ----------------------------------------------------------------- + * The following functions can be called to set optional inputs + * to values other than the defaults given below: + * + * Function | Optional input / [ default value ] + * -------------------------------------------------------------- + * | + * CVodeSetQuadSensErrCon | are quadrature sensitivity variables + * | considered in the error control? + * | If yes, tolerances for quadrature + * | sensitivity variables are required. + * | [errconQS = FALSE] + * | + * ----------------------------------------------------------------- + * If successful, these functions return CV_SUCCESS. If an argument + * has an illegal value, they return one of the error flags + * defined for the CVodeSet* routines. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeSetQuadSensErrCon(void *cvode_mem, booleantype errconQS); + +/* + * ----------------------------------------------------------------- + * Function : CVodeSensToggleOff + * ----------------------------------------------------------------- + * CVodeSensToggleOff deactivates sensitivity calculations. + * It does NOT deallocate sensitivity-related memory so that + * sensitivity computations can be later toggled ON (through + * CVodeSensReInit). + * + * The return value is equal to CV_SUCCESS = 0 if there were no + * errors or CV_MEM_NULL if cvode_mem was NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeSensToggleOff(void *cvode_mem); + + +/* + * ================================================================= + * + * MAIN SOLVER FUNCTION FOR FORWARD PROBLEMS + * + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Function : CVode + * ----------------------------------------------------------------- + * CVode integrates the ODE over an interval in t. + * If itask is CV_NORMAL, then the solver integrates from its + * current internal t value to a point at or beyond tout, then + * interpolates to t = tout and returns y(tout) in the user- + * allocated vector yout. If itask is CV_ONE_STEP, then the solver + * takes one internal time step and returns in yout the value of + * y at the new internal time. In this case, tout is used only + * during the first call to CVode to determine the direction of + * integration and the rough scale of the problem. If tstop is + * enabled (through a call to CVodeSetStopTime), then CVode returns + * the solution at tstop. Once the integrator returns at a tstop + * time, any future testing for tstop is disabled (and can be + * reenabled only though a new call to CVodeSetStopTime). + * The time reached by the solver is placed in (*tret). The + * user is responsible for allocating the memory for this value. + * + * cvode_mem is the pointer to CVODES memory returned by + * CVodeCreate. + * + * tout is the next time at which a computed solution is desired. + * + * yout is the computed solution vector. In CV_NORMAL mode with no + * errors and no roots found, yout=y(tout). + * + * tret is a pointer to a real location. CVode sets (*tret) to + * the time reached by the solver and returns yout=y(*tret). + * + * itask is CV_NORMAL or CV_ONE_STEP. These two modes are described above. + * + * Here is a brief description of each return value: + * + * CV_SUCCESS: CVode succeeded and no roots were found. + * + * CV_ROOT_RETURN: CVode succeeded, and found one or more roots. + * If nrtfn > 1, call CVodeGetRootInfo to see + * which g_i were found to have a root at (*tret). + * + * CV_TSTOP_RETURN: CVode succeded and returned at tstop. + * + * CV_MEM_NULL: The cvode_mem argument was NULL. + * + * CV_NO_MALLOC: cvode_mem was not allocated. + * + * CV_ILL_INPUT: One of the inputs to CVode is illegal. This + * includes the situation when a component of the + * error weight vectors becomes < 0 during + * internal time-stepping. The ILL_INPUT flag + * will also be returned if the linear solver + * routine CV--- (called by the user after + * calling CVodeCreate) failed to set one of the + * linear solver-related fields in cvode_mem or + * if the linear solver's init routine failed. In + * any case, the user should see the printed + * error message for more details. + * + * CV_TOO_MUCH_WORK: The solver took mxstep internal steps but + * could not reach tout. The default value for + * mxstep is MXSTEP_DEFAULT = 500. + * + * CV_TOO_MUCH_ACC: The solver could not satisfy the accuracy + * demanded by the user for some internal step. + * + * CV_ERR_FAILURE: Error test failures occurred too many times + * (= MXNEF = 7) during one internal time step or + * occurred with |h| = hmin. + * + * CV_CONV_FAILURE: Convergence test failures occurred too many + * times (= MXNCF = 10) during one internal time + * step or occurred with |h| = hmin. + * + * CV_LINIT_FAIL: The linear solver's initialization function + * failed. + * + * CV_LSETUP_FAIL: The linear solver's setup routine failed in an + * unrecoverable manner. + * + * CV_LSOLVE_FAIL: The linear solver's solve routine failed in an + * unrecoverable manner. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVode(void *cvode_mem, realtype tout, N_Vector yout, + realtype *tret, int itask); + + +/* + * ================================================================= + * + * EXTRACTION AND DENSE OUTPUT FUNCTIONS FOR FORWARD PROBLEMS + * + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Function : CVodeGetDky + * ----------------------------------------------------------------- + * CVodeGetDky computes the kth derivative of the y function at + * time t, where tn-hu <= t <= tn, tn denotes the current + * internal time reached, and hu is the last internal step size + * successfully used by the solver. The user may request + * k=0, 1, ..., qu, where qu is the current order. The + * derivative vector is returned in dky. This vector must be + * allocated by the caller. It is only legal to call this + * function after a successful return from CVode. + * + * cvode_mem is the pointer to CVODES memory returned by + * CVodeCreate. + * + * t is the time at which the kth derivative of y is evaluated. + * The legal range for t is [tn-hu,tn] as described above. + * + * k is the order of the derivative of y to be computed. The + * legal range for k is [0,qu] as described above. + * + * dky is the output derivative vector [(D_k)y](t). + * + * The return values for CVodeGetDky are defined below. + * Here is a brief description of each return value: + * + * CV_SUCCESS: CVodeGetDky succeeded. + * + * CV_BAD_K : k is not in the range 0, 1, ..., qu. + * + * CV_BAD_T : t is not in the interval [tn-hu,tn]. + * + * CV_BAD_DKY : The dky argument was NULL. + * + * CV_MEM_NULL : The cvode_mem argument was NULL. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetDky(void *cvode_mem, realtype t, int k, N_Vector dky); + + +/* + * ----------------------------------------------------------------- + * Quadrature integration solution extraction routines + * ----------------------------------------------------------------- + * The following functions can be called to obtain the quadrature + * variables after a successful integration step. + * If quadratures were not computed, they return CV_NO_QUAD. + * + * CVodeGetQuad returns the quadrature variables at the same time + * as that at which CVode returned the solution. + * + * CVodeGetQuadDky returns the quadrature variables (or their + * derivatives up to the current method order) at any time within + * the last integration step (dense output). See CVodeGetQuad for + * more information. + * + * The output vectors yQout and dky must be allocated by the user. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetQuad(void *cvode_mem, realtype *tret, N_Vector yQout); + +SUNDIALS_EXPORT int CVodeGetQuadDky(void *cvode_mem, realtype t, int k, N_Vector dky); + +/* + * ----------------------------------------------------------------- + * Forward sensitivity solution extraction routines + * ----------------------------------------------------------------- + * The following functions can be called to obtain the sensitivity + * variables after a successful integration step. + * + * CVodeGetSens and CVodeGetSens1 return all the sensitivity vectors + * or only one of them, respectively, at the same time as that at + * which CVode returned the solution. + * The array of output vectors or output vector ySout must be + * allocated by the user. + * + * CVodeGetSensDky1 computes the kth derivative of the is-th + * sensitivity (is=1, 2, ..., Ns) of the y function at time t, + * where tn-hu <= t <= tn, tn denotes the current internal time + * reached, and hu is the last internal step size successfully + * used by the solver. The user may request k=0, 1, ..., qu, + * where qu is the current order. + * The is-th sensitivity derivative vector is returned in dky. + * This vector must be allocated by the caller. It is only legal + * to call this function after a successful return from CVode + * with sensitivty computations enabled. + * Arguments have the same meaning as in CVodeDky. + * + * CVodeGetSensDky computes the k-th derivative of all + * sensitivities of the y function at time t. It repeatedly calls + * CVodeGetSensDky. The argument dkyA must be a pointer to + * N_Vector and must be allocated by the user to hold at least Ns + * vectors. + * + * Return values are similar to those of CVodeDky. Additionally, + * CVodeSensDky can return CV_NO_SENS if sensitivities were + * not computed and CV_BAD_IS if is < 0 or is >= Ns. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetSens(void *cvode_mem, realtype *tret, N_Vector *ySout); +SUNDIALS_EXPORT int CVodeGetSens1(void *cvode_mem, realtype *tret, int is, N_Vector ySout); + +SUNDIALS_EXPORT int CVodeGetSensDky(void *cvode_mem, realtype t, int k, N_Vector *dkyA); +SUNDIALS_EXPORT int CVodeGetSensDky1(void *cvode_mem, realtype t, int k, int is, N_Vector dky); + +/* + * ----------------------------------------------------------------- + * Quadrature sensitivity solution extraction routines + * ----------------------------------------------------------------- + * The following functions can be called to obtain the quadrature + * sensitivity variables after a successful integration step. + * + * CVodeGetQuadSens and CVodeGetQuadSens1 return all the quadrature + * sensitivity vectors or only one of them, respectively, at the + * same time as that at which CVode returned the solution. + * The array of output vectors or output vector yQSout must be + * allocated by the user. + * + * CVodeGetQuadSensDky1 computes the kth derivative of the is-th + * quadrature sensitivity (is=1, 2, ..., Ns) at time t, where + * tn-hu <= t <= tn, tn denotes the current internal time + * reached, and hu is the last internal step size successfully + * used by the solver. The user may request k=0, 1, ..., qu, + * where qu is the current order. + * The is-th sensitivity derivative vector is returned in dkyQS. + * This vector must be allocated by the caller. It is only legal + * to call this function after a successful return from CVode + * with quadrature sensitivty computations enabled. + * Arguments have the same meaning as in CVodeDky. + * + * CVodeGetQuadSensDky computes the k-th derivative of all + * quadrature sensitivities at time t. It repeatedly calls + * CVodeGetSensDky. The argument dkyQS_all must be a pointer to + * N_Vector and must be allocated by the user to hold at least Ns + * vectors. + * + * Return values are similar to those of CVodeDky. Additionally, + * CVodeQuadSensDky can return CV_NO_QUADSENS if quadrature + * sensitivities were not computed and CV_BAD_IS if is < 0 or is >= Ns. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetQuadSens(void *cvode_mem, realtype *tret, N_Vector *yQSout); +SUNDIALS_EXPORT int CVodeGetQuadSens1(void *cvode_mem, realtype *tret, int is, N_Vector yQSout); + +SUNDIALS_EXPORT int CVodeGetQuadSensDky(void *cvode_mem, realtype t, int k, N_Vector *dkyQS_all); +SUNDIALS_EXPORT int CVodeGetQuadSensDky1(void *cvode_mem, realtype t, int k, int is, N_Vector dkyQS); + +/* + * ================================================================= + * + * OPTIONAL OUTPUT FUNCTIONS FOR FORWARD PROBLEMS + * + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Integrator optional output extraction functions + * ----------------------------------------------------------------- + * The following functions can be called to get optional outputs + * and statistics related to the main integrator. + * ----------------------------------------------------------------- + * CVodeGetWorkSpace returns the CVODES real and integer workspaces + * CVodeGetNumSteps returns the cumulative number of internal + * steps taken by the solver + * CVodeGetNumRhsEvals returns the number of calls to the user's + * f function + * CVodeGetNumLinSolvSetups returns the number of calls made to + * the linear solver's setup routine + * CVodeGetNumErrTestFails returns the number of local error test + * failures that have occured + * CVodeGetLastOrder returns the order used during the last + * internal step + * CVodeGetCurrentOrder returns the order to be used on the next + * internal step + * CVodeGetNumStabLimOrderReds returns the number of order + * reductions due to stability limit detection + * CVodeGetActualInitStep returns the actual initial step size + * used by CVODES + * CVodeGetLastStep returns the step size for the last internal + * step + * CVodeGetCurrentStep returns the step size to be attempted on + * the next internal step + * CVodeGetCurrentTime returns the current internal time reached + * by the solver + * CVodeGetTolScaleFactor returns a suggested factor by which the + * user's tolerances should be scaled when too + * much accuracy has been requested for some + * internal step + * CVodeGetErrWeights returns the current error weight vector. + * The user must allocate space for eweight. + * CVodeGetEstLocalErrors returns the vector of estimated local + * errors. The user must allocate space for ele. + * CVodeGetNumGEvals returns the number of calls to the user's + * g function (for rootfinding) + * CVodeGetRootInfo returns the indices for which g_i was found to + * have a root. The user must allocate space for + * rootsfound. For i = 0 ... nrtfn-1, + * rootsfound[i] = 1 if g_i has a root, and = 0 if not. + * + * CVodeGet* return values: + * CV_SUCCESS if succesful + * CV_MEM_NULL if the cvode memory was NULL + * CV_NO_SLDET if stability limit was not turned on + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetWorkSpace(void *cvode_mem, long int *lenrw, long int *leniw); +SUNDIALS_EXPORT int CVodeGetNumSteps(void *cvode_mem, long int *nsteps); +SUNDIALS_EXPORT int CVodeGetNumRhsEvals(void *cvode_mem, long int *nfevals); +SUNDIALS_EXPORT int CVodeGetNumLinSolvSetups(void *cvode_mem, long int *nlinsetups); +SUNDIALS_EXPORT int CVodeGetNumErrTestFails(void *cvode_mem, long int *netfails); +SUNDIALS_EXPORT int CVodeGetLastOrder(void *cvode_mem, int *qlast); +SUNDIALS_EXPORT int CVodeGetCurrentOrder(void *cvode_mem, int *qcur); +SUNDIALS_EXPORT int CVodeGetNumStabLimOrderReds(void *cvode_mem, long int *nslred); +SUNDIALS_EXPORT int CVodeGetActualInitStep(void *cvode_mem, realtype *hinused); +SUNDIALS_EXPORT int CVodeGetLastStep(void *cvode_mem, realtype *hlast); +SUNDIALS_EXPORT int CVodeGetCurrentStep(void *cvode_mem, realtype *hcur); +SUNDIALS_EXPORT int CVodeGetCurrentTime(void *cvode_mem, realtype *tcur); +SUNDIALS_EXPORT int CVodeGetTolScaleFactor(void *cvode_mem, realtype *tolsfac); +SUNDIALS_EXPORT int CVodeGetErrWeights(void *cvode_mem, N_Vector eweight); +SUNDIALS_EXPORT int CVodeGetEstLocalErrors(void *cvode_mem, N_Vector ele); +SUNDIALS_EXPORT int CVodeGetNumGEvals(void *cvode_mem, long int *ngevals); +SUNDIALS_EXPORT int CVodeGetRootInfo(void *cvode_mem, int *rootsfound); + +/* + * ----------------------------------------------------------------- + * As a convenience, the following functions provides the + * optional outputs in one group. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetIntegratorStats(void *cvode_mem, long int *nsteps, + long int *nfevals, long int *nlinsetups, + long int *netfails, int *qlast, + int *qcur, realtype *hinused, realtype *hlast, + realtype *hcur, realtype *tcur); + +/* + * ----------------------------------------------------------------- + * Nonlinear solver optional output extraction functions + * ----------------------------------------------------------------- + * The following functions can be called to get optional outputs + * and statistics related to the nonlinear solver. + * ----------------------------------------------------------------- + * CVodeGetNumNonlinSolvIters returns the number of nonlinear + * solver iterations performed. + * CVodeGetNumNonlinSolvConvFails returns the number of nonlinear + * convergence failures. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetNumNonlinSolvIters(void *cvode_mem, long int *nniters); +SUNDIALS_EXPORT int CVodeGetNumNonlinSolvConvFails(void *cvode_mem, long int *nncfails); + +/* + * ----------------------------------------------------------------- + * As a convenience, the following function provides the + * nonlinear solver optional outputs in a group. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetNonlinSolvStats(void *cvode_mem, long int *nniters, + long int *nncfails); + + +/* + * ----------------------------------------------------------------- + * The following function returns the name of the constant + * associated with a CVODES return flag + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT char *CVodeGetReturnFlagName(int flag); + +/* + * ----------------------------------------------------------------- + * Quadrature integration optional output extraction routines + * ----------------------------------------------------------------- + * The following functions can be called to get optional outputs + * and statistics related to the integration of quadratures. + * ----------------------------------------------------------------- + * CVodeGetQuadNumRhsEvals returns the number of calls to the + * user function fQ defining the right hand + * side of the quadrature variables. + * CVodeGetQuadNumErrTestFails returns the number of local error + * test failures for quadrature variables. + * CVodeGetQuadErrWeights returns the vector of error weights for + * the quadrature variables. The user must + * allocate space for ewtQ. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetQuadNumRhsEvals(void *cvode_mem, long int *nfQevals); +SUNDIALS_EXPORT int CVodeGetQuadNumErrTestFails(void *cvode_mem, long int *nQetfails); +SUNDIALS_EXPORT int CVodeGetQuadErrWeights(void *cvode_mem, N_Vector eQweight); + +/* + * ----------------------------------------------------------------- + * As a convenience, the following function provides the above + * optional outputs in a group. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetQuadStats(void *cvode_mem, long int *nfQevals, + long int *nQetfails); + +/* + * ----------------------------------------------------------------- + * Forward sensitivity optional output extraction routines + * ----------------------------------------------------------------- + * The following functions can be called to get optional outputs + * and statistics related to the integration of sensitivities. + * ----------------------------------------------------------------- + * CVodeGetSensNumRhsEvals returns the number of calls to the + * sensitivity right hand side routine. + * CVodeGetNumRhsEvalsSens returns the number of calls to the + * user f routine due to finite difference evaluations of the + * sensitivity equations. + * CVodeGetSensNumErrTestFails returns the number of local error + * test failures for sensitivity variables. + * CVodeGetSensNumLinSolvSetups returns the number of calls made + * to the linear solver's setup routine due to sensitivity computations. + * CVodeGetSensErrWeights returns the sensitivity error weight + * vectors. The user need not allocate space for ewtS. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetSensNumRhsEvals(void *cvode_mem, long int *nfSevals); +SUNDIALS_EXPORT int CVodeGetNumRhsEvalsSens(void *cvode_mem, long int *nfevalsS); +SUNDIALS_EXPORT int CVodeGetSensNumErrTestFails(void *cvode_mem, long int *nSetfails); +SUNDIALS_EXPORT int CVodeGetSensNumLinSolvSetups(void *cvode_mem, long int *nlinsetupsS); +SUNDIALS_EXPORT int CVodeGetSensErrWeights(void *cvode_mem, N_Vector *eSweight); + +/* + * ----------------------------------------------------------------- + * As a convenience, the following function provides the + * optional outputs in a group. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetSensStats(void *cvode_mem, long int *nfSevals, long int *nfevalsS, + long int *nSetfails, long int *nlinsetupsS); + +/* + * ----------------------------------------------------------------- + * Sensitivity nonlinear solver optional output extraction + * ----------------------------------------------------------------- + * The following functions can be called to get optional outputs + * and statistics related to the sensitivity nonlinear solver. + * ----------------------------------------------------------------- + * CVodeGetSensNumNonlinSolvIters returns the total number of + * nonlinear iterations for sensitivity variables. + * CVodeGetSensNumNonlinSolvConvFails returns the total number + * of nonlinear convergence failures for sensitivity variables + * CVodeGetStgrSensNumNonlinSolvIters returns a vector of Ns + * nonlinear iteration counters for sensitivity variables in + * the CV_STAGGERED1 method. + * CVodeGetStgrSensNumNonlinSolvConvFails returns a vector of Ns + * nonlinear solver convergence failure counters for sensitivity + * variables in the CV_STAGGERED1 method. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetSensNumNonlinSolvIters(void *cvode_mem, long int *nSniters); +SUNDIALS_EXPORT int CVodeGetSensNumNonlinSolvConvFails(void *cvode_mem, long int *nSncfails); +SUNDIALS_EXPORT int CVodeGetStgrSensNumNonlinSolvIters(void *cvode_mem, long int *nSTGR1niters); +SUNDIALS_EXPORT int CVodeGetStgrSensNumNonlinSolvConvFails(void *cvode_mem, + long int *nSTGR1ncfails); + +/* + * ----------------------------------------------------------------- + * As a convenience, the following function provides the + * optional outputs in groups. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetSensNonlinSolvStats(void *cvode_mem, long int *nSniters, + long int *nSncfails); + + +/* + * ----------------------------------------------------------------- + * Quadrature sensitivity optional output extraction routines + * ----------------------------------------------------------------- + * The following functions can be called to get optional outputs and + * statistics related to the integration of quadrature sensitivitiess. + * ----------------------------------------------------------------- + * CVodeGetQuadSensNumRhsEvals returns the number of calls to the + * user function fQS defining the right hand side of the + * quadrature sensitivity equations. + * CVodeGetQuadSensNumErrTestFails returns the number of local error + * test failures for quadrature sensitivity variables. + * CVodeGetQuadSensErrWeights returns the vector of error weights + * for the quadrature sensitivity variables. The user must + * allocate space for ewtQS. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetQuadSensNumRhsEvals(void *cvode_mem, long int *nfQSevals); +SUNDIALS_EXPORT int CVodeGetQuadSensNumErrTestFails(void *cvode_mem, long int *nQSetfails); +SUNDIALS_EXPORT int CVodeGetQuadSensErrWeights(void *cvode_mem, N_Vector *eQSweight); + +/* + * ----------------------------------------------------------------- + * As a convenience, the following function provides the above + * optional outputs in a group. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetQuadSensStats(void *cvode_mem, + long int *nfQSevals, + long int *nQSetfails); + + +/* + * ================================================================= + * + * INITIALIZATION AND DEALLOCATION FUNCTIONS FOR BACKWARD PROBLEMS + * + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * CVodeAdjInit + * ----------------------------------------------------------------- + * CVodeAdjInit specifies some parameters for ASA, initializes ASA + * and allocates space for the adjoint memory structure. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeAdjInit(void *cvode_mem, long int steps, int interp); + +/* + * ----------------------------------------------------------------- + * CVodeAdjReInit + * ----------------------------------------------------------------- + * CVodeAdjReInit reinitializes the CVODES memory structure for ASA, + * assuming that the number of steps between check points and the + * type of interpolation remained unchanged. The list of check points + * (and associated memory) is deleted. The list of backward problems + * is kept (however, new backward problems can be added to this list + * by calling CVodeCreateB). The CVODES memory for the forward and + * backward problems can be reinitialized separately by calling + * CVodeReInit and CVodeReInitB, respectively. + * NOTE: if a entirely new list of backward problems is desired, + * then simply free the adjoint memory (by calling CVodeAdjFree) + * and reinitialize ASA with CVodeAdjInit. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeAdjReInit(void *cvode_mem); + +/* + * ----------------------------------------------------------------- + * CVodeAdjFree + * ----------------------------------------------------------------- + * CVodeAdjFree frees the memory allocated by CVodeAdjInit. + * It is typically called by CVodeFree. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void CVodeAdjFree(void *cvode_mem); + + +/* + * ----------------------------------------------------------------- + * Interfaces to CVODES functions for setting-up backward problems. + * ----------------------------------------------------------------- + * CVodeCreateB, + * + * CVodeInitB, CVodeInitBS, CVodeReInitB + * + * CVodeQuadInitB, CVodeQuadInitBS, CVodeQuadReInitB + * + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeCreateB(void *cvode_mem, int lmmB, int iterB, int *which); + +SUNDIALS_EXPORT int CVodeInitB(void *cvode_mem, int which, + CVRhsFnB fB, + realtype tB0, N_Vector yB0); +SUNDIALS_EXPORT int CVodeInitBS(void *cvode_mem, int which, + CVRhsFnBS fBs, + realtype tB0, N_Vector yB0); +SUNDIALS_EXPORT int CVodeReInitB(void *cvode_mem, int which, + realtype tB0, N_Vector yB0); + +SUNDIALS_EXPORT int CVodeSStolerancesB(void *cvode_mem, int which, + realtype reltolB, realtype abstolB); +SUNDIALS_EXPORT int CVodeSVtolerancesB(void *cvode_mem, int which, + realtype reltolB, N_Vector abstolB); + +SUNDIALS_EXPORT int CVodeQuadInitB(void *cvode_mem, int which, + CVQuadRhsFnB fQB, N_Vector yQB0); +SUNDIALS_EXPORT int CVodeQuadInitBS(void *cvode_mem, int which, + CVQuadRhsFnBS fQBs, N_Vector yQB0); +SUNDIALS_EXPORT int CVodeQuadReInitB(void *cvode_mem, int which, N_Vector yQB0); + +SUNDIALS_EXPORT int CVodeQuadSStolerancesB(void *cvode_mem, int which, + realtype reltolQB, realtype abstolQB); +SUNDIALS_EXPORT int CVodeQuadSVtolerancesB(void *cvode_mem, int which, + realtype reltolQB, N_Vector abstolQB); + +/* + * ================================================================= + * + * MAIN SOLVER FUNCTIONS FOR FORWARD PROBLEMS + * + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * CVodeF + * ----------------------------------------------------------------- + * CVodeF integrates towards tout and returns solution into yout. + * In the same time, it stores check point data every 'steps'. + * + * CVodeF can be called repeatedly by the user. + * + * ncheckPtr points to the number of check points stored so far. + * + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeF(void *cvode_mem, realtype tout, N_Vector yout, + realtype *tret, int itask, int *ncheckPtr); + + +/* + * ----------------------------------------------------------------- + * CVodeB + * ----------------------------------------------------------------- + * CVodeB performs the integration of all backward problems specified + * through calls to CVodeCreateB through a sequence of forward-backward + * runs in between consecutive check points. CVodeB can be called + * either in CV_NORMAL or CV_ONE_STEP mode. After a successful return + * from CVodeB, the solution and quadrature variables at the current + * return time for any given backward problem can be obtained by + * calling CVodeGetB and CVodeGetQuadB, respectively. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeB(void *cvode_mem, realtype tBout, int itaskB); + +/* + * ================================================================= + * + * OPTIONAL INPUT FUNCTIONS FOR BACKWARD PROBLEMS + * + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * CVodeSetAdjNoSensi + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeSetAdjNoSensi(void *cvode_mem); + +/* + * ----------------------------------------------------------------- + * Optional input functions for backward problems + * ----------------------------------------------------------------- + * These functions are just wrappers around the corresponding + * functions in cvodes.h, with some particularizations for the + * backward integration. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeSetIterTypeB(void *cvode_mem, int which, int iterB); +SUNDIALS_EXPORT int CVodeSetUserDataB(void *cvode_mem, int which, void *user_dataB); +SUNDIALS_EXPORT int CVodeSetMaxOrdB(void *cvode_mem, int which, int maxordB); +SUNDIALS_EXPORT int CVodeSetMaxNumStepsB(void *cvode_mem, int which, long int mxstepsB); +SUNDIALS_EXPORT int CVodeSetStabLimDetB(void *cvode_mem, int which, booleantype stldetB); +SUNDIALS_EXPORT int CVodeSetInitStepB(void *cvode_mem, int which, realtype hinB); +SUNDIALS_EXPORT int CVodeSetMinStepB(void *cvode_mem, int which, realtype hminB); +SUNDIALS_EXPORT int CVodeSetMaxStepB(void *cvode_mem, int which, realtype hmaxB); + +SUNDIALS_EXPORT int CVodeSetQuadErrConB(void *cvode_mem, int which, booleantype errconQB); + +/* + * ================================================================= + * + * EXTRACTION AND DENSE OUTPUT FUNCTIONS FOR BACKWARD PROBLEMS + * + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * CVodeGetB and CVodeGetQuadB + * ----------------------------------------------------------------- + * Extraction functions for the solution and quadratures for a given + * backward problem. They return their corresponding output vector + * at the current time reached by the integration of the backward + * problem. To obtain the solution or quadratures associated with + * a given backward problem at some other time within the last + * integration step (dense output), first obtain a pointer to the + * proper CVODES memory by calling CVodeGetAdjCVodeBmem and then use it + * to call CVodeGetDky and CVodeGetQuadDky. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetB(void *cvode_mem, int which, + realtype *tBret, N_Vector yB); +SUNDIALS_EXPORT int CVodeGetQuadB(void *cvode_mem, int which, + realtype *tBret, N_Vector qB); + + +/* + * ================================================================= + * + * OPTIONAL OUTPUT FUNCTIONS FOR BACKWARD PROBLEMS + * + * ================================================================= + */ + + +/* + * ----------------------------------------------------------------- + * CVodeGetAdjCVodeBmem + * ----------------------------------------------------------------- + * CVodeGetAdjCVodeBmem returns a (void *) pointer to the CVODES + * memory allocated for the backward problem. This pointer can + * then be used to call any of the CVodeGet* CVODES routines to + * extract optional output for the backward integration phase. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void *CVodeGetAdjCVodeBmem(void *cvode_mem, int which); + + +/* + * ----------------------------------------------------------------- + * CVodeGetAdjY + * Returns the interpolated forward solution at time t. This + * function is a wrapper around the interpType-dependent internal + * function. + * The calling function must allocate space for y. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetAdjY(void *cvode_mem, realtype t, N_Vector y); + +/* + * ----------------------------------------------------------------- + * CVodeGetAdjCheckPointsInfo + * Loads an array of nckpnts structures of type CVadjCheckPointRec. + * The user must allocate space for ckpnt (ncheck+1). + * ----------------------------------------------------------------- + */ + +typedef struct { + void *my_addr; + void *next_addr; + realtype t0; + realtype t1; + long int nstep; + int order; + realtype step; +} CVadjCheckPointRec; + +SUNDIALS_EXPORT int CVodeGetAdjCheckPointsInfo(void *cvode_mem, CVadjCheckPointRec *ckpnt); + +/* + * ----------------------------------------------------------------- + * CVodeGetAdjDataPointHermite + * Returns the 2 vectors stored for cubic Hermite interpolation + * at the data point 'which'. The user must allocate space for + * y and yd. Returns CV_MEM_NULL if cvode_mem is NULL. + * Returns CV_ILL_INPUT if interpType != CV_HERMITE. + * CVodeGetAdjDataPointPolynomial + * Returns the vector stored for polynomial interpolation + * at the data point 'which'. The user must allocate space for + * y. Returns CV_MEM_NULL if cvode_mem is NULL. + * Returns CV_ILL_INPUT if interpType != CV_POLYNOMIAL. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetAdjDataPointHermite(void *cvode_mem, long int which, + realtype *t, N_Vector y, N_Vector yd); + +SUNDIALS_EXPORT int CVodeGetAdjDataPointPolynomial(void *cvode_mem, long int which, + realtype *t, int *order, N_Vector y); + +/* + * ----------------------------------------------------------------- + * CVodeGetAdjCurrentCheckPoint + * Returns the address of the 'active' check point. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetAdjCurrentCheckPoint(void *cvode_mem, void **addr); + + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/cvodes/cvodes.h b/odemex/Parser/CVode/cv_src/include/cvodes/cvodes.h new file mode 100644 index 0000000..f368530 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/cvodes/cvodes.h @@ -0,0 +1,1968 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.22 $ + * $Date: 2008/04/16 21:53:06 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the interface file for the main CVODES integrator. + * ----------------------------------------------------------------- + * + * CVODES is used to solve numerically the ordinary initial value + * problem: + * + * y' = f(t,y), + * y(t0) = y0, + * + * where t0, y0 in R^N, and f: R x R^N -> R^N are given. + * + * Optionally, CVODES can perform forward or adjoint sensitivity + * analysis to find sensitivities of the solution y with respect + * to parameters in the right hand side f and/or in the initial + * conditions y0. + * + * ----------------------------------------------------------------- + * + * 1: CONSTANTS + * input constants + * return flags + * + * 2: FUNCTION TYPES + * CVRhsFn CVQuadRhsFn CVSensRhsFn CVSensRhs1Fn CVQuadSensRhsFn + * CVRootFn + * CVEwtFn + * CVErrHandlerFn + * CVRhsFnB CVRhsFnBS + * CVQuadRhsFnB CVQuadRhsFnBS + * + * 3: INITIALIZATION AND DEALLOCATION FUNCTIONS FOR FORWARD PROBLEMS + * CVodeCreate + * CVodeInit CVodeReInit + * CVodeQuadInit CVodeQuadReInit + * CVodeSensInit CVodeSensReInit + * CVodeRootInit + * CVodeFree CVodeQuadFree CVodeSensFree + * + * 4: OPTIONAL INPUT FUNCTIONS FOR FORWARD PROBLEMS + * + * 5: MAIN SOLVER FUNCTION FOR FORWARD PROBLEMS + * CVode + * + * 6: EXTRACTION AND DENSE OUTPUT FUNCTIONS FOR FORWARD PROBLEMS + * CVodeGetDky + * CVodeGetQuad + * CVodeGetQuadDky + * CVodeGetSens CVodeGetSens1 + * CVodeGetSensDky CVodeGetSensDky1 + * CVodeGetQuadSens CVodeGetQuadSens1 + * CVodeGetQuadSensDky CVodeGetQuadSensDky1 + * + * 7: OPTIONAL OUTPUT FUNCTIONS FOR FORWARD PROBLEMS + * + * 8: INITIALIZATION AND DEALLOCATION FUNCTIONS FOR BACKWARD PROBLEMS + * CVodeAdjInit CVodeAdjReInit + * CVodeAdjFree + * CVodeInitB CVodeInitBS CVodeReInitB + * CVodeQuadInitB CVodeQuadInitBS CVodeQuadReInitB + * + * 9 MAIN SOLVER FUNCTIONS FOR FORWARD PROBLEMS + * CVodeF + * CVodeB + * + * 10: OPTIONAL INPUT FUNCTIONS FOR BACKWARD PROBLEMS + * + * 11: EXTRACTION AND DENSE OUTPUT FUNCTIONS FOR BACKWARD PROBLEMS + * CVodeGetB + * CVodeGetQuadB + * + * 12: OPTIONAL OUTPUT FUNCTIONS FOR BACKWARD PROBLEMS + * + * ----------------------------------------------------------------- + */ + +#ifndef _CVODES_H +#define _CVODES_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +#include + +/* + * ================================================================= + * + * CVODES CONSTANTS + * + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Enumerations for inputs to: + * CVodeCreate (lmm, iter), + * CVodeSensInit, CvodeSensinit1, CVodeSensReInit (ism), + * CVodeAdjInit (interp), + * CVode (itask) + * ----------------------------------------------------------------- + * Symbolic constants for the lmm and iter parameters to CVodeCreate + * the input parameter itask to CVode, and the input parameter interp + * to CVodeAdjInit, are given below. + * + * lmm: The user of the CVODES package specifies whether to use + * the CV_ADAMS or CV_BDF (backward differentiation formula) + * linear multistep method. The BDF method is recommended + * for stiff problems, and the CV_ADAMS method is recommended + * for nonstiff problems. + * + * iter: At each internal time step, a nonlinear equation must + * be solved. The user can specify either CV_FUNCTIONAL + * iteration, which does not require linear algebra, or a + * CV_NEWTON iteration, which requires the solution of linear + * systems. In the CV_NEWTON case, the user also specifies a + * CVODE linear solver. CV_NEWTON is recommended in case of + * stiff problems. + * + * ism: This parameter specifies the sensitivity corrector type + * to be used. In the CV_SIMULTANEOUS case, the nonlinear + * systems for states and all sensitivities are solved + * simultaneously. In the CV_STAGGERED case, the nonlinear + * system for states is solved first and then, the + * nonlinear systems for all sensitivities are solved + * at the same time. Finally, in the CV_STAGGERED1 approach + * all nonlinear systems are solved in a sequence. + * + * itask: The itask input parameter to CVode indicates the job + * of the solver for the next user step. The CV_NORMAL + * itask is to have the solver take internal steps until + * it has reached or just passed the user specified tout + * parameter. The solver then interpolates in order to + * return an approximate value of y(tout). The CV_ONE_STEP + * option tells the solver to just take one internal step + * and return the solution at the point reached by that step. + * + * interp: Specifies the interpolation type used to evaluate the + * forward solution during the backward integration phase. + * CV_HERMITE specifies cubic Hermite interpolation. + * CV_POYNOMIAL specifies the polynomial interpolation + * ----------------------------------------------------------------- + */ + +/* lmm */ +#define CV_ADAMS 1 +#define CV_BDF 2 + +/* iter */ +#define CV_FUNCTIONAL 1 +#define CV_NEWTON 2 + +/* itask */ +#define CV_NORMAL 1 +#define CV_ONE_STEP 2 + +/* ism */ +#define CV_SIMULTANEOUS 1 +#define CV_STAGGERED 2 +#define CV_STAGGERED1 3 + +/* DQtype */ +#define CV_CENTERED 1 +#define CV_FORWARD 2 + +/* interp */ +#define CV_HERMITE 1 +#define CV_POLYNOMIAL 2 + +/* + * ---------------------------------------- + * CVODES return flags + * ---------------------------------------- + */ + +#define CV_SUCCESS 0 +#define CV_TSTOP_RETURN 1 +#define CV_ROOT_RETURN 2 + +#define CV_WARNING 99 + +#define CV_TOO_MUCH_WORK -1 +#define CV_TOO_MUCH_ACC -2 +#define CV_ERR_FAILURE -3 +#define CV_CONV_FAILURE -4 + +#define CV_LINIT_FAIL -5 +#define CV_LSETUP_FAIL -6 +#define CV_LSOLVE_FAIL -7 +#define CV_RHSFUNC_FAIL -8 +#define CV_FIRST_RHSFUNC_ERR -9 +#define CV_REPTD_RHSFUNC_ERR -10 +#define CV_UNREC_RHSFUNC_ERR -11 +#define CV_RTFUNC_FAIL -12 + +#define CV_MEM_FAIL -20 +#define CV_MEM_NULL -21 +#define CV_ILL_INPUT -22 +#define CV_NO_MALLOC -23 +#define CV_BAD_K -24 +#define CV_BAD_T -25 +#define CV_BAD_DKY -26 +#define CV_TOO_CLOSE -27 + +#define CV_NO_QUAD -30 +#define CV_QRHSFUNC_FAIL -31 +#define CV_FIRST_QRHSFUNC_ERR -32 +#define CV_REPTD_QRHSFUNC_ERR -33 +#define CV_UNREC_QRHSFUNC_ERR -34 + +#define CV_NO_SENS -40 +#define CV_SRHSFUNC_FAIL -41 +#define CV_FIRST_SRHSFUNC_ERR -42 +#define CV_REPTD_SRHSFUNC_ERR -43 +#define CV_UNREC_SRHSFUNC_ERR -44 + +#define CV_BAD_IS -45 + +#define CV_NO_QUADSENS -50 +#define CV_QSRHSFUNC_FAIL -51 +#define CV_FIRST_QSRHSFUNC_ERR -52 +#define CV_REPTD_QSRHSFUNC_ERR -53 +#define CV_UNREC_QSRHSFUNC_ERR -54 + +/* + * ---------------------------------------- + * CVODEA return flags + * ---------------------------------------- + */ + +#define CV_NO_ADJ -101 +#define CV_NO_FWD -102 +#define CV_NO_BCK -103 +#define CV_BAD_TB0 -104 +#define CV_REIFWD_FAIL -105 +#define CV_FWD_FAIL -106 +#define CV_GETY_BADT -107 + +/* + * ================================================================= + * + * FUNCTION TYPES + * + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Type : CVRhsFn + * ----------------------------------------------------------------- + * The f function which defines the right hand side of the ODE + * system y' = f(t,y) must have type CVRhsFn. + * f takes as input the independent variable value t, and the + * dependent variable vector y. It stores the result of f(t,y) + * in the vector ydot. The y and ydot arguments are of type + * N_Vector. + * (Allocation of memory for ydot is handled within CVODES) + * The user_data parameter is the same as the user_data + * parameter set by the user through the CVodeSetUserData routine. + * This user-supplied pointer is passed to the user's f function + * every time it is called. + * + * A CVRhsFn should return 0 if successful, a negative value if + * an unrecoverable error occured, and a positive value if a + * recoverable error (e.g. invalid y values) occured. + * If an unrecoverable occured, the integration is halted. + * If a recoverable error occured, then (in most cases) CVODES + * will try to correct and retry. + * ----------------------------------------------------------------- + */ + +typedef int (*CVRhsFn)(realtype t, N_Vector y, + N_Vector ydot, void *user_data); + +/* + * ----------------------------------------------------------------- + * Type : CVRootFn + * ----------------------------------------------------------------- + * A function g, which defines a set of functions g_i(t,y) whose + * roots are sought during the integration, must have type CVRootFn. + * The function g takes as input the independent variable value + * t, and the dependent variable vector y. It stores the nrtfn + * values g_i(t,y) in the realtype array gout. + * (Allocation of memory for gout is handled within CVODE.) + * The user_data parameter is the same as that passed by the user + * to the CVodeSetUserData routine. This user-supplied pointer is + * passed to the user's g function every time it is called. + * + * A CVRootFn should return 0 if successful or a non-zero value + * if an error occured (in which case the integration will be halted). + * ----------------------------------------------------------------- + */ + +typedef int (*CVRootFn)(realtype t, N_Vector y, realtype *gout, void *user_data); + +/* + * ----------------------------------------------------------------- + * Type : CVEwtFn + * ----------------------------------------------------------------- + * A function e, which sets the error weight vector ewt, must have + * type CVEwtFn. + * The function e takes as input the current dependent variable y. + * It must set the vector of error weights used in the WRMS norm: + * + * ||y||_WRMS = sqrt [ 1/N * sum ( ewt_i * y_i)^2 ] + * + * Typically, the vector ewt has components: + * + * ewt_i = 1 / (reltol * |y_i| + abstol_i) + * + * The user_data parameter is the same as that passed by the user + * to the CVodeSetUserData routine. This user-supplied pointer is + * passed to the user's e function every time it is called. + * A CVEwtFn e must return 0 if the error weight vector has been + * successfuly set and a non-zero value otherwise. + * ----------------------------------------------------------------- + */ + +typedef int (*CVEwtFn)(N_Vector y, N_Vector ewt, void *user_data); + + +/* + * ----------------------------------------------------------------- + * Type : CVErrHandlerFn + * ----------------------------------------------------------------- + * A function eh, which handles error messages, must have type + * CVErrHandlerFn. + * The function eh takes as input the error code, the name of the + * module reporting the error, the error message, and a pointer to + * user data, the same as that passed to CVodeSetUserData. + * + * All error codes are negative, except CV_WARNING which indicates + * a warning (the solver continues). + * + * A CVErrHandlerFn has no return value. + * ----------------------------------------------------------------- + */ + +typedef void (*CVErrHandlerFn)(int error_code, + const char *module, const char *function, + char *msg, void *user_data); + +/* + * ----------------------------------------------------------------- + * Type : CVQuadRhsFn + * ----------------------------------------------------------------- + * The fQ function which defines the right hand side of the + * quadrature equations yQ' = fQ(t,y) must have type CVQuadRhsFn. + * fQ takes as input the value of the independent variable t, + * the vector of states y and must store the result of fQ in + * yQdot. (Allocation of memory for yQdot is handled by CVODES). + * The user_data parameter is the same as the user_data parameter + * set by the user through the CVodeSetUserData routine and is + * passed to the fQ function every time it is called. + * + * If the quadrature RHS also depends on the sensitivity variables, + * i.e., yQ' = fQs(t,y,yS), then fQ must be of type CVodeQuadRhsFnS. + * + * A CVQuadRhsFn or CVodeQuadRhsFnS should return 0 if successful, + * a negative value if an unrecoverable error occured, and a positive + * value if a recoverable error (e.g. invalid y values) occured. + * If an unrecoverable occured, the integration is halted. + * If a recoverable error occured, then (in most cases) CVODES + * will try to correct and retry. + * ----------------------------------------------------------------- + */ + +typedef int (*CVQuadRhsFn)(realtype t, N_Vector y, + N_Vector yQdot, + void *user_data); + +/* + * ----------------------------------------------------------------- + * Type : CVSensRhsFn + * ----------------------------------------------------------------- + * The fS function which defines the right hand side of the + * sensitivity ODE systems s' = f_y * s + f_p must have type + * CVSensRhsFn. + * fS takes as input the number of sensitivities Ns, the + * independent variable value t, the states y and the + * corresponding value of f(t,y) in ydot, and the dependent + * sensitivity vectors yS. It stores the result of fS in ySdot. + * (Allocation of memory for ySdot is handled within CVODES) + * The user_data parameter is the same as the user_data parameter + * set by the user through the CVodeSetUserData routine and is + * passed to the fS function every time it is called. + * + * A CVSensRhsFn should return 0 if successful, a negative value if + * an unrecoverable error occured, and a positive value if a + * recoverable error (e.g. invalid y or yS values) occured. + * If an unrecoverable occured, the integration is halted. + * If a recoverable error occured, then (in most cases) CVODES + * will try to correct and retry. + * ----------------------------------------------------------------- + */ + +typedef int (*CVSensRhsFn)(int Ns, realtype t, + N_Vector y, N_Vector ydot, + N_Vector *yS, N_Vector *ySdot, + void *user_data, + N_Vector tmp1, N_Vector tmp2); + +/* + * ----------------------------------------------------------------- + * Type : CVSensRhs1Fn + * ----------------------------------------------------------------- + * The fS1 function which defines the right hand side of the i-th + * sensitivity ODE system s_i' = f_y * s_i + f_p must have type + * CVSensRhs1Fn. + * fS1 takes as input the number of sensitivities Ns, the current + * sensitivity iS, the independent variable value t, the states y + * and the corresponding value of f(t,y) in ydot, and the + * dependent sensitivity vector yS. It stores the result of fS in + * ySdot. + * (Allocation of memory for ySdot is handled within CVODES) + * The user_data parameter is the same as the user_data parameter + * set by the user through the CVodeSetUserData routine and is + * passed to the fS1 function every time it is called. + * + * A CVSensRhs1Fn should return 0 if successful, a negative value if + * an unrecoverable error occured, and a positive value if a + * recoverable error (e.g. invalid y or yS values) occured. + * If an unrecoverable occured, the integration is halted. + * If a recoverable error occured, then (in most cases) CVODES + * will try to correct and retry. + * ----------------------------------------------------------------- + */ + +typedef int (*CVSensRhs1Fn)(int Ns, realtype t, + N_Vector y, N_Vector ydot, + int iS, N_Vector yS, N_Vector ySdot, + void *user_data, + N_Vector tmp1, N_Vector tmp2); + +/* + * ----------------------------------------------------------------- + * Type : CVQuadSensRhsFn + * ----------------------------------------------------------------- + * The fQS function which defines the right hand side of the + * sensitivity ODE systems for quadratures, yQS' = fQ_y * yS + fQ_p + * must have type CVQuadSensRhsFn. + * + * fQS takes as input the number of sensitivities Ns (the same as + * that passed to CVodeQuadSensInit), the independent variable + * value t, the states y and the dependent sensitivity vectors yS, + * as well as the current value of the quadrature RHS yQdot. + * It stores the result of fQS in yQSdot. + * (Allocation of memory for yQSdot is handled within CVODES) + * + * A CVQuadSensRhsFn should return 0 if successful, a negative + * value if an unrecoverable error occured, and a positive value + * if a recoverable error (e.g. invalid y or yS values) occured. + * If an unrecoverable occured, the integration is halted. + * If a recoverable error occured, then (in most cases) CVODES + * will try to correct and retry. + * ----------------------------------------------------------------- + */ + +typedef int (*CVQuadSensRhsFn)(int Ns, realtype t, + N_Vector y, N_Vector *yS, + N_Vector yQdot, N_Vector *yQSdot, + void *user_data, + N_Vector tmp, N_Vector tmpQ); + +/* + * ----------------------------------------------------------------- + * CVRhsFnB and CVRhsFnBS + * The fB function which defines the right hand side of the + * ODE systems to be integrated backwards must have type CVRhsFnB. + * If the backward problem depends on forward sensitivities, its + * RHS function must have type CVRhsFnBS. + * ----------------------------------------------------------------- + * CVQuadRhsFnB and CVQuadRhsFnBS + * The fQB function which defines the quadratures to be integrated + * backwards must have type CVQuadRhsFnB. + * If the backward problem depends on forward sensitivities, its + * quadrature RHS function must have type CVQuadRhsFnBS. + * ----------------------------------------------------------------- + */ + +typedef int (*CVRhsFnB)(realtype t, N_Vector y, + N_Vector yB, N_Vector yBdot, + void *user_dataB); + +typedef int (*CVRhsFnBS)(realtype t, N_Vector y, N_Vector *yS, + N_Vector yB, N_Vector yBdot, + void *user_dataB); + + +typedef int (*CVQuadRhsFnB)(realtype t, N_Vector y, + N_Vector yB, N_Vector qBdot, + void *user_dataB); + +typedef int (*CVQuadRhsFnBS)(realtype t, N_Vector y, N_Vector *yS, + N_Vector yB, N_Vector qBdot, + void *user_dataB); + + +/* + * ================================================================= + * + * INITIALIZATION AND DEALLOCATION FUNCTIONS FOR FORWARD PROBLEMS + * + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Function : CVodeCreate + * ----------------------------------------------------------------- + * CVodeCreate creates an internal memory block for a problem to + * be solved by CVODES. + * + * lmm is the type of linear multistep method to be used. + * The legal values are CV_ADAMS and CV_BDF (see previous + * description). + * + * iter is the type of iteration used to solve the nonlinear + * system that arises during each internal time step. + * The legal values are CV_FUNCTIONAL and CV_NEWTON. + * + * If successful, CVodeCreate returns a pointer to initialized + * problem memory. This pointer should be passed to CVodeInit. + * If an initialization error occurs, CVodeCreate prints an error + * message to standard err and returns NULL. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void *CVodeCreate(int lmm, int iter); + +/* + * ----------------------------------------------------------------- + * Functions : CVodeInit and CVodeReInit + * ----------------------------------------------------------------- + * CVodeInit allocates and initializes memory for a problem to + * to be solved by CVODE. + * + * CVodeReInit re-initializes CVode for the solution of a problem, + * where a prior call to CVodeInit has been made with the same + * problem size N. CVodeReInit performs the same input checking + * and initializations that CVodeInit does. + * But it does no memory allocation, assuming that the existing + * internal memory is sufficient for the new problem. + * + * The use of CVodeReInit requires that the maximum method order, + * maxord, is no larger for the new problem than for the problem + * specified in the last call to CVodeInit. This condition is + * automatically fulfilled if the multistep method parameter lmm + * is unchanged (or changed from CV_ADAMS to CV_BDF) and the default + * value for maxord is specified. + * + * cvode_mem is pointer to CVODE memory returned by CVodeCreate. + * + * f is the name of the C function defining the right-hand + * side function in y' = f(t,y). + * + * t0 is the initial value of t. + * + * y0 is the initial condition vector y(t0). + * + * Return flag: + * CV_SUCCESS if successful + * CV_MEM_NULL if the cvode memory was NULL + * CV_MEM_FAIL if a memory allocation failed + * CV_NO_MALLOC if cvode_mem has not been allocated + * (i.e., CVodeInit has not been called). + * CV_ILL_INPUT if an argument has an illegal value. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeInit(void *cvode_mem, CVRhsFn f, realtype t0, N_Vector y0); +SUNDIALS_EXPORT int CVodeReInit(void *cvode_mem, realtype t0, N_Vector y0); + +/* + * ----------------------------------------------------------------- + * Functions : CVodeSStolerances + * CVodeSVtolerances + * CVodeWFtolerances + * ----------------------------------------------------------------- + * + * These functions specify the integration tolerances. One of them + * MUST be called before the first call to CVode. + * + * CVodeSStolerances specifies scalar relative and absolute tolerances. + * CVodeSVtolerances specifies scalar relative tolerance and a vector + * absolute tolerance (a potentially different absolute tolerance + * for each vector component). + * CVodeWFtolerances specifies a user-provides function (of type CVEwtFn) + * which will be called to set the error weight vector. + * + * The tolerances reltol and abstol define a vector of error weights, + * ewt, with components + * ewt[i] = 1/(reltol*abs(y[i]) + abstol) (in the SS case), or + * ewt[i] = 1/(reltol*abs(y[i]) + abstol[i]) (in the SV case). + * This vector is used in all error and convergence tests, which + * use a weighted RMS norm on all error-like vectors v: + * WRMSnorm(v) = sqrt( (1/N) sum(i=1..N) (v[i]*ewt[i])^2 ), + * where N is the problem dimension. + * + * The return value of these functions is equal to CV_SUCCESS = 0 if + * there were no errors; otherwise it is a negative int equal to: + * CV_MEM_NULL indicating cvode_mem was NULL (i.e., + * CVodeCreate has not been called). + * CV_NO_MALLOC indicating that cvode_mem has not been + * allocated (i.e., CVodeInit has not been + * called). + * CV_ILL_INPUT indicating an input argument was illegal + * (e.g. a negative tolerance) + * In case of an error return, an error message is also printed. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeSStolerances(void *cvode_mem, realtype reltol, realtype abstol); +SUNDIALS_EXPORT int CVodeSVtolerances(void *cvode_mem, realtype reltol, N_Vector abstol); +SUNDIALS_EXPORT int CVodeWFtolerances(void *cvode_mem, CVEwtFn efun); + +/* + * ----------------------------------------------------------------- + * Function : CVodeQuadInit and CVodeQuadReInit + * ----------------------------------------------------------------- + * CVodeQuadInit allocates and initializes memory related to + * quadrature integration. + * + * CVodeQuadReInit re-initializes CVODES's quadrature related + * memory for a problem, assuming it has already been allocated + * in prior calls to CVodeInit and CVodeQuadInit. + * The number of quadratures Nq is assumed to be unchanged + * since the previous call to CVodeQuadInit. + * + * cvode_mem is a pointer to CVODES memory returned by CVodeCreate + * + * fQ is the user-provided integrand routine. + * + * yQ0 is an N_Vector with initial values for quadratures + * (typically yQ0 has all zero components). + * + * Return values: + * CV_SUCCESS if successful + * CV_MEM_NULL if the cvode memory was NULL + * CV_MEM_FAIL if a memory allocation failed + * CV_NO_QUAD if quadratures were not initialized + * (i.e. CVodeQuadInit has not been called) + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeQuadInit(void *cvode_mem, CVQuadRhsFn fQ, N_Vector yQ0); +SUNDIALS_EXPORT int CVodeQuadReInit(void *cvode_mem, N_Vector yQ0); + +/* + * ----------------------------------------------------------------- + * Functions : CVodeQuadSStolerances + * CVodeQuadSVtolerances + * ----------------------------------------------------------------- + * + * These functions specify the integration tolerances for quadrature + * variables. One of them MUST be called before the first call to + * CVode IF error control on the quadrature variables is enabled + * (see CVodeSetQuadErrCon). + * + * CVodeSStolerances specifies scalar relative and absolute tolerances. + * CVodeSVtolerances specifies scalar relative tolerance and a vector + * absolute tolerance (a potentially different absolute tolerance + * for each vector component). + * + * Return values: + * CV_SUCCESS if successful + * CV_MEM_NULL if the cvode memory was NULL + * CV_NO_QUAD if quadratures were not initialized + * CV_ILL_INPUT if an input argument was illegal + * (e.g. a negative tolerance) + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeQuadSStolerances(void *cvode_mem, realtype reltolQ, realtype abstolQ); +SUNDIALS_EXPORT int CVodeQuadSVtolerances(void *cvode_mem, realtype reltolQ, N_Vector abstolQ); + +/* + * ----------------------------------------------------------------- + * Function : CVodeSensInit, CVSensInit1, and CVodeSensReInit + * ----------------------------------------------------------------- + * CVodeSensInit and CVSensInit1 allocate and initialize memory + * related to sensitivity computations. They only differ in the + * type of the sensitivity RHS function: CVodeSensInit specifies + * fS of type CVSensRhsFn (i.e. a function that evaluates all + * sensitivity RHS simultaneously), while CVodeSensInit1 specifies + * fS of type CVSensRhs1Fn (i.e. a function that evaluates one + * sensitivity RHS at a time). Recall that ism=CV_STAGGERED1 is + * compatible ONLY with a CVSensRhs1Fn. As such, this value for + * ism cannot be passed to CVodeSensInit. + * + * CVodeSensReInit re-initializes CVODES's sensitivity related + * memory for a problem, assuming it has already been allocated + * in prior calls to CVodeInit and CVodeSensInit. + * The number of sensitivities Ns is assumed to be unchanged + * since the previous call to CVodeSensInit. + * If any error occurs during initialization, it is reported to + * the file whose file pointer is errfp. + * CVodeSensReInit potentially does some minimal memory allocation + * (for the sensitivity absolute tolerance and for arrays of + * counters used by the CV_STAGGERED1 method). + + * cvode_mem is pointer to CVODES memory returned by CVodeCreate + * + * Ns is the number of sensitivities to be computed. + * + * ism is the type of corrector used in sensitivity + * analysis. The legal values are: CV_SIMULTANEOUS, + * CV_STAGGERED, and CV_STAGGERED1. + * + * fS is the sensitivity righ-hand side function + * (pass NULL to use the internal DQ approximation) + * + * yS0 is the array of initial condition vectors for + * sensitivity variables. + * + * Return values: + * CV_SUCCESS + * CV_MEM_NULL + * CV_ILL_INPUT + * CV_MEM_FAIL + * CV_NO_SENS + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeSensInit(void *cvode_mem, int Ns, int ism, + CVSensRhsFn fS, N_Vector *yS0); +SUNDIALS_EXPORT int CVodeSensInit1(void *cvode_mem, int Ns, int ism, + CVSensRhs1Fn fS1, N_Vector *yS0); +SUNDIALS_EXPORT int CVodeSensReInit(void *cvode_mem, int ism, N_Vector *yS0); + +/* + * ----------------------------------------------------------------- + * Functions : CVodeSensSStolerances + * CVodeSensSVtolerances + * CVodeSensEEtolerances + * ----------------------------------------------------------------- + * + * These functions specify the integration tolerances for sensitivity + * variables. One of them MUST be called before the first call to CVode. + * + * CVodeSensSStolerances specifies scalar relative and absolute tolerances. + * CVodeSensSVtolerances specifies scalar relative tolerance and a vector + * absolute tolerance for each sensitivity vector (a potentially different + * absolute tolerance for each vector component). + * CVodeSensEEtolerances specifies that tolerances for sensitivity variables + * should be estimated from those provided for the state variables. + * + * The return value is equal to CV_SUCCESS = 0 if there were no + * errors; otherwise it is a negative int equal to: + * CV_MEM_NULL indicating cvode_mem was NULL, or + * CV_NO_SENS indicating there was not a prior call to + * CVodeSensInit. + * CV_ILL_INPUT indicating an input argument was illegal + * (e.g. negative tolerances) + * In case of an error return, an error message is also printed. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeSensSStolerances(void *cvode_mem, realtype reltolS, realtype *abstolS); +SUNDIALS_EXPORT int CVodeSensSVtolerances(void *cvode_mem, realtype reltolS, N_Vector *abstolS); +SUNDIALS_EXPORT int CVodeSensEEtolerances(void *cvode_mem); + +/* + * ----------------------------------------------------------------- + * Function : CVodeQuadSensInit and CVodeQuadSensReInit + * ----------------------------------------------------------------- + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeQuadSensInit(void *cvode_mem, CVQuadSensRhsFn fQS, N_Vector *yQS0); +SUNDIALS_EXPORT int CVodeQuadSensReInit(void *cvode_mem, N_Vector *yQS0); + +/* + * ----------------------------------------------------------------- + * Functions : CVodeQuadSensSStolerances + * CVodeQuadSensSVtolerances + * CVodeQuadSensEEtolerances + * ----------------------------------------------------------------- + * + * These functions specify the integration tolerances for quadrature + * sensitivity variables. One of them MUST be called before the first + * call to CVode IF these variables are included in the error test. + * + * CVodeQuadSensSStolerances specifies scalar relative and absolute tolerances. + * CVodeQuadSensSVtolerances specifies scalar relative tolerance and a vector + * absolute tolerance for each quadrature sensitivity vector (a potentially + * different absolute tolerance for each vector component). + * CVodeQuadSensEEtolerances specifies that tolerances for sensitivity variables + * should be estimated from those provided for the quadrature variables. + * In this case, tolerances for the quadrature variables must be + * specified through a call to one of CVodeQuad**tolerances. + * + * The return value is equal to CV_SUCCESS = 0 if there were no + * errors; otherwise it is a negative int equal to: + * CV_MEM_NULL if cvode_mem was NULL, or + * CV_NO_QuadSENS if there was not a prior call to + * CVodeQuadSensInit. + * CV_ILL_INPUT if an input argument was illegal + * (e.g. negative tolerances) + * In case of an error return, an error message is also printed. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeQuadSensSStolerances(void *cvode_mem, realtype reltolQS, realtype *abstolQS); +SUNDIALS_EXPORT int CVodeQuadSensSVtolerances(void *cvode_mem, realtype reltolQS, N_Vector *abstolQS); +SUNDIALS_EXPORT int CVodeQuadSensEEtolerances(void *cvode_mem); + +/* + * ----------------------------------------------------------------- + * Function : CVodeRootInit + * ----------------------------------------------------------------- + * CVodeRootInit initializes a rootfinding problem to be solved + * during the integration of the ODE system. It must be called + * after CVodeCreate, and before CVode. The arguments are: + * + * cvode_mem = pointer to CVODE memory returned by CVodeCreate. + * + * nrtfn = number of functions g_i, an int >= 0. + * + * g = name of user-supplied function, of type CVRootFn, + * defining the functions g_i whose roots are sought. + * + * If a new problem is to be solved with a call to CVodeReInit, + * where the new problem has no root functions but the prior one + * did, then call CVodeRootInit with nrtfn = 0. + * + * The return value of CVodeRootInit is CV_SUCCESS = 0 if there were + * no errors; otherwise it is a negative int equal to: + * CV_MEM_NULL indicating cvode_mem was NULL, or + * CV_MEM_FAIL indicating a memory allocation failed. + * (including an attempt to increase maxord). + * CV_ILL_INPUT indicating nrtfn > 0 but g = NULL. + * In case of an error return, an error message is also printed. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeRootInit(void *cvode_mem, int nrtfn, CVRootFn g); + +/* + * ----------------------------------------------------------------- + * Function : CVodeFree + * ----------------------------------------------------------------- + * CVodeFree frees the problem memory cvode_mem allocated by + * CVodeInit. Its only argument is the pointer cvode_mem + * returned by CVodeCreate. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void CVodeFree(void **cvode_mem); + +/* + * ----------------------------------------------------------------- + * Function : CVodeQuadFree + * ----------------------------------------------------------------- + * CVodeQuadFree frees the problem memory in cvode_mem allocated + * for quadrature integration. Its only argument is the pointer + * cvode_mem returned by CVodeCreate. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void CVodeQuadFree(void *cvode_mem); + +/* + * ----------------------------------------------------------------- + * Function : CVodeSensFree + * ----------------------------------------------------------------- + * CVodeSensFree frees the problem memory in cvode_mem allocated + * for sensitivity analysis. Its only argument is the pointer + * cvode_mem returned by CVodeCreate. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void CVodeSensFree(void *cvode_mem); + +/* + * ----------------------------------------------------------------- + * Function : CVodeQuadSensFree + * ----------------------------------------------------------------- + * CVodeQuadSensFree frees the problem memory in cvode_mem allocated + * for quadrature sensitivity analysis. Its only argument is the + * pointer cvode_mem returned by CVodeCreate. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void CVodeQuadSensFree(void *cvode_mem); + +/* + * ================================================================= + * + * OPTIONAL INPUT FUNCTIONS FOR FORWARD PROBLEMS + * + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Integrator optional input specification functions + * ----------------------------------------------------------------- + * The following functions can be called to set optional inputs + * to values other than the defaults given below: + * + * Function | Optional input / [ default value ] + * ----------------------------------------------------------------- + * | + * CVodeSetErrHandlerFn | user-provided ErrHandler function. + * | [internal] + * | + * CVodeSetErrFile | the file pointer for an error file + * | where all CVODE warning and error + * | messages will be written if the default + * | internal error handling function is used. + * | This parameter can be stdout (standard + * | output), stderr (standard error), or a + * | file pointer (corresponding to a user + * | error file opened for writing) returned + * | by fopen. + * | If not called, then all messages will + * | be written to the standard error stream. + * | [stderr] + * | + * CVodeSetUserData | a pointer to user data that will be + * | passed to the user's f function every + * | time f is called. + * | [NULL] + * | + * CVodeSetMaxOrd | maximum lmm order to be used by the + * | solver. + * | [12 for Adams , 5 for BDF] + * | + * CVodeSetMaxNumSteps | maximum number of internal steps to be + * | taken by the solver in its attempt to + * | reach tout. + * | [500] + * | + * CVodeSetMaxHnilWarns | maximum number of warning messages + * | issued by the solver that t+h==t on the + * | next internal step. A value of -1 means + * | no such messages are issued. + * | [10] + * | + * CVodeSetStabLimDet | flag to turn on/off stability limit + * | detection (TRUE = on, FALSE = off). + * | When BDF is used and order is 3 or + * | greater, CVsldet is called to detect + * | stability limit. If limit is detected, + * | the order is reduced. + * | [FALSE] + * | + * CVodeSetInitStep | initial step size. + * | [estimated by CVODES] + * | + * CVodeSetMinStep | minimum absolute value of step size + * | allowed. + * | [0.0] + * | + * CVodeSetMaxStep | maximum absolute value of step size + * | allowed. + * | [infinity] + * | + * CVodeSetStopTime | the independent variable value past + * | which the solution is not to proceed. + * | [infinity] + * | + * CVodeSetMaxErrTestFails | Maximum number of error test failures + * | in attempting one step. + * | [7] + * | + * CVodeSetMaxNonlinIters | Maximum number of nonlinear solver + * | iterations at one solution. + * | [3] + * | + * CVodeSetMaxConvFails | Maximum number of allowable conv. + * | failures in attempting one step. + * | [10] + * | + * CVodeSetNonlinConvCoef | Coeficient in the nonlinear conv. + * | test. + * | [0.1] + * | + * ----------------------------------------------------------------- + * | + * CVodeSetIterType | Changes the current nonlinear iteration + * | type. + * | [set by CVodecreate] + * | + * ----------------------------------------------------------------- + * | + * CVodeSetRootDirection | Specifies the direction of zero + * | crossings to be monitored + * | [both directions] + * | + * CVodeSetNoInactiveRootWarn | disable warning about possible + * | g==0 at beginning of integration + * | + * ----------------------------------------------------------------- + * Return flag: + * CV_SUCCESS if successful + * CV_MEM_NULL if the cvode memory is NULL + * CV_ILL_INPUT if an argument has an illegal value + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeSetErrHandlerFn(void *cvode_mem, CVErrHandlerFn ehfun, void *eh_data); +SUNDIALS_EXPORT int CVodeSetErrFile(void *cvode_mem, FILE *errfp); +SUNDIALS_EXPORT int CVodeSetUserData(void *cvode_mem, void *user_data); +SUNDIALS_EXPORT int CVodeSetMaxOrd(void *cvode_mem, int maxord); +SUNDIALS_EXPORT int CVodeSetMaxNumSteps(void *cvode_mem, long int mxsteps); +SUNDIALS_EXPORT int CVodeSetMaxHnilWarns(void *cvode_mem, int mxhnil); +SUNDIALS_EXPORT int CVodeSetStabLimDet(void *cvode_mem, booleantype stldet); +SUNDIALS_EXPORT int CVodeSetInitStep(void *cvode_mem, realtype hin); +SUNDIALS_EXPORT int CVodeSetMinStep(void *cvode_mem, realtype hmin); +SUNDIALS_EXPORT int CVodeSetMaxStep(void *cvode_mem, realtype hmax); +SUNDIALS_EXPORT int CVodeSetStopTime(void *cvode_mem, realtype tstop); +SUNDIALS_EXPORT int CVodeSetMaxErrTestFails(void *cvode_mem, int maxnef); +SUNDIALS_EXPORT int CVodeSetMaxNonlinIters(void *cvode_mem, int maxcor); +SUNDIALS_EXPORT int CVodeSetMaxConvFails(void *cvode_mem, int maxncf); +SUNDIALS_EXPORT int CVodeSetNonlinConvCoef(void *cvode_mem, realtype nlscoef); + +SUNDIALS_EXPORT int CVodeSetIterType(void *cvode_mem, int iter); + +SUNDIALS_EXPORT int CVodeSetRootDirection(void *cvode_mem, int *rootdir); +SUNDIALS_EXPORT int CVodeSetNoInactiveRootWarn(void *cvode_mem); + + +/* + * ----------------------------------------------------------------- + * Quadrature optional input specification functions + * ----------------------------------------------------------------- + * The following functions can be called to set optional inputs + * to values other than the defaults given below: + * + * Function | Optional input / [ default value ] + * -------------------------------------------------------------- + * | + * CVodeSetQuadErrCon | are quadrature variables considered in + * | the error control? + * | If yes, tolerances for quadrature are + * | required (see CVodeQuad**tolerances) + * | [errconQ = FALSE] + * | + * ----------------------------------------------------------------- + * If successful, these functions return CV_SUCCESS. If an argument + * has an illegal value, they return one of the error flags + * defined for the CVodeSet* routines. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeSetQuadErrCon(void *cvode_mem, booleantype errconQ); + +/* + * ----------------------------------------------------------------- + * Forward sensitivity optional input specification functions + * ----------------------------------------------------------------- + * The following functions can be called to set optional inputs + * to other values than the defaults given below: + * + * Function | Optional input / [ default value ] + * ----------------------------------------------------------------- + * | + * CVodeSetSensDQMethod | controls the selection of finite + * | difference schemes used in evaluating + * | the sensitivity right hand sides: + * | (centered vs. forward and + * | simultaneous vs. separate) + * | [DQtype=CV_CENTERED] + * | [DQrhomax=0.0] + * | + * CVodeSetSensParams | parameter information: + * | p: pointer to problem parameters + * | plist: list of parameters with respect + * | to which sensitivities are to be + * | computed. + * | pbar: order of magnitude info. + * | Typically, if p[plist[i]] is nonzero, + * | pbar[i]=p[plist[i]]. + * | [p=NULL] + * | [plist=NULL] + * | [pbar=NULL] + * | + * CVodeSetSensErrCon | are sensitivity variables considered in + * | the error control? + * | [FALSE] + * | + * CVodeSetSensMaxNonlinIters | Maximum number of nonlinear solver + * | iterations at one solution. + * | [3] + * | + * ----------------------------------------------------------------- + * The return values are the same as for CVodeSet* + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeSetSensDQMethod(void *cvode_mem, int DQtype, realtype DQrhomax); +SUNDIALS_EXPORT int CVodeSetSensErrCon(void *cvode_mem, booleantype errconS); +SUNDIALS_EXPORT int CVodeSetSensMaxNonlinIters(void *cvode_mem, int maxcorS); +SUNDIALS_EXPORT int CVodeSetSensParams(void *cvode_mem, realtype *p, realtype *pbar, int *plist); + +/* + * ----------------------------------------------------------------- + * Quadrature sensitivity optional input specification functions + * ----------------------------------------------------------------- + * The following functions can be called to set optional inputs + * to values other than the defaults given below: + * + * Function | Optional input / [ default value ] + * -------------------------------------------------------------- + * | + * CVodeSetQuadSensErrCon | are quadrature sensitivity variables + * | considered in the error control? + * | If yes, tolerances for quadrature + * | sensitivity variables are required. + * | [errconQS = FALSE] + * | + * ----------------------------------------------------------------- + * If successful, these functions return CV_SUCCESS. If an argument + * has an illegal value, they return one of the error flags + * defined for the CVodeSet* routines. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeSetQuadSensErrCon(void *cvode_mem, booleantype errconQS); + +/* + * ----------------------------------------------------------------- + * Function : CVodeSensToggleOff + * ----------------------------------------------------------------- + * CVodeSensToggleOff deactivates sensitivity calculations. + * It does NOT deallocate sensitivity-related memory so that + * sensitivity computations can be later toggled ON (through + * CVodeSensReInit). + * + * The return value is equal to CV_SUCCESS = 0 if there were no + * errors or CV_MEM_NULL if cvode_mem was NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeSensToggleOff(void *cvode_mem); + + +/* + * ================================================================= + * + * MAIN SOLVER FUNCTION FOR FORWARD PROBLEMS + * + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Function : CVode + * ----------------------------------------------------------------- + * CVode integrates the ODE over an interval in t. + * If itask is CV_NORMAL, then the solver integrates from its + * current internal t value to a point at or beyond tout, then + * interpolates to t = tout and returns y(tout) in the user- + * allocated vector yout. If itask is CV_ONE_STEP, then the solver + * takes one internal time step and returns in yout the value of + * y at the new internal time. In this case, tout is used only + * during the first call to CVode to determine the direction of + * integration and the rough scale of the problem. If tstop is + * enabled (through a call to CVodeSetStopTime), then CVode returns + * the solution at tstop. Once the integrator returns at a tstop + * time, any future testing for tstop is disabled (and can be + * reenabled only though a new call to CVodeSetStopTime). + * The time reached by the solver is placed in (*tret). The + * user is responsible for allocating the memory for this value. + * + * cvode_mem is the pointer to CVODES memory returned by + * CVodeCreate. + * + * tout is the next time at which a computed solution is desired. + * + * yout is the computed solution vector. In CV_NORMAL mode with no + * errors and no roots found, yout=y(tout). + * + * tret is a pointer to a real location. CVode sets (*tret) to + * the time reached by the solver and returns yout=y(*tret). + * + * itask is CV_NORMAL or CV_ONE_STEP. These two modes are described above. + * + * Here is a brief description of each return value: + * + * CV_SUCCESS: CVode succeeded and no roots were found. + * + * CV_ROOT_RETURN: CVode succeeded, and found one or more roots. + * If nrtfn > 1, call CVodeGetRootInfo to see + * which g_i were found to have a root at (*tret). + * + * CV_TSTOP_RETURN: CVode succeded and returned at tstop. + * + * CV_MEM_NULL: The cvode_mem argument was NULL. + * + * CV_NO_MALLOC: cvode_mem was not allocated. + * + * CV_ILL_INPUT: One of the inputs to CVode is illegal. This + * includes the situation when a component of the + * error weight vectors becomes < 0 during + * internal time-stepping. The ILL_INPUT flag + * will also be returned if the linear solver + * routine CV--- (called by the user after + * calling CVodeCreate) failed to set one of the + * linear solver-related fields in cvode_mem or + * if the linear solver's init routine failed. In + * any case, the user should see the printed + * error message for more details. + * + * CV_TOO_MUCH_WORK: The solver took mxstep internal steps but + * could not reach tout. The default value for + * mxstep is MXSTEP_DEFAULT = 500. + * + * CV_TOO_MUCH_ACC: The solver could not satisfy the accuracy + * demanded by the user for some internal step. + * + * CV_ERR_FAILURE: Error test failures occurred too many times + * (= MXNEF = 7) during one internal time step or + * occurred with |h| = hmin. + * + * CV_CONV_FAILURE: Convergence test failures occurred too many + * times (= MXNCF = 10) during one internal time + * step or occurred with |h| = hmin. + * + * CV_LINIT_FAIL: The linear solver's initialization function + * failed. + * + * CV_LSETUP_FAIL: The linear solver's setup routine failed in an + * unrecoverable manner. + * + * CV_LSOLVE_FAIL: The linear solver's solve routine failed in an + * unrecoverable manner. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVode(void *cvode_mem, realtype tout, N_Vector yout, + realtype *tret, int itask); + + +/* + * ================================================================= + * + * EXTRACTION AND DENSE OUTPUT FUNCTIONS FOR FORWARD PROBLEMS + * + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Function : CVodeGetDky + * ----------------------------------------------------------------- + * CVodeGetDky computes the kth derivative of the y function at + * time t, where tn-hu <= t <= tn, tn denotes the current + * internal time reached, and hu is the last internal step size + * successfully used by the solver. The user may request + * k=0, 1, ..., qu, where qu is the current order. The + * derivative vector is returned in dky. This vector must be + * allocated by the caller. It is only legal to call this + * function after a successful return from CVode. + * + * cvode_mem is the pointer to CVODES memory returned by + * CVodeCreate. + * + * t is the time at which the kth derivative of y is evaluated. + * The legal range for t is [tn-hu,tn] as described above. + * + * k is the order of the derivative of y to be computed. The + * legal range for k is [0,qu] as described above. + * + * dky is the output derivative vector [(D_k)y](t). + * + * The return values for CVodeGetDky are defined below. + * Here is a brief description of each return value: + * + * CV_SUCCESS: CVodeGetDky succeeded. + * + * CV_BAD_K : k is not in the range 0, 1, ..., qu. + * + * CV_BAD_T : t is not in the interval [tn-hu,tn]. + * + * CV_BAD_DKY : The dky argument was NULL. + * + * CV_MEM_NULL : The cvode_mem argument was NULL. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetDky(void *cvode_mem, realtype t, int k, N_Vector dky); + + +/* + * ----------------------------------------------------------------- + * Quadrature integration solution extraction routines + * ----------------------------------------------------------------- + * The following functions can be called to obtain the quadrature + * variables after a successful integration step. + * If quadratures were not computed, they return CV_NO_QUAD. + * + * CVodeGetQuad returns the quadrature variables at the same time + * as that at which CVode returned the solution. + * + * CVodeGetQuadDky returns the quadrature variables (or their + * derivatives up to the current method order) at any time within + * the last integration step (dense output). See CVodeGetQuad for + * more information. + * + * The output vectors yQout and dky must be allocated by the user. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetQuad(void *cvode_mem, realtype *tret, N_Vector yQout); + +SUNDIALS_EXPORT int CVodeGetQuadDky(void *cvode_mem, realtype t, int k, N_Vector dky); + +/* + * ----------------------------------------------------------------- + * Forward sensitivity solution extraction routines + * ----------------------------------------------------------------- + * The following functions can be called to obtain the sensitivity + * variables after a successful integration step. + * + * CVodeGetSens and CVodeGetSens1 return all the sensitivity vectors + * or only one of them, respectively, at the same time as that at + * which CVode returned the solution. + * The array of output vectors or output vector ySout must be + * allocated by the user. + * + * CVodeGetSensDky1 computes the kth derivative of the is-th + * sensitivity (is=1, 2, ..., Ns) of the y function at time t, + * where tn-hu <= t <= tn, tn denotes the current internal time + * reached, and hu is the last internal step size successfully + * used by the solver. The user may request k=0, 1, ..., qu, + * where qu is the current order. + * The is-th sensitivity derivative vector is returned in dky. + * This vector must be allocated by the caller. It is only legal + * to call this function after a successful return from CVode + * with sensitivty computations enabled. + * Arguments have the same meaning as in CVodeDky. + * + * CVodeGetSensDky computes the k-th derivative of all + * sensitivities of the y function at time t. It repeatedly calls + * CVodeGetSensDky. The argument dkyA must be a pointer to + * N_Vector and must be allocated by the user to hold at least Ns + * vectors. + * + * Return values are similar to those of CVodeDky. Additionally, + * CVodeSensDky can return CV_NO_SENS if sensitivities were + * not computed and CV_BAD_IS if is < 0 or is >= Ns. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetSens(void *cvode_mem, realtype *tret, N_Vector *ySout); +SUNDIALS_EXPORT int CVodeGetSens1(void *cvode_mem, realtype *tret, int is, N_Vector ySout); + +SUNDIALS_EXPORT int CVodeGetSensDky(void *cvode_mem, realtype t, int k, N_Vector *dkyA); +SUNDIALS_EXPORT int CVodeGetSensDky1(void *cvode_mem, realtype t, int k, int is, N_Vector dky); + +/* + * ----------------------------------------------------------------- + * Quadrature sensitivity solution extraction routines + * ----------------------------------------------------------------- + * The following functions can be called to obtain the quadrature + * sensitivity variables after a successful integration step. + * + * CVodeGetQuadSens and CVodeGetQuadSens1 return all the quadrature + * sensitivity vectors or only one of them, respectively, at the + * same time as that at which CVode returned the solution. + * The array of output vectors or output vector yQSout must be + * allocated by the user. + * + * CVodeGetQuadSensDky1 computes the kth derivative of the is-th + * quadrature sensitivity (is=1, 2, ..., Ns) at time t, where + * tn-hu <= t <= tn, tn denotes the current internal time + * reached, and hu is the last internal step size successfully + * used by the solver. The user may request k=0, 1, ..., qu, + * where qu is the current order. + * The is-th sensitivity derivative vector is returned in dkyQS. + * This vector must be allocated by the caller. It is only legal + * to call this function after a successful return from CVode + * with quadrature sensitivty computations enabled. + * Arguments have the same meaning as in CVodeDky. + * + * CVodeGetQuadSensDky computes the k-th derivative of all + * quadrature sensitivities at time t. It repeatedly calls + * CVodeGetSensDky. The argument dkyQS_all must be a pointer to + * N_Vector and must be allocated by the user to hold at least Ns + * vectors. + * + * Return values are similar to those of CVodeDky. Additionally, + * CVodeQuadSensDky can return CV_NO_QUADSENS if quadrature + * sensitivities were not computed and CV_BAD_IS if is < 0 or is >= Ns. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetQuadSens(void *cvode_mem, realtype *tret, N_Vector *yQSout); +SUNDIALS_EXPORT int CVodeGetQuadSens1(void *cvode_mem, realtype *tret, int is, N_Vector yQSout); + +SUNDIALS_EXPORT int CVodeGetQuadSensDky(void *cvode_mem, realtype t, int k, N_Vector *dkyQS_all); +SUNDIALS_EXPORT int CVodeGetQuadSensDky1(void *cvode_mem, realtype t, int k, int is, N_Vector dkyQS); + +/* + * ================================================================= + * + * OPTIONAL OUTPUT FUNCTIONS FOR FORWARD PROBLEMS + * + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Integrator optional output extraction functions + * ----------------------------------------------------------------- + * The following functions can be called to get optional outputs + * and statistics related to the main integrator. + * ----------------------------------------------------------------- + * CVodeGetWorkSpace returns the CVODES real and integer workspaces + * CVodeGetNumSteps returns the cumulative number of internal + * steps taken by the solver + * CVodeGetNumRhsEvals returns the number of calls to the user's + * f function + * CVodeGetNumLinSolvSetups returns the number of calls made to + * the linear solver's setup routine + * CVodeGetNumErrTestFails returns the number of local error test + * failures that have occured + * CVodeGetLastOrder returns the order used during the last + * internal step + * CVodeGetCurrentOrder returns the order to be used on the next + * internal step + * CVodeGetNumStabLimOrderReds returns the number of order + * reductions due to stability limit detection + * CVodeGetActualInitStep returns the actual initial step size + * used by CVODES + * CVodeGetLastStep returns the step size for the last internal + * step + * CVodeGetCurrentStep returns the step size to be attempted on + * the next internal step + * CVodeGetCurrentTime returns the current internal time reached + * by the solver + * CVodeGetTolScaleFactor returns a suggested factor by which the + * user's tolerances should be scaled when too + * much accuracy has been requested for some + * internal step + * CVodeGetErrWeights returns the current error weight vector. + * The user must allocate space for eweight. + * CVodeGetEstLocalErrors returns the vector of estimated local + * errors. The user must allocate space for ele. + * CVodeGetNumGEvals returns the number of calls to the user's + * g function (for rootfinding) + * CVodeGetRootInfo returns the indices for which g_i was found to + * have a root. The user must allocate space for + * rootsfound. For i = 0 ... nrtfn-1, + * rootsfound[i] = 1 if g_i has a root, and = 0 if not. + * + * CVodeGet* return values: + * CV_SUCCESS if succesful + * CV_MEM_NULL if the cvode memory was NULL + * CV_NO_SLDET if stability limit was not turned on + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetWorkSpace(void *cvode_mem, long int *lenrw, long int *leniw); +SUNDIALS_EXPORT int CVodeGetNumSteps(void *cvode_mem, long int *nsteps); +SUNDIALS_EXPORT int CVodeGetNumRhsEvals(void *cvode_mem, long int *nfevals); +SUNDIALS_EXPORT int CVodeGetNumLinSolvSetups(void *cvode_mem, long int *nlinsetups); +SUNDIALS_EXPORT int CVodeGetNumErrTestFails(void *cvode_mem, long int *netfails); +SUNDIALS_EXPORT int CVodeGetLastOrder(void *cvode_mem, int *qlast); +SUNDIALS_EXPORT int CVodeGetCurrentOrder(void *cvode_mem, int *qcur); +SUNDIALS_EXPORT int CVodeGetNumStabLimOrderReds(void *cvode_mem, long int *nslred); +SUNDIALS_EXPORT int CVodeGetActualInitStep(void *cvode_mem, realtype *hinused); +SUNDIALS_EXPORT int CVodeGetLastStep(void *cvode_mem, realtype *hlast); +SUNDIALS_EXPORT int CVodeGetCurrentStep(void *cvode_mem, realtype *hcur); +SUNDIALS_EXPORT int CVodeGetCurrentTime(void *cvode_mem, realtype *tcur); +SUNDIALS_EXPORT int CVodeGetTolScaleFactor(void *cvode_mem, realtype *tolsfac); +SUNDIALS_EXPORT int CVodeGetErrWeights(void *cvode_mem, N_Vector eweight); +SUNDIALS_EXPORT int CVodeGetEstLocalErrors(void *cvode_mem, N_Vector ele); +SUNDIALS_EXPORT int CVodeGetNumGEvals(void *cvode_mem, long int *ngevals); +SUNDIALS_EXPORT int CVodeGetRootInfo(void *cvode_mem, int *rootsfound); + +/* + * ----------------------------------------------------------------- + * As a convenience, the following functions provides the + * optional outputs in one group. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetIntegratorStats(void *cvode_mem, long int *nsteps, + long int *nfevals, long int *nlinsetups, + long int *netfails, int *qlast, + int *qcur, realtype *hinused, realtype *hlast, + realtype *hcur, realtype *tcur); + +/* + * ----------------------------------------------------------------- + * Nonlinear solver optional output extraction functions + * ----------------------------------------------------------------- + * The following functions can be called to get optional outputs + * and statistics related to the nonlinear solver. + * ----------------------------------------------------------------- + * CVodeGetNumNonlinSolvIters returns the number of nonlinear + * solver iterations performed. + * CVodeGetNumNonlinSolvConvFails returns the number of nonlinear + * convergence failures. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetNumNonlinSolvIters(void *cvode_mem, long int *nniters); +SUNDIALS_EXPORT int CVodeGetNumNonlinSolvConvFails(void *cvode_mem, long int *nncfails); + +/* + * ----------------------------------------------------------------- + * As a convenience, the following function provides the + * nonlinear solver optional outputs in a group. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetNonlinSolvStats(void *cvode_mem, long int *nniters, + long int *nncfails); + + +/* + * ----------------------------------------------------------------- + * The following function returns the name of the constant + * associated with a CVODES return flag + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT char *CVodeGetReturnFlagName(int flag); + +/* + * ----------------------------------------------------------------- + * Quadrature integration optional output extraction routines + * ----------------------------------------------------------------- + * The following functions can be called to get optional outputs + * and statistics related to the integration of quadratures. + * ----------------------------------------------------------------- + * CVodeGetQuadNumRhsEvals returns the number of calls to the + * user function fQ defining the right hand + * side of the quadrature variables. + * CVodeGetQuadNumErrTestFails returns the number of local error + * test failures for quadrature variables. + * CVodeGetQuadErrWeights returns the vector of error weights for + * the quadrature variables. The user must + * allocate space for ewtQ. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetQuadNumRhsEvals(void *cvode_mem, long int *nfQevals); +SUNDIALS_EXPORT int CVodeGetQuadNumErrTestFails(void *cvode_mem, long int *nQetfails); +SUNDIALS_EXPORT int CVodeGetQuadErrWeights(void *cvode_mem, N_Vector eQweight); + +/* + * ----------------------------------------------------------------- + * As a convenience, the following function provides the above + * optional outputs in a group. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetQuadStats(void *cvode_mem, long int *nfQevals, + long int *nQetfails); + +/* + * ----------------------------------------------------------------- + * Forward sensitivity optional output extraction routines + * ----------------------------------------------------------------- + * The following functions can be called to get optional outputs + * and statistics related to the integration of sensitivities. + * ----------------------------------------------------------------- + * CVodeGetSensNumRhsEvals returns the number of calls to the + * sensitivity right hand side routine. + * CVodeGetNumRhsEvalsSens returns the number of calls to the + * user f routine due to finite difference evaluations of the + * sensitivity equations. + * CVodeGetSensNumErrTestFails returns the number of local error + * test failures for sensitivity variables. + * CVodeGetSensNumLinSolvSetups returns the number of calls made + * to the linear solver's setup routine due to sensitivity computations. + * CVodeGetSensErrWeights returns the sensitivity error weight + * vectors. The user need not allocate space for ewtS. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetSensNumRhsEvals(void *cvode_mem, long int *nfSevals); +SUNDIALS_EXPORT int CVodeGetNumRhsEvalsSens(void *cvode_mem, long int *nfevalsS); +SUNDIALS_EXPORT int CVodeGetSensNumErrTestFails(void *cvode_mem, long int *nSetfails); +SUNDIALS_EXPORT int CVodeGetSensNumLinSolvSetups(void *cvode_mem, long int *nlinsetupsS); +SUNDIALS_EXPORT int CVodeGetSensErrWeights(void *cvode_mem, N_Vector *eSweight); + +/* + * ----------------------------------------------------------------- + * As a convenience, the following function provides the + * optional outputs in a group. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetSensStats(void *cvode_mem, long int *nfSevals, long int *nfevalsS, + long int *nSetfails, long int *nlinsetupsS); + +/* + * ----------------------------------------------------------------- + * Sensitivity nonlinear solver optional output extraction + * ----------------------------------------------------------------- + * The following functions can be called to get optional outputs + * and statistics related to the sensitivity nonlinear solver. + * ----------------------------------------------------------------- + * CVodeGetSensNumNonlinSolvIters returns the total number of + * nonlinear iterations for sensitivity variables. + * CVodeGetSensNumNonlinSolvConvFails returns the total number + * of nonlinear convergence failures for sensitivity variables + * CVodeGetStgrSensNumNonlinSolvIters returns a vector of Ns + * nonlinear iteration counters for sensitivity variables in + * the CV_STAGGERED1 method. + * CVodeGetStgrSensNumNonlinSolvConvFails returns a vector of Ns + * nonlinear solver convergence failure counters for sensitivity + * variables in the CV_STAGGERED1 method. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetSensNumNonlinSolvIters(void *cvode_mem, long int *nSniters); +SUNDIALS_EXPORT int CVodeGetSensNumNonlinSolvConvFails(void *cvode_mem, long int *nSncfails); +SUNDIALS_EXPORT int CVodeGetStgrSensNumNonlinSolvIters(void *cvode_mem, long int *nSTGR1niters); +SUNDIALS_EXPORT int CVodeGetStgrSensNumNonlinSolvConvFails(void *cvode_mem, + long int *nSTGR1ncfails); + +/* + * ----------------------------------------------------------------- + * As a convenience, the following function provides the + * optional outputs in groups. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetSensNonlinSolvStats(void *cvode_mem, long int *nSniters, + long int *nSncfails); + + +/* + * ----------------------------------------------------------------- + * Quadrature sensitivity optional output extraction routines + * ----------------------------------------------------------------- + * The following functions can be called to get optional outputs and + * statistics related to the integration of quadrature sensitivitiess. + * ----------------------------------------------------------------- + * CVodeGetQuadSensNumRhsEvals returns the number of calls to the + * user function fQS defining the right hand side of the + * quadrature sensitivity equations. + * CVodeGetQuadSensNumErrTestFails returns the number of local error + * test failures for quadrature sensitivity variables. + * CVodeGetQuadSensErrWeights returns the vector of error weights + * for the quadrature sensitivity variables. The user must + * allocate space for ewtQS. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetQuadSensNumRhsEvals(void *cvode_mem, long int *nfQSevals); +SUNDIALS_EXPORT int CVodeGetQuadSensNumErrTestFails(void *cvode_mem, long int *nQSetfails); +SUNDIALS_EXPORT int CVodeGetQuadSensErrWeights(void *cvode_mem, N_Vector *eQSweight); + +/* + * ----------------------------------------------------------------- + * As a convenience, the following function provides the above + * optional outputs in a group. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetQuadSensStats(void *cvode_mem, + long int *nfQSevals, + long int *nQSetfails); + + +/* + * ================================================================= + * + * INITIALIZATION AND DEALLOCATION FUNCTIONS FOR BACKWARD PROBLEMS + * + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * CVodeAdjInit + * ----------------------------------------------------------------- + * CVodeAdjInit specifies some parameters for ASA, initializes ASA + * and allocates space for the adjoint memory structure. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeAdjInit(void *cvode_mem, long int steps, int interp); + +/* + * ----------------------------------------------------------------- + * CVodeAdjReInit + * ----------------------------------------------------------------- + * CVodeAdjReInit reinitializes the CVODES memory structure for ASA, + * assuming that the number of steps between check points and the + * type of interpolation remained unchanged. The list of check points + * (and associated memory) is deleted. The list of backward problems + * is kept (however, new backward problems can be added to this list + * by calling CVodeCreateB). The CVODES memory for the forward and + * backward problems can be reinitialized separately by calling + * CVodeReInit and CVodeReInitB, respectively. + * NOTE: if a entirely new list of backward problems is desired, + * then simply free the adjoint memory (by calling CVodeAdjFree) + * and reinitialize ASA with CVodeAdjInit. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeAdjReInit(void *cvode_mem); + +/* + * ----------------------------------------------------------------- + * CVodeAdjFree + * ----------------------------------------------------------------- + * CVodeAdjFree frees the memory allocated by CVodeAdjInit. + * It is typically called by CVodeFree. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void CVodeAdjFree(void *cvode_mem); + + +/* + * ----------------------------------------------------------------- + * Interfaces to CVODES functions for setting-up backward problems. + * ----------------------------------------------------------------- + * CVodeCreateB, + * + * CVodeInitB, CVodeInitBS, CVodeReInitB + * + * CVodeQuadInitB, CVodeQuadInitBS, CVodeQuadReInitB + * + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeCreateB(void *cvode_mem, int lmmB, int iterB, int *which); + +SUNDIALS_EXPORT int CVodeInitB(void *cvode_mem, int which, + CVRhsFnB fB, + realtype tB0, N_Vector yB0); +SUNDIALS_EXPORT int CVodeInitBS(void *cvode_mem, int which, + CVRhsFnBS fBs, + realtype tB0, N_Vector yB0); +SUNDIALS_EXPORT int CVodeReInitB(void *cvode_mem, int which, + realtype tB0, N_Vector yB0); + +SUNDIALS_EXPORT int CVodeSStolerancesB(void *cvode_mem, int which, + realtype reltolB, realtype abstolB); +SUNDIALS_EXPORT int CVodeSVtolerancesB(void *cvode_mem, int which, + realtype reltolB, N_Vector abstolB); + +SUNDIALS_EXPORT int CVodeQuadInitB(void *cvode_mem, int which, + CVQuadRhsFnB fQB, N_Vector yQB0); +SUNDIALS_EXPORT int CVodeQuadInitBS(void *cvode_mem, int which, + CVQuadRhsFnBS fQBs, N_Vector yQB0); +SUNDIALS_EXPORT int CVodeQuadReInitB(void *cvode_mem, int which, N_Vector yQB0); + +SUNDIALS_EXPORT int CVodeQuadSStolerancesB(void *cvode_mem, int which, + realtype reltolQB, realtype abstolQB); +SUNDIALS_EXPORT int CVodeQuadSVtolerancesB(void *cvode_mem, int which, + realtype reltolQB, N_Vector abstolQB); + +/* + * ================================================================= + * + * MAIN SOLVER FUNCTIONS FOR FORWARD PROBLEMS + * + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * CVodeF + * ----------------------------------------------------------------- + * CVodeF integrates towards tout and returns solution into yout. + * In the same time, it stores check point data every 'steps'. + * + * CVodeF can be called repeatedly by the user. + * + * ncheckPtr points to the number of check points stored so far. + * + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeF(void *cvode_mem, realtype tout, N_Vector yout, + realtype *tret, int itask, int *ncheckPtr); + + +/* + * ----------------------------------------------------------------- + * CVodeB + * ----------------------------------------------------------------- + * CVodeB performs the integration of all backward problems specified + * through calls to CVodeCreateB through a sequence of forward-backward + * runs in between consecutive check points. CVodeB can be called + * either in CV_NORMAL or CV_ONE_STEP mode. After a successful return + * from CVodeB, the solution and quadrature variables at the current + * return time for any given backward problem can be obtained by + * calling CVodeGetB and CVodeGetQuadB, respectively. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeB(void *cvode_mem, realtype tBout, int itaskB); + +/* + * ================================================================= + * + * OPTIONAL INPUT FUNCTIONS FOR BACKWARD PROBLEMS + * + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * CVodeSetAdjNoSensi + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeSetAdjNoSensi(void *cvode_mem); + +/* + * ----------------------------------------------------------------- + * Optional input functions for backward problems + * ----------------------------------------------------------------- + * These functions are just wrappers around the corresponding + * functions in cvodes.h, with some particularizations for the + * backward integration. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeSetIterTypeB(void *cvode_mem, int which, int iterB); +SUNDIALS_EXPORT int CVodeSetUserDataB(void *cvode_mem, int which, void *user_dataB); +SUNDIALS_EXPORT int CVodeSetMaxOrdB(void *cvode_mem, int which, int maxordB); +SUNDIALS_EXPORT int CVodeSetMaxNumStepsB(void *cvode_mem, int which, long int mxstepsB); +SUNDIALS_EXPORT int CVodeSetStabLimDetB(void *cvode_mem, int which, booleantype stldetB); +SUNDIALS_EXPORT int CVodeSetInitStepB(void *cvode_mem, int which, realtype hinB); +SUNDIALS_EXPORT int CVodeSetMinStepB(void *cvode_mem, int which, realtype hminB); +SUNDIALS_EXPORT int CVodeSetMaxStepB(void *cvode_mem, int which, realtype hmaxB); + +SUNDIALS_EXPORT int CVodeSetQuadErrConB(void *cvode_mem, int which, booleantype errconQB); + +/* + * ================================================================= + * + * EXTRACTION AND DENSE OUTPUT FUNCTIONS FOR BACKWARD PROBLEMS + * + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * CVodeGetB and CVodeGetQuadB + * ----------------------------------------------------------------- + * Extraction functions for the solution and quadratures for a given + * backward problem. They return their corresponding output vector + * at the current time reached by the integration of the backward + * problem. To obtain the solution or quadratures associated with + * a given backward problem at some other time within the last + * integration step (dense output), first obtain a pointer to the + * proper CVODES memory by calling CVodeGetAdjCVodeBmem and then use it + * to call CVodeGetDky and CVodeGetQuadDky. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetB(void *cvode_mem, int which, + realtype *tBret, N_Vector yB); +SUNDIALS_EXPORT int CVodeGetQuadB(void *cvode_mem, int which, + realtype *tBret, N_Vector qB); + + +/* + * ================================================================= + * + * OPTIONAL OUTPUT FUNCTIONS FOR BACKWARD PROBLEMS + * + * ================================================================= + */ + + +/* + * ----------------------------------------------------------------- + * CVodeGetAdjCVodeBmem + * ----------------------------------------------------------------- + * CVodeGetAdjCVodeBmem returns a (void *) pointer to the CVODES + * memory allocated for the backward problem. This pointer can + * then be used to call any of the CVodeGet* CVODES routines to + * extract optional output for the backward integration phase. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void *CVodeGetAdjCVodeBmem(void *cvode_mem, int which); + + +/* + * ----------------------------------------------------------------- + * CVodeGetAdjY + * Returns the interpolated forward solution at time t. This + * function is a wrapper around the interpType-dependent internal + * function. + * The calling function must allocate space for y. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetAdjY(void *cvode_mem, realtype t, N_Vector y); + +/* + * ----------------------------------------------------------------- + * CVodeGetAdjCheckPointsInfo + * Loads an array of nckpnts structures of type CVadjCheckPointRec. + * The user must allocate space for ckpnt (ncheck+1). + * ----------------------------------------------------------------- + */ + +typedef struct { + void *my_addr; + void *next_addr; + realtype t0; + realtype t1; + long int nstep; + int order; + realtype step; +} CVadjCheckPointRec; + +SUNDIALS_EXPORT int CVodeGetAdjCheckPointsInfo(void *cvode_mem, CVadjCheckPointRec *ckpnt); + +/* + * ----------------------------------------------------------------- + * CVodeGetAdjDataPointHermite + * Returns the 2 vectors stored for cubic Hermite interpolation + * at the data point 'which'. The user must allocate space for + * y and yd. Returns CV_MEM_NULL if cvode_mem is NULL. + * Returns CV_ILL_INPUT if interpType != CV_HERMITE. + * CVodeGetAdjDataPointPolynomial + * Returns the vector stored for polynomial interpolation + * at the data point 'which'. The user must allocate space for + * y. Returns CV_MEM_NULL if cvode_mem is NULL. + * Returns CV_ILL_INPUT if interpType != CV_POLYNOMIAL. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetAdjDataPointHermite(void *cvode_mem, long int which, + realtype *t, N_Vector y, N_Vector yd); + +SUNDIALS_EXPORT int CVodeGetAdjDataPointPolynomial(void *cvode_mem, long int which, + realtype *t, int *order, N_Vector y); + +/* + * ----------------------------------------------------------------- + * CVodeGetAdjCurrentCheckPoint + * Returns the address of the 'active' check point. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetAdjCurrentCheckPoint(void *cvode_mem, void **addr); + + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_band.h b/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_band.h new file mode 100644 index 0000000..fc3ce44 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_band.h @@ -0,0 +1,72 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.7 $ + * $Date: 2008/04/18 19:42:36 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the band linear solver CSVBAND. + * ----------------------------------------------------------------- + */ + +#ifndef _CVSBAND_H +#define _CVSBAND_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * Function : CVBand + * ----------------------------------------------------------------- + * A call to the CVBand function links the main CVODE integrator + * with the CVSBAND linear solver. + * + * cvode_mem is the pointer to the integrator memory returned by + * CVodeCreate. + * + * N is the size of the ODE system. + * + * mupper is the upper bandwidth of the band Jacobian + * approximation. + * + * mlower is the lower bandwidth of the band Jacobian + * approximation. + * + * The return value of CVBand is one of: + * CVDLS_SUCCESS if successful + * CVDLS_MEM_NULL if the cvode memory was NULL + * CVDLS_MEM_FAIL if there was a memory allocation failure + * CVDLS_ILL_INPUT if a required vector operation is missing or + * if a bandwidth has an illegal value. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVBand(void *cvode_mem, int N, int mupper, int mlower); + +/* + * ----------------------------------------------------------------- + * Function: CVBandB + * ----------------------------------------------------------------- + * CVBandB links the main CVODE integrator with the CVSBAND + * linear solver for the backward integration. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVBandB(void *cvode_mem, int which, + int nB, int mupperB, int mlowerB); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_bandpre.h b/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_bandpre.h new file mode 100644 index 0000000..966fdc3 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_bandpre.h @@ -0,0 +1,179 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.7 $ + * $Date: 2007/11/26 16:19:58 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the CVSBANDPRE module, which + * provides a banded difference quotient Jacobian-based + * preconditioner and solver routines for use with CVSPGMR, + * CVSPBCG, or CVSPTFQMR. + * + * Part I contains type definitions and function prototypes for using + * CVSBANDPRE on forward problems (IVP integration and/or FSA) + * + * Part II contains type definitions and function prototypes for using + * CVSBANDPRE on adjopint (backward) problems + * ----------------------------------------------------------------- + */ + +#ifndef _CVSBANDPRE_H +#define _CVSBANDPRE_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ================================================================= + * PART I - forward problems + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * + * SUMMARY + * + * These routines provide a band matrix preconditioner based on + * difference quotients of the ODE right-hand side function f. + * The user supplies parameters + * mu = upper half-bandwidth (number of super-diagonals) + * ml = lower half-bandwidth (number of sub-diagonals) + * The routines generate a band matrix of bandwidth ml + mu + 1 + * and use this to form a preconditioner for use with the Krylov + * linear solver in CVSP*. Although this matrix is intended to + * approximate the Jacobian df/dy, it may be a very crude + * approximation. The true Jacobian need not be banded, or its + * true bandwith may be larger than ml + mu + 1, as long as the + * banded approximation generated here is sufficiently accurate + * to speed convergence as a preconditioner. + * + * Usage: + * The following is a summary of the usage of this module. + * Details of the calls to CVodeCreate, CVodeMalloc, CVSp*, + * and CVode are available in the User Guide. + * To use these routines, the sequence of calls in the user + * main program should be as follows: + * + * #include + * #include + * ... + * Set y0 + * ... + * cvode_mem = CVodeCreate(...); + * ier = CVodeMalloc(...); + * ... + * flag = CVSptfqmr(cvode_mem, pretype, maxl); + * -or- + * flag = CVSpgmr(cvode_mem, pretype, maxl); + * -or- + * flag = CVSpbcg(cvode_mem, pretype, maxl); + * ... + * flag = CVBandPrecInit(cvode_mem, N, mu, ml); + * ... + * flag = CVode(...); + * ... + * Free y0 + * ... + * CVodeFree(&cvode_mem); + * + * Notes: + * (1) Include this file for the CVBandPrecData type definition. + * (2) In the CVBandPrecInit call, the arguments N is the + * problem dimension. + * (3) In the CVBPSp* call, the user is free to specify + * the input pretype and the optional input maxl. + * ----------------------------------------------------------------- + */ + + +/* + * ----------------------------------------------------------------- + * Function : CVBandPrecInit + * ----------------------------------------------------------------- + * CVBandPrecInit allocates and initializes the BANDPRE preconditioner + * module. This functino must be called AFTER one of the SPILS linear + * solver modules has been attached to the CVODE integrator. + * + * The parameters of CVBandPrecInit are as follows: + * + * cvode_mem is the pointer to CVODE memory returned by CVodeCreate. + * + * N is the problem size. + * + * mu is the upper half bandwidth. + * + * ml is the lower half bandwidth. + * + * The return value of CVBandPrecInit is one of: + * CVSPILS_SUCCESS if no errors occurred + * CVSPILS_MEM_NULL if the integrator memory is NULL + * CVSPILS_LMEM_NULL if the linear solver memory is NULL + * CVSPILS_ILL_INPUT if an input has an illegal value + * CVSPILS_MEM_FAIL if a memory allocation request failed + * + * NOTE: The band preconditioner assumes a serial implementation + * of the NVECTOR package. Therefore, CVBandPrecInit will + * first test for a compatible N_Vector internal + * representation by checking for required functions. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVBandPrecInit(void *cvode_mem, int N, int mu, int ml); + +/* + * ----------------------------------------------------------------- + * Optional output functions : CVBandPrecGet* + * ----------------------------------------------------------------- + * CVBandPrecGetWorkSpace returns the real and integer work space used + * by CVBANDPRE. + * CVBandPrecGetNumRhsEvals returns the number of calls made from + * CVBANDPRE to the user's right-hand side + * routine f. + * + * The return value of CVBandPrecGet* is one of: + * CVSPILS_SUCCESS if no errors occurred + * CVSPILS_MEM_NULL if the integrator memory is NULL + * CVSPILS_LMEM_NULL if the linear solver memory is NULL + * CVSPILS_PMEM_NULL if the preconditioner memory is NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVBandPrecGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS); +SUNDIALS_EXPORT int CVBandPrecGetNumRhsEvals(void *cvode_mem, long int *nfevalsBP); + +/* + * ================================================================= + * PART II - backward problems + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Functions: CVBandPrecInitB, CVBPSp*B + * ----------------------------------------------------------------- + * Interface functions for the CVBANDPRE preconditioner to be used + * on the backward phase. + * + * CVBandPrecInitB interfaces to the CVBANDPRE preconditioner + * for the backward integration. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVBandPrecInitB(void *cvode_mem, int which, + int nB, int muB, int mlB); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_bbdpre.h b/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_bbdpre.h new file mode 100644 index 0000000..5792794 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_bbdpre.h @@ -0,0 +1,331 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.10 $ + * $Date: 2007/11/26 16:19:58 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the CVBBDPRE module, for a + * band-block-diagonal preconditioner, i.e. a block-diagonal + * matrix with banded blocks, for use with CVSPGMR/CVSPBCG/CVSPTFQMR, + * and the parallel implementation of the NVECTOR module. + * + * + * Part I contains type definitions and function prototypes for using + * CVBBDPRE on forward problems (IVP integration and/or FSA) + * + * Part II contains type definitions and function prototypes for using + * CVBBDPRE on adjopint (backward) problems + * ----------------------------------------------------------------- + */ + +#ifndef _CVSBBDPRE_H +#define _CVSBBDPRE_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ================================================================= + * PART I - forward problems + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * + * SUMMARY + * + * These routines provide a preconditioner matrix that is + * block-diagonal with banded blocks. The blocking corresponds + * to the distribution of the dependent variable vector y among + * the processors. Each preconditioner block is generated from + * the Jacobian of the local part (on the current processor) of a + * given function g(t,y) approximating f(t,y). The blocks are + * generated by a difference quotient scheme on each processor + * independently. This scheme utilizes an assumed banded + * structure with given half-bandwidths, mudq and mldq. + * However, the banded Jacobian block kept by the scheme has + * half-bandwiths mukeep and mlkeep, which may be smaller. + * + * The user's calling program should have the following form: + * + * #include + * #include + * ... + * void *cvode_mem; + * ... + * Set y0 + * ... + * cvode_mem = CVodeCreate(...); + * ier = CVodeMalloc(...); + * ... + * flag = CVSpgmr(cvode_mem, pretype, maxl); + * -or- + * flag = CVSpbcg(cvode_mem, pretype, maxl); + * -or- + * flag = CVSptfqmr(cvode_mem, pretype, maxl); + * ... + * flag = CVBBDPrecInit(cvode_mem, Nlocal, mudq ,mldq, + * mukeep, mlkeep, dqrely, gloc, cfn); + * ... + * ier = CVode(...); + * ... + * CVodeFree(&cvode_mem); + * + * Free y0 + * + * The user-supplied routines required are: + * + * f = function defining the ODE right-hand side f(t,y). + * + * gloc = function defining the approximation g(t,y). + * + * cfn = function to perform communication need for gloc. + * + * Notes: + * + * 1) This header file is included by the user for the definition + * of the CVBBDData type and for needed function prototypes. + * + * 2) The CVBBDPrecInit call includes half-bandwiths mudq and mldq + * to be used in the difference quotient calculation of the + * approximate Jacobian. They need not be the true + * half-bandwidths of the Jacobian of the local block of g, + * when smaller values may provide a greater efficiency. + * Also, the half-bandwidths mukeep and mlkeep of the retained + * banded approximate Jacobian block may be even smaller, + * to reduce storage and computation costs further. + * For all four half-bandwidths, the values need not be the + * same on every processor. + * + * 3) The actual name of the user's f function is passed to + * CVodeInit, and the names of the user's gloc and cfn + * functions are passed to CVBBDPrecInit. + * + * 4) The pointer to the user-defined data block user_data, which is + * set through CVodeSetUserData is also available to the user in + * gloc and cfn. + * + * 5) Optional outputs specific to this module are available by + * way of routines listed below. These include work space sizes + * and the cumulative number of gloc calls. The costs + * associated with this module also include nsetups banded LU + * factorizations, nlinsetups cfn calls, and npsolves banded + * backsolve calls, where nlinsetups and npsolves are + * integrator/CVSPGMR/CVSPBCG/CVSPTFQMR optional outputs. + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Type : CVLocalFn + * ----------------------------------------------------------------- + * The user must supply a function g(t,y) which approximates the + * right-hand side function f for the system y'=f(t,y), and which + * is computed locally (without interprocess communication). + * (The case where g is mathematically identical to f is allowed.) + * The implementation of this function must have type CVLocalFn. + * + * This function takes as input the local vector size Nlocal, the + * independent variable value t, the local real dependent + * variable vector y, and a pointer to the user-defined data + * block user_data. It is to compute the local part of g(t,y) and + * store this in the vector g. + * (Allocation of memory for y and g is handled within the + * preconditioner module.) + * The user_data parameter is the same as that specified by the user + * through the CVodeSetFdata routine. + * + * A CVLocalFn should return 0 if successful, a positive value if + * a recoverable error occurred, and a negative value if an + * unrecoverable error occurred. + * ----------------------------------------------------------------- + */ + +typedef int (*CVLocalFn)(int Nlocal, realtype t, + N_Vector y, N_Vector g, void *user_data); + +/* + * ----------------------------------------------------------------- + * Type : CVCommFn + * ----------------------------------------------------------------- + * The user may supply a function of type CVCommFn which performs + * all interprocess communication necessary to evaluate the + * approximate right-hand side function described above. + * + * This function takes as input the local vector size Nlocal, + * the independent variable value t, the dependent variable + * vector y, and a pointer to the user-defined data block user_data. + * The user_data parameter is the same as that specified by the user + * through the CVodeSetUserData routine. The CVCommFn cfn is + * expected to save communicated data in space defined within the + * structure user_data. Note: A CVCommFn cfn does not have a return value. + * + * Each call to the CVCommFn cfn is preceded by a call to the + * CVRhsFn f with the same (t,y) arguments. Thus cfn can omit any + * communications done by f if relevant to the evaluation of g. + * If all necessary communication was done by f, the user can + * pass NULL for cfn in CVBBDPrecInit (see below). + * + * A CVCommFn should return 0 if successful, a positive value if + * a recoverable error occurred, and a negative value if an + * unrecoverable error occurred. + * ----------------------------------------------------------------- + */ + +typedef int (*CVCommFn)(int Nlocal, realtype t, + N_Vector y, + void *user_data); + +/* + * ----------------------------------------------------------------- + * Function : CVBBDPrecInit + * ----------------------------------------------------------------- + * CVBBDPrecInit allocates and initializes the BBD preconditioner. + * + * The parameters of CVBBDPrecInit are as follows: + * + * cvode_mem is the pointer to the integrator memory. + * + * Nlocal is the length of the local block of the vectors y etc. + * on the current processor. + * + * mudq, mldq are the upper and lower half-bandwidths to be used + * in the difference quotient computation of the local + * Jacobian block. + * + * mukeep, mlkeep are the upper and lower half-bandwidths of the + * retained banded approximation to the local Jacobian + * block. + * + * dqrely is an optional input. It is the relative increment + * in components of y used in the difference quotient + * approximations. To specify the default, pass 0. + * The default is dqrely = sqrt(unit roundoff). + * + * gloc is the name of the user-supplied function g(t,y) that + * approximates f and whose local Jacobian blocks are + * to form the preconditioner. + * + * cfn is the name of the user-defined function that performs + * necessary interprocess communication for the + * execution of gloc. + * + * The return value of CVBBDPrecInit is one of: + * CVSPILS_SUCCESS if no errors occurred + * CVSPILS_MEM_NULL if the integrator memory is NULL + * CVSPILS_LMEM_NULL if the linear solver memory is NULL + * CVSPILS_ILL_INPUT if an input has an illegal value + * CVSPILS_MEM_FAIL if a memory allocation request failed + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVBBDPrecInit(void *cvode_mem, int Nlocal, + int mudq, int mldq, + int mukeep, int mlkeep, + realtype dqrely, + CVLocalFn gloc, CVCommFn cfn); + +/* + * ----------------------------------------------------------------- + * Function : CVBBDPrecReInit + * ----------------------------------------------------------------- + * CVBBDPrecReInit re-initializes the BBDPRE module when solving a + * sequence of problems of the same size with CVSPGMR/CVBBDPRE, + * CVSPBCG/CVBBDPRE, or CVSPTFQMR/CVBBDPRE provided there is no change + * in Nlocal, mukeep, or mlkeep. After solving one problem, and after + * calling CVodeReInit to re-initialize the integrator for a subsequent + * problem, call CVBBDPrecReInit. + * + * All arguments have the same names and meanings as those + * of CVBBDPrecInit. + * + * The return value of CVBBDPrecReInit is one of: + * CVSPILS_SUCCESS if no errors occurred + * CVSPILS_MEM_NULL if the integrator memory is NULL + * CVSPILS_LMEM_NULL if the linear solver memory is NULL + * CVSPILS_PMEM_NULL if the preconditioner memory is NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVBBDPrecReInit(void *cvode_mem, int mudq, int mldq, + realtype dqrely); + +/* + * ----------------------------------------------------------------- + * CVBBDPRE optional output extraction routines + * ----------------------------------------------------------------- + * CVBBDPrecGetWorkSpace returns the BBDPRE real and integer work space + * sizes. + * CVBBDPrecGetNumGfnEvals returns the number of calls to gfn. + * + * The return value of CVBBDPrecGet* is one of: + * CVSPILS_SUCCESS if no errors occurred + * CVSPILS_MEM_NULL if the integrator memory is NULL + * CVSPILS_LMEM_NULL if the linear solver memory is NULL + * CVSPILS_PMEM_NULL if the preconditioner memory is NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVBBDPrecGetWorkSpace(void *cvode_mem, + long int *lenrwBBDP, long int *leniwBBDP); +SUNDIALS_EXPORT int CVBBDPrecGetNumGfnEvals(void *cvode_mem, long int *ngevalsBBDP); + +/* + * ================================================================= + * PART II - backward problems + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Types: CVLocalFnB and CVCommFnB + * ----------------------------------------------------------------- + * Local approximation function and inter-process communication + * function for the BBD preconditioner on the backward phase. + * ----------------------------------------------------------------- + */ + +typedef int (*CVLocalFnB)(int NlocalB, realtype t, + N_Vector y, + N_Vector yB, N_Vector gB, + void *user_dataB); + +typedef int (*CVCommFnB)(int NlocalB, realtype t, + N_Vector y, + N_Vector yB, + void *user_dataB); + +/* + * ----------------------------------------------------------------- + * Functions: CVBBDPrecInitB, CVBBDSp*B, CVBBDPrecReInit + * ----------------------------------------------------------------- + * Interface functions for the CVBBDPRE preconditioner to be used on + * the backward phase. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVBBDPrecInitB(void *cvode_mem, int which, int NlocalB, + int mudqB, int mldqB, + int mukeepB, int mlkeepB, + realtype dqrelyB, + CVLocalFnB glocB, CVCommFnB cfnB); + +SUNDIALS_EXPORT int CVBBDPrecReInitB(void *cvode_mem, int which, + int mudqB, int mldqB, + realtype dqrelyB); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_dense.h b/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_dense.h new file mode 100644 index 0000000..59fe7f7 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_dense.h @@ -0,0 +1,64 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.7 $ + * $Date: 2008/04/18 19:42:36 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the dense linear solver CVSDENSE. + * ----------------------------------------------------------------- + */ + +#ifndef _CVSDENSE_H +#define _CVSDENSE_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * Function: CVDense + * ----------------------------------------------------------------- + * A call to the CVDense function links the main integrator with + * the CVSDENSE linear solver. + * + * cvode_mem is the pointer to the integrator memory returned by + * CVodeCreate. + * + * N is the size of the ODE system. + * + * The return value of CVDense is one of: + * CVDLS_SUCCESS if successful + * CVDLS_MEM_NULL if the cvode memory was NULL + * CVDLS_MEM_FAIL if there was a memory allocation failure + * CVDLS_ILL_INPUT if a required vector operation is missing + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVDense(void *cvode_mem, int N); + +/* + * ----------------------------------------------------------------- + * Function: CVDenseB + * ----------------------------------------------------------------- + * CVDenseB links the main CVODE integrator with the CVSDENSE + * linear solver for the backward integration. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVDenseB(void *cvode_mem, int which, int nB); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_diag.h b/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_diag.h new file mode 100644 index 0000000..00bf2a0 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_diag.h @@ -0,0 +1,140 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.5 $ + * $Date: 2007/03/22 18:05:50 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the diagonal linear solver CVSDIAG. + * + * + * Part I contains type definitions and function prototypes for using + * CVDIAG on forward problems (IVP integration and/or FSA) + * + * Part II contains type definitions and function prototypes for using + * CVDIAG on adjoint (backward) problems + * ----------------------------------------------------------------- + */ + +#ifndef _CVSDIAG_H +#define _CVSDIAG_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * CVDIAG return values + * ----------------------------------------------------------------- + */ + +#define CVDIAG_SUCCESS 0 +#define CVDIAG_MEM_NULL -1 +#define CVDIAG_LMEM_NULL -2 +#define CVDIAG_ILL_INPUT -3 +#define CVDIAG_MEM_FAIL -4 + +/* Additional last_flag values */ + +#define CVDIAG_INV_FAIL -5 +#define CVDIAG_RHSFUNC_UNRECVR -6 +#define CVDIAG_RHSFUNC_RECVR -7 + +/* Return values for adjoint module */ + +#define CVDIAG_NO_ADJ -101 + +/* + * ----------------------------------------------------------------- + * PART I - forward problems + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Function : CVDiag + * ----------------------------------------------------------------- + * A call to the CVDiag function links the main integrator with + * the CVDIAG linear solver. + * + * cvode_mem is the pointer to the integrator memory returned by + * CVodeCreate. + * + * The return value of CVDiag is one of: + * CVDIAG_SUCCESS if successful + * CVDIAG_MEM_NULL if the cvode memory was NULL + * CVDIAG_MEM_FAIL if there was a memory allocation failure + * CVDIAG_ILL_INPUT if a required vector operation is missing + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVDiag(void *cvode_mem); + +/* + * ----------------------------------------------------------------- + * Optional outputs from the CVDIAG linear solver + * ----------------------------------------------------------------- + * + * CVDiagGetWorkSpace returns the real and integer workspace used + * by CVDIAG. + * CVDiagGetNumRhsEvals returns the number of calls to the user + * f routine due to finite difference Jacobian + * evaluation. + * Note: The number of diagonal approximate + * Jacobians formed is equal to the number of + * CVDiagSetup calls. This number is available + * through CVodeGetNumLinSolvSetups. + * CVDiagGetLastFlag returns the last error flag set by any of + * the CVDIAG interface functions. + * + * The return value of CVDiagGet* is one of: + * CVDIAG_SUCCESS if successful + * CVDIAG_MEM_NULL if the cvode memory was NULL + * CVDIAG_LMEM_NULL if the cvdiag memory was NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVDiagGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS); +SUNDIALS_EXPORT int CVDiagGetNumRhsEvals(void *cvode_mem, long int *nfevalsLS); +SUNDIALS_EXPORT int CVDiagGetLastFlag(void *cvode_mem, int *flag); + +/* + * ----------------------------------------------------------------- + * The following function returns the name of the constant + * associated with a CVDIAG return flag + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT char *CVDiagGetReturnFlagName(int flag); + +/* + * ----------------------------------------------------------------- + * PART II - backward problems + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Function: CVDiagB + * ----------------------------------------------------------------- + * CVDiagB links the main CVODE integrator with the CVDIAG + * linear solver for the backward integration. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVDiagB(void *cvode_mem, int which); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_direct.h b/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_direct.h new file mode 100644 index 0000000..3c0366a --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_direct.h @@ -0,0 +1,366 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.7 $ + * $Date: 2008/04/18 19:42:37 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Common header file for the direct linear solvers in CVODES. + * + * Part I contains type definitions and function prototypes for + * using a CVDLS linear solver on forward problems (IVP + * integration and/or FSA) + * + * Part II contains type definitions and function prototypes for + * using a CVDLS linear solver on adjoint (backward) problems + * ----------------------------------------------------------------- + */ + +#ifndef _CVSDLS_H +#define _CVSDLS_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ================================================================= + * C V S D I R E C T C O N S T A N T S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * CVSDIRECT return values + * ----------------------------------------------------------------- + */ + +#define CVDLS_SUCCESS 0 +#define CVDLS_MEM_NULL -1 +#define CVDLS_LMEM_NULL -2 +#define CVDLS_ILL_INPUT -3 +#define CVDLS_MEM_FAIL -4 + +/* Additional last_flag values */ + +#define CVDLS_JACFUNC_UNRECVR -5 +#define CVDLS_JACFUNC_RECVR -6 + +/* Return values for the adjoint module */ + +#define CVDLS_NO_ADJ -101 +#define CVDLS_LMEMB_NULL -102 + +/* + * ================================================================= + * PART I: F O R W A R D P R O B L E M S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * FUNCTION TYPES + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Type: CVDlsDenseJacFn + * ----------------------------------------------------------------- + * + * A dense Jacobian approximation function Jac must be of type + * CVDlsDenseJacFn. Its parameters are: + * + * N is the problem size. + * + * Jac is the dense matrix (of type DlsMat) that will be loaded + * by a CVDlsDenseJacFn with an approximation to the Jacobian + * matrix J = (df_i/dy_j) at the point (t,y). + * + * t is the current value of the independent variable. + * + * y is the current value of the dependent variable vector, + * namely the predicted value of y(t). + * + * fy is the vector f(t,y). + * + * user_data is a pointer to user data - the same as the user_data + * parameter passed to CVodeSetFdata. + * + * tmp1, tmp2, and tmp3 are pointers to memory allocated for + * vectors of length N which can be used by a CVDlsDenseJacFn + * as temporary storage or work space. + * + * A CVDlsDenseJacFn should return 0 if successful, a positive + * value if a recoverable error occurred, and a negative value if + * an unrecoverable error occurred. + * + * ----------------------------------------------------------------- + * + * NOTE: The following are two efficient ways to load a dense Jac: + * (1) (with macros - no explicit data structure references) + * for (j=0; j < Neq; j++) { + * col_j = DENSE_COL(Jac,j); + * for (i=0; i < Neq; i++) { + * generate J_ij = the (i,j)th Jacobian element + * col_j[i] = J_ij; + * } + * } + * (2) (without macros - explicit data structure references) + * for (j=0; j < Neq; j++) { + * col_j = (Jac->data)[j]; + * for (i=0; i < Neq; i++) { + * generate J_ij = the (i,j)th Jacobian element + * col_j[i] = J_ij; + * } + * } + * A third way, using the DENSE_ELEM(A,i,j) macro, is much less + * efficient in general. It is only appropriate for use in small + * problems in which efficiency of access is NOT a major concern. + * + * NOTE: If the user's Jacobian routine needs other quantities, + * they are accessible as follows: hcur (the current stepsize) + * and ewt (the error weight vector) are accessible through + * CVodeGetCurrentStep and CVodeGetErrWeights, respectively + * (see cvode.h). The unit roundoff is available as + * UNIT_ROUNDOFF defined in sundials_types.h. + * + * ----------------------------------------------------------------- + */ + + +typedef int (*CVDlsDenseJacFn)(int N, realtype t, + N_Vector y, N_Vector fy, + DlsMat Jac, void *user_data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +/* + * ----------------------------------------------------------------- + * Type: CVDlsBandJacFn + * ----------------------------------------------------------------- + * + * A band Jacobian approximation function Jac must have the + * prototype given below. Its parameters are: + * + * N is the length of all vector arguments. + * + * mupper is the upper half-bandwidth of the approximate banded + * Jacobian. This parameter is the same as the mupper parameter + * passed by the user to the linear solver initialization function. + * + * mlower is the lower half-bandwidth of the approximate banded + * Jacobian. This parameter is the same as the mlower parameter + * passed by the user to the linear solver initialization function. + * + * t is the current value of the independent variable. + * + * y is the current value of the dependent variable vector, + * namely the predicted value of y(t). + * + * fy is the vector f(t,y). + * + * Jac is the band matrix (of type DlsMat) that will be loaded + * by a CVDlsBandJacFn with an approximation to the Jacobian matrix + * Jac = (df_i/dy_j) at the point (t,y). + * Three efficient ways to load J are: + * + * (1) (with macros - no explicit data structure references) + * for (j=0; j < n; j++) { + * col_j = BAND_COL(Jac,j); + * for (i=j-mupper; i <= j+mlower; i++) { + * generate J_ij = the (i,j)th Jacobian element + * BAND_COL_ELEM(col_j,i,j) = J_ij; + * } + * } + * + * (2) (with BAND_COL macro, but without BAND_COL_ELEM macro) + * for (j=0; j < n; j++) { + * col_j = BAND_COL(Jac,j); + * for (k=-mupper; k <= mlower; k++) { + * generate J_ij = the (i,j)th Jacobian element, i=j+k + * col_j[k] = J_ij; + * } + * } + * + * (3) (without macros - explicit data structure references) + * offset = Jac->smu; + * for (j=0; j < n; j++) { + * col_j = ((Jac->data)[j])+offset; + * for (k=-mupper; k <= mlower; k++) { + * generate J_ij = the (i,j)th Jacobian element, i=j+k + * col_j[k] = J_ij; + * } + * } + * Caution: Jac->smu is generally NOT the same as mupper. + * + * The BAND_ELEM(A,i,j) macro is appropriate for use in small + * problems in which efficiency of access is NOT a major concern. + * + * user_data is a pointer to user data - the same as the user_data + * parameter passed to CVodeSetFdata. + * + * NOTE: If the user's Jacobian routine needs other quantities, + * they are accessible as follows: hcur (the current stepsize) + * and ewt (the error weight vector) are accessible through + * CVodeGetCurrentStep and CVodeGetErrWeights, respectively + * (see cvode.h). The unit roundoff is available as + * UNIT_ROUNDOFF defined in sundials_types.h + * + * tmp1, tmp2, and tmp3 are pointers to memory allocated for + * vectors of length N which can be used by a CVDlsBandJacFn + * as temporary storage or work space. + * + * A CVDlsBandJacFn should return 0 if successful, a positive value + * if a recoverable error occurred, and a negative value if an + * unrecoverable error occurred. + * ----------------------------------------------------------------- + */ + +typedef int (*CVDlsBandJacFn)(int N, int mupper, int mlower, + realtype t, N_Vector y, N_Vector fy, + DlsMat Jac, void *user_data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +/* + * ----------------------------------------------------------------- + * EXPORTED FUNCTIONS + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Optional inputs to the CVDLS linear solver + * ----------------------------------------------------------------- + * + * CVDlsSetDenseJacFn specifies the dense Jacobian approximation + * routine to be used for a direct dense linear solver. + * + * CVDlsSetBandJacFn specifies the band Jacobian approximation + * routine to be used for a direct band linear solver. + * + * By default, a difference quotient approximation, supplied with + * the solver is used. + * + * The return value is one of: + * CVDLS_SUCCESS if successful + * CVDLS_MEM_NULL if the CVODE memory was NULL + * CVDLS_LMEM_NULL if the linear solver memory was NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVDlsSetDenseJacFn(void *cvode_mem, CVDlsDenseJacFn jac); +SUNDIALS_EXPORT int CVDlsSetBandJacFn(void *cvode_mem, CVDlsBandJacFn jac); + +/* + * ----------------------------------------------------------------- + * Optional outputs from the CVSDIRECT linear solver + * ----------------------------------------------------------------- + * + * CVDlsGetWorkSpace returns the real and integer workspace used + * by the direct linear solver. + * CVDlsGetNumJacEvals returns the number of calls made to the + * Jacobian evaluation routine jac. + * CVDlsGetNumRhsEvals returns the number of calls to the user + * f routine due to finite difference Jacobian + * evaluation. + * CVDlsGetLastFlag returns the last error flag set by any of + * the CVSDIRECT interface functions. + * + * The return value of CVDlsGet* is one of: + * CVDLS_SUCCESS if successful + * CVDLS_MEM_NULL if the CVODES memory was NULL + * CVDLS_LMEM_NULL if the linear solver memory was NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVDlsGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS); +SUNDIALS_EXPORT int CVDlsGetNumJacEvals(void *cvode_mem, long int *njevals); +SUNDIALS_EXPORT int CVDlsGetNumRhsEvals(void *cvode_mem, long int *nfevalsLS); +SUNDIALS_EXPORT int CVDlsGetLastFlag(void *cvode_mem, int *flag); + +/* + * ----------------------------------------------------------------- + * The following function returns the name of the constant + * associated with a CVSDIRECT return flag + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT char *CVDlsGetReturnFlagName(int flag); + +/* + * ================================================================= + * PART II: B A C K W A R D P R O B L E M S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * FUNCTION TYPES + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Type: CVDlsDenseJacFnB + * ----------------------------------------------------------------- + * A dense Jacobian approximation function jacB for the adjoint + * (backward) problem must have the prototype given below. + * ----------------------------------------------------------------- + */ + +typedef int (*CVDlsDenseJacFnB)(int nB, realtype t, + N_Vector y, + N_Vector yB, N_Vector fyB, + DlsMat JB, void *user_dataB, + N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B); + +/* + * ----------------------------------------------------------------- + * Type : CVDlsBandJacFnB + * ----------------------------------------------------------------- + * A band Jacobian approximation function jacB for the adjoint + * (backward) problem must have the prototype given below. + * ----------------------------------------------------------------- + */ + +typedef int (*CVDlsBandJacFnB)(int nB, int mupperB, int mlowerB, + realtype t, + N_Vector y, + N_Vector yB, N_Vector fyB, + DlsMat JB, void *user_dataB, + N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B); + +/* + * ----------------------------------------------------------------- + * EXPORTED FUNCTIONS + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Functions: CVDlsSetJacFnB + * ----------------------------------------------------------------- + * CVDlsSetDenseJacFnB and CVDlsSetBandJacFnB specify the dense and + * band, respectively, Jacobian functions to be used by a + * CVSDIRECT linear solver for the bacward integration phase. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVDlsSetDenseJacFnB(void *cvode_mem, int which, + CVDlsDenseJacFnB jacB); +SUNDIALS_EXPORT int CVDlsSetBandJacFnB(void *cvode_mem, int which, + CVDlsBandJacFnB jacB); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_lapack.h b/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_lapack.h new file mode 100644 index 0000000..20eedf8 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_lapack.h @@ -0,0 +1,103 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2008/04/18 19:42:37 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Header file for the CVODES dense linear solver CVSLAPACK. + * ----------------------------------------------------------------- + */ + +#ifndef _CVSLAPACK_H +#define _CVSLAPACK_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * Function: CVLapackDense + * ----------------------------------------------------------------- + * A call to the CVLapackDense function links the main integrator + * with the CVSLAPACK linear solver using dense Jacobians. + * + * cvode_mem is the pointer to the integrator memory returned by + * CVodeCreate. + * + * N is the size of the ODE system. + * + * The return value of CVLapackDense is one of: + * CVDLS_SUCCESS if successful + * CVDLS_MEM_NULL if the CVODES memory was NULL + * CVDLS_MEM_FAIL if there was a memory allocation failure + * CVDLS_ILL_INPUT if a required vector operation is missing + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVLapackDense(void *cvode_mem, int N); + +/* + * ----------------------------------------------------------------- + * Function: CVLapackBand + * ----------------------------------------------------------------- + * A call to the CVLapackBand function links the main integrator + * with the CVSLAPACK linear solver using banded Jacobians. + * + * cvode_mem is the pointer to the integrator memory returned by + * CVodeCreate. + * + * N is the size of the ODE system. + * + * mupper is the upper bandwidth of the band Jacobian approximation. + * + * mlower is the lower bandwidth of the band Jacobian approximation. + * + * The return value of CVLapackBand is one of: + * CVDLS_SUCCESS if successful + * CVDLS_MEM_NULL if the CVODES memory was NULL + * CVDLS_MEM_FAIL if there was a memory allocation failure + * CVDLS_ILL_INPUT if a required vector operation is missing or + * if a bandwidth has an illegal value. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVLapackBand(void *cvode_mem, int N, int mupper, int mlower); + +/* + * ----------------------------------------------------------------- + * Function: CVLapackDenseB + * ----------------------------------------------------------------- + * CVLapackDenseB links the main CVODE integrator with the dense + * CVSLAPACK linear solver for the backward integration. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVLapackDenseB(void *cvode_mem, int which, int nB); + +/* + * ----------------------------------------------------------------- + * Function: CVLapackBandB + * ----------------------------------------------------------------- + * CVLapackBandB links the main CVODE integrator with the band + * CVSLAPACK linear solver for the backward integration. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVLapackBandB(void *cvode_mem, int which, + int nB, int mupperB, int mlowerB); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_spbcgs.h b/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_spbcgs.h new file mode 100644 index 0000000..acc56c9 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_spbcgs.h @@ -0,0 +1,87 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.4 $ + * $Date: 2007/03/22 18:05:50 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the CVODES scaled preconditioned + * Bi-CGSTAB linear solver, CVSPBCG. + * + * Part I contains function prototypes for using CVSPBCG on forward + * problems (IVP integration and/or FSA) + * + * Part II contains function prototypes for using CVSPBCG on adjoint + * (backward) problems + * ----------------------------------------------------------------- + */ + +#ifndef _CVSSPBCG_H +#define _CVSSPBCG_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * PART I - forward problems + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Function : CVSpbcg + * ----------------------------------------------------------------- + * A call to the CVSpbcg function links the main CVODE integrator + * with the CVSPBCG linear solver. + * + * cvode_mem is the pointer to the integrator memory returned by + * CVodeCreate. + * + * pretype is the type of user preconditioning to be done. + * This must be one of the four enumeration constants + * PREC_NONE, PREC_LEFT, PREC_RIGHT, or PREC_BOTH defined + * in iterative.h. These correspond to no preconditioning, + * left preconditioning only, right preconditioning + * only, and both left and right preconditioning, + * respectively. + * + * maxl is the maximum Krylov dimension. This is an + * optional input to the CVSPBCG solver. Pass 0 to + * use the default value CVSPILS_MAXL=5. + * + * The return value of CVSpbcg is one of: + * CVSPILS_SUCCESS if successful + * CVSPILS_MEM_NULL if the cvode memory was NULL + * CVSPILS_MEM_FAIL if there was a memory allocation failure + * CVSPILS_ILL_INPUT if a required vector operation is missing + * The above constants are defined in cvodes_spils.h + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVSpbcg(void *cvode_mem, int pretype, int maxl); + +/* + * ----------------------------------------------------------------- + * PART II - backward problems + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVSpbcgB(void *cvode_mem, int which, + int pretypeB, int maxlB); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_spgmr.h b/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_spgmr.h new file mode 100644 index 0000000..73f2420 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_spgmr.h @@ -0,0 +1,88 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.4 $ + * $Date: 2007/03/22 18:05:50 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the CVODES scaled preconditioned + * GMRES linear solver, CVSPGMR. + * + * Part I contains function prototypes for using CVSPGMR on forward + * problems (IVP integration and/or FSA) + * + * Part II contains function prototypes for using CVSPGMR on adjoint + * (backward) problems + * ----------------------------------------------------------------- + */ + +#ifndef _CVSSPGMR_H +#define _CVSSPGMR_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * PART I - forward problems + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Function : CVSpgmr + * ----------------------------------------------------------------- + * A call to the CVSpgmr function links the main CVODE integrator + * with the CVSPGMR linear solver. + * + * cvode_mem is the pointer to the integrator memory returned by + * CVodeCreate. + * + * pretype is the type of user preconditioning to be done. + * This must be one of the four enumeration constants + * NONE, LEFT, RIGHT, or BOTH defined in iterative.h. + * These correspond to no preconditioning, + * left preconditioning only, right preconditioning + * only, and both left and right preconditioning, + * respectively. + * + * maxl is the maximum Krylov dimension. This is an + * optional input to the CVSPGMR solver. Pass 0 to + * use the default value CVSPILS_MAXL=5. + * + * The return value of CVSpgmr is one of: + * CVSPILS_SUCCESS if successful + * CVSPILS_MEM_NULL if the cvode memory was NULL + * CVSPILS_MEM_FAIL if there was a memory allocation failure + * CVSPILS_ILL_INPUT if a required vector operation is missing + * The above constants are defined in cvodes_spils.h + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVSpgmr(void *cvode_mem, int pretype, int maxl); + +/* + * ----------------------------------------------------------------- + * PART II - backward problems + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVSpgmrB(void *cvode_mem, int which, + int pretypeB, int maxlB); + + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_spils.h b/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_spils.h new file mode 100644 index 0000000..928a1ef --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_spils.h @@ -0,0 +1,450 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.11 $ + * $Date: 2008/09/03 20:24:48 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the common header file for the Scaled, Preconditioned + * Iterative Linear Solvers in CVODES. + * + * Part I contains type definitions and functions for using the + * iterative linear solvers on forward problems + * (IVP integration and/or FSA) + * + * Part II contains type definitions and functions for using the + * iterative linear solvers on adjoint (backward) problems + * ----------------------------------------------------------------- + */ + +#ifndef _CVSSPILS_H +#define _CVSSPILS_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * CVSPILS return values + * ----------------------------------------------------------------- + */ + +#define CVSPILS_SUCCESS 0 +#define CVSPILS_MEM_NULL -1 +#define CVSPILS_LMEM_NULL -2 +#define CVSPILS_ILL_INPUT -3 +#define CVSPILS_MEM_FAIL -4 +#define CVSPILS_PMEM_NULL -5 + +/* Return values for the adjoint module */ + +#define CVSPILS_NO_ADJ -101 +#define CVSPILS_LMEMB_NULL -102 + +/* + * ----------------------------------------------------------------- + * CVSPILS solver constants + * ----------------------------------------------------------------- + * CVSPILS_MAXL : default value for the maximum Krylov + * dimension + * + * CVSPILS_MSBPRE : maximum number of steps between + * preconditioner evaluations + * + * CVSPILS_DGMAX : maximum change in gamma between + * preconditioner evaluations + * + * CVSPILS_EPLIN : default value for factor by which the + * tolerance on the nonlinear iteration is + * multiplied to get a tolerance on the linear + * iteration + * ----------------------------------------------------------------- + */ + +#define CVSPILS_MAXL 5 +#define CVSPILS_MSBPRE 50 +#define CVSPILS_DGMAX RCONST(0.2) +#define CVSPILS_EPLIN RCONST(0.05) + +/* + * ----------------------------------------------------------------- + * PART I - forward problems + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Type : CVSpilsPrecSetupFn + * ----------------------------------------------------------------- + * The user-supplied preconditioner setup function PrecSetup and + * the user-supplied preconditioner solve function PrecSolve + * together must define left and right preconditoner matrices + * P1 and P2 (either of which may be trivial), such that the + * product P1*P2 is an approximation to the Newton matrix + * M = I - gamma*J. Here J is the system Jacobian J = df/dy, + * and gamma is a scalar proportional to the integration step + * size h. The solution of systems P z = r, with P = P1 or P2, + * is to be carried out by the PrecSolve function, and PrecSetup + * is to do any necessary setup operations. + * + * The user-supplied preconditioner setup function PrecSetup + * is to evaluate and preprocess any Jacobian-related data + * needed by the preconditioner solve function PrecSolve. + * This might include forming a crude approximate Jacobian, + * and performing an LU factorization on the resulting + * approximation to M. This function will not be called in + * advance of every call to PrecSolve, but instead will be called + * only as often as necessary to achieve convergence within the + * Newton iteration. If the PrecSolve function needs no + * preparation, the PrecSetup function can be NULL. + * + * For greater efficiency, the PrecSetup function may save + * Jacobian-related data and reuse it, rather than generating it + * from scratch. In this case, it should use the input flag jok + * to decide whether to recompute the data, and set the output + * flag *jcurPtr accordingly. + * + * Each call to the PrecSetup function is preceded by a call to + * the RhsFn f with the same (t,y) arguments. Thus the PrecSetup + * function can use any auxiliary data that is computed and + * saved by the f function and made accessible to PrecSetup. + * + * A function PrecSetup must have the prototype given below. + * Its parameters are as follows: + * + * t is the current value of the independent variable. + * + * y is the current value of the dependent variable vector, + * namely the predicted value of y(t). + * + * fy is the vector f(t,y). + * + * jok is an input flag indicating whether Jacobian-related + * data needs to be recomputed, as follows: + * jok == FALSE means recompute Jacobian-related data + * from scratch. + * jok == TRUE means that Jacobian data, if saved from + * the previous PrecSetup call, can be reused + * (with the current value of gamma). + * A Precset call with jok == TRUE can only occur after + * a call with jok == FALSE. + * + * jcurPtr is a pointer to an output integer flag which is + * to be set by PrecSetup as follows: + * Set *jcurPtr = TRUE if Jacobian data was recomputed. + * Set *jcurPtr = FALSE if Jacobian data was not recomputed, + * but saved data was reused. + * + * gamma is the scalar appearing in the Newton matrix. + * + * user_data is a pointer to user data - the same as the user_data + * parameter passed to the CVodeSetUserData function. + * + * tmp1, tmp2, and tmp3 are pointers to memory allocated + * for N_Vectors which can be used by + * CVSpilsPrecSetupFn as temporary storage or + * work space. + * + * NOTE: If the user's preconditioner needs other quantities, + * they are accessible as follows: hcur (the current stepsize) + * and ewt (the error weight vector) are accessible through + * CVodeGetCurrentStep and CVodeGetErrWeights, respectively). + * The unit roundoff is available as UNIT_ROUNDOFF defined in + * sundials_types.h. + * + * Returned value: + * The value to be returned by the PrecSetup function is a flag + * indicating whether it was successful. This value should be + * 0 if successful, + * > 0 for a recoverable error (step will be retried), + * < 0 for an unrecoverable error (integration is halted). + * ----------------------------------------------------------------- + */ + +typedef int (*CVSpilsPrecSetupFn)(realtype t, N_Vector y, N_Vector fy, + booleantype jok, booleantype *jcurPtr, + realtype gamma, void *user_data, + N_Vector tmp1, N_Vector tmp2, + N_Vector tmp3); + +/* + * ----------------------------------------------------------------- + * Type : CVSpilsPrecSolveFn + * ----------------------------------------------------------------- + * The user-supplied preconditioner solve function PrecSolve + * is to solve a linear system P z = r in which the matrix P is + * one of the preconditioner matrices P1 or P2, depending on the + * type of preconditioning chosen. + * + * A function PrecSolve must have the prototype given below. + * Its parameters are as follows: + * + * t is the current value of the independent variable. + * + * y is the current value of the dependent variable vector. + * + * fy is the vector f(t,y). + * + * r is the right-hand side vector of the linear system. + * + * z is the output vector computed by PrecSolve. + * + * gamma is the scalar appearing in the Newton matrix. + * + * delta is an input tolerance for use by PSolve if it uses + * an iterative method in its solution. In that case, + * the residual vector Res = r - P z of the system + * should be made less than delta in weighted L2 norm, + * i.e., sqrt [ Sum (Res[i]*ewt[i])^2 ] < delta. + * Note: the error weight vector ewt can be obtained + * through a call to the routine CVodeGetErrWeights. + * + * lr is an input flag indicating whether PrecSolve is to use + * the left preconditioner P1 or right preconditioner + * P2: lr = 1 means use P1, and lr = 2 means use P2. + * + * user_data is a pointer to user data - the same as the user_data + * parameter passed to the CVodeSetUserData function. + * + * tmp is a pointer to memory allocated for an N_Vector + * which can be used by PSolve for work space. + * + * Returned value: + * The value to be returned by the PrecSolve function is a flag + * indicating whether it was successful. This value should be + * 0 if successful, + * positive for a recoverable error (step will be retried), + * negative for an unrecoverable error (integration is halted). + * ----------------------------------------------------------------- + */ + +typedef int (*CVSpilsPrecSolveFn)(realtype t, N_Vector y, N_Vector fy, + N_Vector r, N_Vector z, + realtype gamma, realtype delta, + int lr, void *user_data, N_Vector tmp); + +/* + * ----------------------------------------------------------------- + * Type : CVSpilsJacTimesVecFn + * ----------------------------------------------------------------- + * The user-supplied function jtimes is to generate the product + * J*v for given v, where J is the Jacobian df/dy, or an + * approximation to it, and v is a given vector. It should return + * 0 if successful a positive value for a recoverable error or + * a negative value for an unrecoverable failure. + * + * A function jtimes must have the prototype given below. Its + * parameters are as follows: + * + * v is the N_Vector to be multiplied by J. + * + * Jv is the output N_Vector containing J*v. + * + * t is the current value of the independent variable. + * + * y is the current value of the dependent variable + * vector. + * + * fy is the vector f(t,y). + * + * user_data is a pointer to user data, the same as the user_data + * parameter passed to the CVodeSetUserData function. + * + * tmp is a pointer to memory allocated for an N_Vector + * which can be used by Jtimes for work space. + * ----------------------------------------------------------------- + */ + +typedef int (*CVSpilsJacTimesVecFn)(N_Vector v, N_Vector Jv, realtype t, + N_Vector y, N_Vector fy, + void *user_data, N_Vector tmp); + + +/* + * ----------------------------------------------------------------- + * Optional inputs to the CVSPILS linear solver + * ----------------------------------------------------------------- + * + * CVSpilsSetPrecType resets the type of preconditioner, pretype, + * from the value previously set. + * This must be one of PREC_NONE, PREC_LEFT, + * PREC_RIGHT, or PREC_BOTH. + * + * CVSpilsSetGSType specifies the type of Gram-Schmidt + * orthogonalization to be used. This must be one of + * the two enumeration constants MODIFIED_GS or + * CLASSICAL_GS defined in iterative.h. These correspond + * to using modified Gram-Schmidt and classical + * Gram-Schmidt, respectively. + * Default value is MODIFIED_GS. + * + * CVSpilsSetMaxl resets the maximum Krylov subspace size, maxl, + * from the value previously set. + * An input value <= 0, gives the default value. + * + * CVSpilsSetEpsLin specifies the factor by which the tolerance on + * the nonlinear iteration is multiplied to get a + * tolerance on the linear iteration. + * Default value is 0.05. + * + * CVSpilsSetPreconditioner specifies the PrecSetup and PrecSolve functions. + * Default is NULL for both arguments (no preconditioning). + * + * CVSpilsSetJacTimesVecFn specifies the jtimes function. Default is to use + * an internal finite difference approximation routine. + * + * The return value of CVSpilsSet* is one of: + * CVSPILS_SUCCESS if successful + * CVSPILS_MEM_NULL if the cvode memory was NULL + * CVSPILS_LMEM_NULL if the linear solver memory was NULL + * CVSPILS_ILL_INPUT if an input has an illegal value + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVSpilsSetPrecType(void *cvode_mem, int pretype); +SUNDIALS_EXPORT int CVSpilsSetGSType(void *cvode_mem, int gstype); +SUNDIALS_EXPORT int CVSpilsSetMaxl(void *cvode_mem, int maxl); +SUNDIALS_EXPORT int CVSpilsSetEpsLin(void *cvode_mem, realtype eplifac); +SUNDIALS_EXPORT int CVSpilsSetPreconditioner(void *cvode_mem, + CVSpilsPrecSetupFn pset, + CVSpilsPrecSolveFn psolve); +SUNDIALS_EXPORT int CVSpilsSetJacTimesVecFn(void *cvode_mem, + CVSpilsJacTimesVecFn jtv); + +/* + * ----------------------------------------------------------------- + * Optional outputs from the CVSPILS linear solver + * ----------------------------------------------------------------- + * CVSpilsGetWorkSpace returns the real and integer workspace used + * by the SPILS module. + * + * CVSpilsGetNumPrecEvals returns the number of preconditioner + * evaluations, i.e. the number of calls made + * to PrecSetup with jok==FALSE. + * + * CVSpilsGetNumPrecSolves returns the number of calls made to + * PrecSolve. + * + * CVSpilsGetNumLinIters returns the number of linear iterations. + * + * CVSpilsGetNumConvFails returns the number of linear + * convergence failures. + * + * CVSpilsGetNumJtimesEvals returns the number of calls to jtimes. + * + * CVSpilsGetNumRhsEvals returns the number of calls to the user + * f routine due to finite difference Jacobian + * times vector evaluation. + * + * CVSpilsGetLastFlag returns the last error flag set by any of + * the CVSPILS interface functions. + * + * The return value of CVSpilsGet* is one of: + * CVSPILS_SUCCESS if successful + * CVSPILS_MEM_NULL if the cvode memory was NULL + * CVSPILS_LMEM_NULL if the linear solver memory was NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVSpilsGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS); +SUNDIALS_EXPORT int CVSpilsGetNumPrecEvals(void *cvode_mem, long int *npevals); +SUNDIALS_EXPORT int CVSpilsGetNumPrecSolves(void *cvode_mem, long int *npsolves); +SUNDIALS_EXPORT int CVSpilsGetNumLinIters(void *cvode_mem, long int *nliters); +SUNDIALS_EXPORT int CVSpilsGetNumConvFails(void *cvode_mem, long int *nlcfails); +SUNDIALS_EXPORT int CVSpilsGetNumJtimesEvals(void *cvode_mem, long int *njvevals); +SUNDIALS_EXPORT int CVSpilsGetNumRhsEvals(void *cvode_mem, long int *nfevalsLS); +SUNDIALS_EXPORT int CVSpilsGetLastFlag(void *cvode_mem, int *flag); + +/* + * ----------------------------------------------------------------- + * The following function returns the name of the constant + * associated with a CVSPILS return flag + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT char *CVSpilsGetReturnFlagName(int flag); + + +/* + * ----------------------------------------------------------------- + * PART II - backward problems + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Type : CVSpilsPrecSetupFnB + * ----------------------------------------------------------------- + * A function PrecSetupB for the adjoint (backward) problem must have + * the prototype given below. + * ----------------------------------------------------------------- + */ + +typedef int (*CVSpilsPrecSetupFnB)(realtype t, N_Vector y, + N_Vector yB, N_Vector fyB, + booleantype jokB, + booleantype *jcurPtrB, realtype gammaB, + void *user_dataB, + N_Vector tmp1B, N_Vector tmp2B, + N_Vector tmp3B); + + +/* + * ----------------------------------------------------------------- + * Type : CVSpilsPrecSolveFnB + * ----------------------------------------------------------------- + * A function PrecSolveB for the adjoint (backward) problem must + * have the prototype given below. + * ----------------------------------------------------------------- + */ + +typedef int (*CVSpilsPrecSolveFnB)(realtype t, N_Vector y, + N_Vector yB, N_Vector fyB, + N_Vector rB, N_Vector zB, + realtype gammaB, realtype deltaB, + int lrB, void *user_dataB, N_Vector tmpB); + +/* + * ----------------------------------------------------------------- + * Type : CVSpilsJacTimesVecFnB + * ----------------------------------------------------------------- + * A function jtimesB for the adjoint (backward) problem must have + * the prototype given below. + * ----------------------------------------------------------------- + */ + +typedef int (*CVSpilsJacTimesVecFnB)(N_Vector vB, N_Vector JvB, realtype t, + N_Vector y, N_Vector yB, N_Vector fyB, + void *jac_dataB, N_Vector tmpB); + +/* + * ----------------------------------------------------------------- + * Functions + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVSpilsSetPrecTypeB(void *cvode_mem, int which, int pretypeB); +SUNDIALS_EXPORT int CVSpilsSetGSTypeB(void *cvode_mem, int which, int gstypeB); +SUNDIALS_EXPORT int CVSpilsSetEpslinB(void *cvode_mem, int which, realtype eplifacB); +SUNDIALS_EXPORT int CVSpilsSetMaxlB(void *cvode_mem, int which, int maxlB); +SUNDIALS_EXPORT int CVSpilsSetPreconditionerB(void *cvode_mem, int which, + CVSpilsPrecSetupFnB psetB, + CVSpilsPrecSolveFnB psolveB); +SUNDIALS_EXPORT int CVSpilsSetJacTimesVecFnB(void *cvode_mem, int which, + CVSpilsJacTimesVecFnB jtvB); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_sptfqmr.h b/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_sptfqmr.h new file mode 100644 index 0000000..2b91a3a --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/cvodes/cvodes_sptfqmr.h @@ -0,0 +1,88 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.4 $ + * $Date: 2007/03/22 18:05:50 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the CVODES scaled preconditioned TFQMR + * linear solver, CVSPTFQMR. + * + * Part I contains function prototypes for using CVSPTFQMR on forward + * problems (IVP integration and/or FSA) + * + * Part II contains function prototypes for using CVSPTFQMR on adjoint + * (backward) problems + * ----------------------------------------------------------------- + */ + +#ifndef _CVSSPTFQMR_H +#define _CVSSPTFQMR_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * PART I - forward problems + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Function : CVSptfqmr + * ----------------------------------------------------------------- + * A call to the CVSptfqmr function links the main CVODE integrator + * with the CVSPTFQMR linear solver. + * + * cvode_mem is the pointer to the integrator memory returned by + * CVodeCreate. + * + * pretype is the type of user preconditioning to be done. + * This must be one of the four enumeration constants + * PREC_NONE, PREC_LEFT, PREC_RIGHT, or PREC_BOTH defined + * in iterative.h. These correspond to no preconditioning, + * left preconditioning only, right preconditioning + * only, and both left and right preconditioning, + * respectively. + * + * maxl is the maximum Krylov dimension. This is an + * optional input to the CVSPTFQMR solver. Pass 0 to + * use the default value CVSPILS_MAXL=5. + * + * The return value of CVSptfqmr is one of: + * CVSPILS_SUCCESS if successful + * CVSPILS_MEM_NULL if the cvode memory was NULL + * CVSPILS_MEM_FAIL if there was a memory allocation failure + * CVSPILS_ILL_INPUT if a required vector operation is missing + * The above constants are defined in cvodes_spils.h + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVSptfqmr(void *cvode_mem, int pretype, int maxl); + + +/* + * ----------------------------------------------------------------- + * PART II - backward problems + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVSptfqmrB(void *cvode_mem, int which, + int pretypeB, int maxlB); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/cvodes_band.h b/odemex/Parser/CVode/cv_src/include/cvodes_band.h new file mode 100644 index 0000000..fc3ce44 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/cvodes_band.h @@ -0,0 +1,72 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.7 $ + * $Date: 2008/04/18 19:42:36 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the band linear solver CSVBAND. + * ----------------------------------------------------------------- + */ + +#ifndef _CVSBAND_H +#define _CVSBAND_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * Function : CVBand + * ----------------------------------------------------------------- + * A call to the CVBand function links the main CVODE integrator + * with the CVSBAND linear solver. + * + * cvode_mem is the pointer to the integrator memory returned by + * CVodeCreate. + * + * N is the size of the ODE system. + * + * mupper is the upper bandwidth of the band Jacobian + * approximation. + * + * mlower is the lower bandwidth of the band Jacobian + * approximation. + * + * The return value of CVBand is one of: + * CVDLS_SUCCESS if successful + * CVDLS_MEM_NULL if the cvode memory was NULL + * CVDLS_MEM_FAIL if there was a memory allocation failure + * CVDLS_ILL_INPUT if a required vector operation is missing or + * if a bandwidth has an illegal value. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVBand(void *cvode_mem, int N, int mupper, int mlower); + +/* + * ----------------------------------------------------------------- + * Function: CVBandB + * ----------------------------------------------------------------- + * CVBandB links the main CVODE integrator with the CVSBAND + * linear solver for the backward integration. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVBandB(void *cvode_mem, int which, + int nB, int mupperB, int mlowerB); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/cvodes_bandpre.h b/odemex/Parser/CVode/cv_src/include/cvodes_bandpre.h new file mode 100644 index 0000000..966fdc3 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/cvodes_bandpre.h @@ -0,0 +1,179 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.7 $ + * $Date: 2007/11/26 16:19:58 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the CVSBANDPRE module, which + * provides a banded difference quotient Jacobian-based + * preconditioner and solver routines for use with CVSPGMR, + * CVSPBCG, or CVSPTFQMR. + * + * Part I contains type definitions and function prototypes for using + * CVSBANDPRE on forward problems (IVP integration and/or FSA) + * + * Part II contains type definitions and function prototypes for using + * CVSBANDPRE on adjopint (backward) problems + * ----------------------------------------------------------------- + */ + +#ifndef _CVSBANDPRE_H +#define _CVSBANDPRE_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ================================================================= + * PART I - forward problems + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * + * SUMMARY + * + * These routines provide a band matrix preconditioner based on + * difference quotients of the ODE right-hand side function f. + * The user supplies parameters + * mu = upper half-bandwidth (number of super-diagonals) + * ml = lower half-bandwidth (number of sub-diagonals) + * The routines generate a band matrix of bandwidth ml + mu + 1 + * and use this to form a preconditioner for use with the Krylov + * linear solver in CVSP*. Although this matrix is intended to + * approximate the Jacobian df/dy, it may be a very crude + * approximation. The true Jacobian need not be banded, or its + * true bandwith may be larger than ml + mu + 1, as long as the + * banded approximation generated here is sufficiently accurate + * to speed convergence as a preconditioner. + * + * Usage: + * The following is a summary of the usage of this module. + * Details of the calls to CVodeCreate, CVodeMalloc, CVSp*, + * and CVode are available in the User Guide. + * To use these routines, the sequence of calls in the user + * main program should be as follows: + * + * #include + * #include + * ... + * Set y0 + * ... + * cvode_mem = CVodeCreate(...); + * ier = CVodeMalloc(...); + * ... + * flag = CVSptfqmr(cvode_mem, pretype, maxl); + * -or- + * flag = CVSpgmr(cvode_mem, pretype, maxl); + * -or- + * flag = CVSpbcg(cvode_mem, pretype, maxl); + * ... + * flag = CVBandPrecInit(cvode_mem, N, mu, ml); + * ... + * flag = CVode(...); + * ... + * Free y0 + * ... + * CVodeFree(&cvode_mem); + * + * Notes: + * (1) Include this file for the CVBandPrecData type definition. + * (2) In the CVBandPrecInit call, the arguments N is the + * problem dimension. + * (3) In the CVBPSp* call, the user is free to specify + * the input pretype and the optional input maxl. + * ----------------------------------------------------------------- + */ + + +/* + * ----------------------------------------------------------------- + * Function : CVBandPrecInit + * ----------------------------------------------------------------- + * CVBandPrecInit allocates and initializes the BANDPRE preconditioner + * module. This functino must be called AFTER one of the SPILS linear + * solver modules has been attached to the CVODE integrator. + * + * The parameters of CVBandPrecInit are as follows: + * + * cvode_mem is the pointer to CVODE memory returned by CVodeCreate. + * + * N is the problem size. + * + * mu is the upper half bandwidth. + * + * ml is the lower half bandwidth. + * + * The return value of CVBandPrecInit is one of: + * CVSPILS_SUCCESS if no errors occurred + * CVSPILS_MEM_NULL if the integrator memory is NULL + * CVSPILS_LMEM_NULL if the linear solver memory is NULL + * CVSPILS_ILL_INPUT if an input has an illegal value + * CVSPILS_MEM_FAIL if a memory allocation request failed + * + * NOTE: The band preconditioner assumes a serial implementation + * of the NVECTOR package. Therefore, CVBandPrecInit will + * first test for a compatible N_Vector internal + * representation by checking for required functions. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVBandPrecInit(void *cvode_mem, int N, int mu, int ml); + +/* + * ----------------------------------------------------------------- + * Optional output functions : CVBandPrecGet* + * ----------------------------------------------------------------- + * CVBandPrecGetWorkSpace returns the real and integer work space used + * by CVBANDPRE. + * CVBandPrecGetNumRhsEvals returns the number of calls made from + * CVBANDPRE to the user's right-hand side + * routine f. + * + * The return value of CVBandPrecGet* is one of: + * CVSPILS_SUCCESS if no errors occurred + * CVSPILS_MEM_NULL if the integrator memory is NULL + * CVSPILS_LMEM_NULL if the linear solver memory is NULL + * CVSPILS_PMEM_NULL if the preconditioner memory is NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVBandPrecGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS); +SUNDIALS_EXPORT int CVBandPrecGetNumRhsEvals(void *cvode_mem, long int *nfevalsBP); + +/* + * ================================================================= + * PART II - backward problems + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Functions: CVBandPrecInitB, CVBPSp*B + * ----------------------------------------------------------------- + * Interface functions for the CVBANDPRE preconditioner to be used + * on the backward phase. + * + * CVBandPrecInitB interfaces to the CVBANDPRE preconditioner + * for the backward integration. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVBandPrecInitB(void *cvode_mem, int which, + int nB, int muB, int mlB); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/cvodes_bbdpre.h b/odemex/Parser/CVode/cv_src/include/cvodes_bbdpre.h new file mode 100644 index 0000000..5792794 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/cvodes_bbdpre.h @@ -0,0 +1,331 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.10 $ + * $Date: 2007/11/26 16:19:58 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the CVBBDPRE module, for a + * band-block-diagonal preconditioner, i.e. a block-diagonal + * matrix with banded blocks, for use with CVSPGMR/CVSPBCG/CVSPTFQMR, + * and the parallel implementation of the NVECTOR module. + * + * + * Part I contains type definitions and function prototypes for using + * CVBBDPRE on forward problems (IVP integration and/or FSA) + * + * Part II contains type definitions and function prototypes for using + * CVBBDPRE on adjopint (backward) problems + * ----------------------------------------------------------------- + */ + +#ifndef _CVSBBDPRE_H +#define _CVSBBDPRE_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ================================================================= + * PART I - forward problems + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * + * SUMMARY + * + * These routines provide a preconditioner matrix that is + * block-diagonal with banded blocks. The blocking corresponds + * to the distribution of the dependent variable vector y among + * the processors. Each preconditioner block is generated from + * the Jacobian of the local part (on the current processor) of a + * given function g(t,y) approximating f(t,y). The blocks are + * generated by a difference quotient scheme on each processor + * independently. This scheme utilizes an assumed banded + * structure with given half-bandwidths, mudq and mldq. + * However, the banded Jacobian block kept by the scheme has + * half-bandwiths mukeep and mlkeep, which may be smaller. + * + * The user's calling program should have the following form: + * + * #include + * #include + * ... + * void *cvode_mem; + * ... + * Set y0 + * ... + * cvode_mem = CVodeCreate(...); + * ier = CVodeMalloc(...); + * ... + * flag = CVSpgmr(cvode_mem, pretype, maxl); + * -or- + * flag = CVSpbcg(cvode_mem, pretype, maxl); + * -or- + * flag = CVSptfqmr(cvode_mem, pretype, maxl); + * ... + * flag = CVBBDPrecInit(cvode_mem, Nlocal, mudq ,mldq, + * mukeep, mlkeep, dqrely, gloc, cfn); + * ... + * ier = CVode(...); + * ... + * CVodeFree(&cvode_mem); + * + * Free y0 + * + * The user-supplied routines required are: + * + * f = function defining the ODE right-hand side f(t,y). + * + * gloc = function defining the approximation g(t,y). + * + * cfn = function to perform communication need for gloc. + * + * Notes: + * + * 1) This header file is included by the user for the definition + * of the CVBBDData type and for needed function prototypes. + * + * 2) The CVBBDPrecInit call includes half-bandwiths mudq and mldq + * to be used in the difference quotient calculation of the + * approximate Jacobian. They need not be the true + * half-bandwidths of the Jacobian of the local block of g, + * when smaller values may provide a greater efficiency. + * Also, the half-bandwidths mukeep and mlkeep of the retained + * banded approximate Jacobian block may be even smaller, + * to reduce storage and computation costs further. + * For all four half-bandwidths, the values need not be the + * same on every processor. + * + * 3) The actual name of the user's f function is passed to + * CVodeInit, and the names of the user's gloc and cfn + * functions are passed to CVBBDPrecInit. + * + * 4) The pointer to the user-defined data block user_data, which is + * set through CVodeSetUserData is also available to the user in + * gloc and cfn. + * + * 5) Optional outputs specific to this module are available by + * way of routines listed below. These include work space sizes + * and the cumulative number of gloc calls. The costs + * associated with this module also include nsetups banded LU + * factorizations, nlinsetups cfn calls, and npsolves banded + * backsolve calls, where nlinsetups and npsolves are + * integrator/CVSPGMR/CVSPBCG/CVSPTFQMR optional outputs. + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Type : CVLocalFn + * ----------------------------------------------------------------- + * The user must supply a function g(t,y) which approximates the + * right-hand side function f for the system y'=f(t,y), and which + * is computed locally (without interprocess communication). + * (The case where g is mathematically identical to f is allowed.) + * The implementation of this function must have type CVLocalFn. + * + * This function takes as input the local vector size Nlocal, the + * independent variable value t, the local real dependent + * variable vector y, and a pointer to the user-defined data + * block user_data. It is to compute the local part of g(t,y) and + * store this in the vector g. + * (Allocation of memory for y and g is handled within the + * preconditioner module.) + * The user_data parameter is the same as that specified by the user + * through the CVodeSetFdata routine. + * + * A CVLocalFn should return 0 if successful, a positive value if + * a recoverable error occurred, and a negative value if an + * unrecoverable error occurred. + * ----------------------------------------------------------------- + */ + +typedef int (*CVLocalFn)(int Nlocal, realtype t, + N_Vector y, N_Vector g, void *user_data); + +/* + * ----------------------------------------------------------------- + * Type : CVCommFn + * ----------------------------------------------------------------- + * The user may supply a function of type CVCommFn which performs + * all interprocess communication necessary to evaluate the + * approximate right-hand side function described above. + * + * This function takes as input the local vector size Nlocal, + * the independent variable value t, the dependent variable + * vector y, and a pointer to the user-defined data block user_data. + * The user_data parameter is the same as that specified by the user + * through the CVodeSetUserData routine. The CVCommFn cfn is + * expected to save communicated data in space defined within the + * structure user_data. Note: A CVCommFn cfn does not have a return value. + * + * Each call to the CVCommFn cfn is preceded by a call to the + * CVRhsFn f with the same (t,y) arguments. Thus cfn can omit any + * communications done by f if relevant to the evaluation of g. + * If all necessary communication was done by f, the user can + * pass NULL for cfn in CVBBDPrecInit (see below). + * + * A CVCommFn should return 0 if successful, a positive value if + * a recoverable error occurred, and a negative value if an + * unrecoverable error occurred. + * ----------------------------------------------------------------- + */ + +typedef int (*CVCommFn)(int Nlocal, realtype t, + N_Vector y, + void *user_data); + +/* + * ----------------------------------------------------------------- + * Function : CVBBDPrecInit + * ----------------------------------------------------------------- + * CVBBDPrecInit allocates and initializes the BBD preconditioner. + * + * The parameters of CVBBDPrecInit are as follows: + * + * cvode_mem is the pointer to the integrator memory. + * + * Nlocal is the length of the local block of the vectors y etc. + * on the current processor. + * + * mudq, mldq are the upper and lower half-bandwidths to be used + * in the difference quotient computation of the local + * Jacobian block. + * + * mukeep, mlkeep are the upper and lower half-bandwidths of the + * retained banded approximation to the local Jacobian + * block. + * + * dqrely is an optional input. It is the relative increment + * in components of y used in the difference quotient + * approximations. To specify the default, pass 0. + * The default is dqrely = sqrt(unit roundoff). + * + * gloc is the name of the user-supplied function g(t,y) that + * approximates f and whose local Jacobian blocks are + * to form the preconditioner. + * + * cfn is the name of the user-defined function that performs + * necessary interprocess communication for the + * execution of gloc. + * + * The return value of CVBBDPrecInit is one of: + * CVSPILS_SUCCESS if no errors occurred + * CVSPILS_MEM_NULL if the integrator memory is NULL + * CVSPILS_LMEM_NULL if the linear solver memory is NULL + * CVSPILS_ILL_INPUT if an input has an illegal value + * CVSPILS_MEM_FAIL if a memory allocation request failed + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVBBDPrecInit(void *cvode_mem, int Nlocal, + int mudq, int mldq, + int mukeep, int mlkeep, + realtype dqrely, + CVLocalFn gloc, CVCommFn cfn); + +/* + * ----------------------------------------------------------------- + * Function : CVBBDPrecReInit + * ----------------------------------------------------------------- + * CVBBDPrecReInit re-initializes the BBDPRE module when solving a + * sequence of problems of the same size with CVSPGMR/CVBBDPRE, + * CVSPBCG/CVBBDPRE, or CVSPTFQMR/CVBBDPRE provided there is no change + * in Nlocal, mukeep, or mlkeep. After solving one problem, and after + * calling CVodeReInit to re-initialize the integrator for a subsequent + * problem, call CVBBDPrecReInit. + * + * All arguments have the same names and meanings as those + * of CVBBDPrecInit. + * + * The return value of CVBBDPrecReInit is one of: + * CVSPILS_SUCCESS if no errors occurred + * CVSPILS_MEM_NULL if the integrator memory is NULL + * CVSPILS_LMEM_NULL if the linear solver memory is NULL + * CVSPILS_PMEM_NULL if the preconditioner memory is NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVBBDPrecReInit(void *cvode_mem, int mudq, int mldq, + realtype dqrely); + +/* + * ----------------------------------------------------------------- + * CVBBDPRE optional output extraction routines + * ----------------------------------------------------------------- + * CVBBDPrecGetWorkSpace returns the BBDPRE real and integer work space + * sizes. + * CVBBDPrecGetNumGfnEvals returns the number of calls to gfn. + * + * The return value of CVBBDPrecGet* is one of: + * CVSPILS_SUCCESS if no errors occurred + * CVSPILS_MEM_NULL if the integrator memory is NULL + * CVSPILS_LMEM_NULL if the linear solver memory is NULL + * CVSPILS_PMEM_NULL if the preconditioner memory is NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVBBDPrecGetWorkSpace(void *cvode_mem, + long int *lenrwBBDP, long int *leniwBBDP); +SUNDIALS_EXPORT int CVBBDPrecGetNumGfnEvals(void *cvode_mem, long int *ngevalsBBDP); + +/* + * ================================================================= + * PART II - backward problems + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Types: CVLocalFnB and CVCommFnB + * ----------------------------------------------------------------- + * Local approximation function and inter-process communication + * function for the BBD preconditioner on the backward phase. + * ----------------------------------------------------------------- + */ + +typedef int (*CVLocalFnB)(int NlocalB, realtype t, + N_Vector y, + N_Vector yB, N_Vector gB, + void *user_dataB); + +typedef int (*CVCommFnB)(int NlocalB, realtype t, + N_Vector y, + N_Vector yB, + void *user_dataB); + +/* + * ----------------------------------------------------------------- + * Functions: CVBBDPrecInitB, CVBBDSp*B, CVBBDPrecReInit + * ----------------------------------------------------------------- + * Interface functions for the CVBBDPRE preconditioner to be used on + * the backward phase. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVBBDPrecInitB(void *cvode_mem, int which, int NlocalB, + int mudqB, int mldqB, + int mukeepB, int mlkeepB, + realtype dqrelyB, + CVLocalFnB glocB, CVCommFnB cfnB); + +SUNDIALS_EXPORT int CVBBDPrecReInitB(void *cvode_mem, int which, + int mudqB, int mldqB, + realtype dqrelyB); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/cvodes_dense.h b/odemex/Parser/CVode/cv_src/include/cvodes_dense.h new file mode 100644 index 0000000..59fe7f7 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/cvodes_dense.h @@ -0,0 +1,64 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.7 $ + * $Date: 2008/04/18 19:42:36 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the dense linear solver CVSDENSE. + * ----------------------------------------------------------------- + */ + +#ifndef _CVSDENSE_H +#define _CVSDENSE_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * Function: CVDense + * ----------------------------------------------------------------- + * A call to the CVDense function links the main integrator with + * the CVSDENSE linear solver. + * + * cvode_mem is the pointer to the integrator memory returned by + * CVodeCreate. + * + * N is the size of the ODE system. + * + * The return value of CVDense is one of: + * CVDLS_SUCCESS if successful + * CVDLS_MEM_NULL if the cvode memory was NULL + * CVDLS_MEM_FAIL if there was a memory allocation failure + * CVDLS_ILL_INPUT if a required vector operation is missing + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVDense(void *cvode_mem, int N); + +/* + * ----------------------------------------------------------------- + * Function: CVDenseB + * ----------------------------------------------------------------- + * CVDenseB links the main CVODE integrator with the CVSDENSE + * linear solver for the backward integration. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVDenseB(void *cvode_mem, int which, int nB); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/cvodes_diag.h b/odemex/Parser/CVode/cv_src/include/cvodes_diag.h new file mode 100644 index 0000000..00bf2a0 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/cvodes_diag.h @@ -0,0 +1,140 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.5 $ + * $Date: 2007/03/22 18:05:50 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the diagonal linear solver CVSDIAG. + * + * + * Part I contains type definitions and function prototypes for using + * CVDIAG on forward problems (IVP integration and/or FSA) + * + * Part II contains type definitions and function prototypes for using + * CVDIAG on adjoint (backward) problems + * ----------------------------------------------------------------- + */ + +#ifndef _CVSDIAG_H +#define _CVSDIAG_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * CVDIAG return values + * ----------------------------------------------------------------- + */ + +#define CVDIAG_SUCCESS 0 +#define CVDIAG_MEM_NULL -1 +#define CVDIAG_LMEM_NULL -2 +#define CVDIAG_ILL_INPUT -3 +#define CVDIAG_MEM_FAIL -4 + +/* Additional last_flag values */ + +#define CVDIAG_INV_FAIL -5 +#define CVDIAG_RHSFUNC_UNRECVR -6 +#define CVDIAG_RHSFUNC_RECVR -7 + +/* Return values for adjoint module */ + +#define CVDIAG_NO_ADJ -101 + +/* + * ----------------------------------------------------------------- + * PART I - forward problems + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Function : CVDiag + * ----------------------------------------------------------------- + * A call to the CVDiag function links the main integrator with + * the CVDIAG linear solver. + * + * cvode_mem is the pointer to the integrator memory returned by + * CVodeCreate. + * + * The return value of CVDiag is one of: + * CVDIAG_SUCCESS if successful + * CVDIAG_MEM_NULL if the cvode memory was NULL + * CVDIAG_MEM_FAIL if there was a memory allocation failure + * CVDIAG_ILL_INPUT if a required vector operation is missing + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVDiag(void *cvode_mem); + +/* + * ----------------------------------------------------------------- + * Optional outputs from the CVDIAG linear solver + * ----------------------------------------------------------------- + * + * CVDiagGetWorkSpace returns the real and integer workspace used + * by CVDIAG. + * CVDiagGetNumRhsEvals returns the number of calls to the user + * f routine due to finite difference Jacobian + * evaluation. + * Note: The number of diagonal approximate + * Jacobians formed is equal to the number of + * CVDiagSetup calls. This number is available + * through CVodeGetNumLinSolvSetups. + * CVDiagGetLastFlag returns the last error flag set by any of + * the CVDIAG interface functions. + * + * The return value of CVDiagGet* is one of: + * CVDIAG_SUCCESS if successful + * CVDIAG_MEM_NULL if the cvode memory was NULL + * CVDIAG_LMEM_NULL if the cvdiag memory was NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVDiagGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS); +SUNDIALS_EXPORT int CVDiagGetNumRhsEvals(void *cvode_mem, long int *nfevalsLS); +SUNDIALS_EXPORT int CVDiagGetLastFlag(void *cvode_mem, int *flag); + +/* + * ----------------------------------------------------------------- + * The following function returns the name of the constant + * associated with a CVDIAG return flag + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT char *CVDiagGetReturnFlagName(int flag); + +/* + * ----------------------------------------------------------------- + * PART II - backward problems + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Function: CVDiagB + * ----------------------------------------------------------------- + * CVDiagB links the main CVODE integrator with the CVDIAG + * linear solver for the backward integration. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVDiagB(void *cvode_mem, int which); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/cvodes_direct.h b/odemex/Parser/CVode/cv_src/include/cvodes_direct.h new file mode 100644 index 0000000..3c0366a --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/cvodes_direct.h @@ -0,0 +1,366 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.7 $ + * $Date: 2008/04/18 19:42:37 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Common header file for the direct linear solvers in CVODES. + * + * Part I contains type definitions and function prototypes for + * using a CVDLS linear solver on forward problems (IVP + * integration and/or FSA) + * + * Part II contains type definitions and function prototypes for + * using a CVDLS linear solver on adjoint (backward) problems + * ----------------------------------------------------------------- + */ + +#ifndef _CVSDLS_H +#define _CVSDLS_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ================================================================= + * C V S D I R E C T C O N S T A N T S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * CVSDIRECT return values + * ----------------------------------------------------------------- + */ + +#define CVDLS_SUCCESS 0 +#define CVDLS_MEM_NULL -1 +#define CVDLS_LMEM_NULL -2 +#define CVDLS_ILL_INPUT -3 +#define CVDLS_MEM_FAIL -4 + +/* Additional last_flag values */ + +#define CVDLS_JACFUNC_UNRECVR -5 +#define CVDLS_JACFUNC_RECVR -6 + +/* Return values for the adjoint module */ + +#define CVDLS_NO_ADJ -101 +#define CVDLS_LMEMB_NULL -102 + +/* + * ================================================================= + * PART I: F O R W A R D P R O B L E M S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * FUNCTION TYPES + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Type: CVDlsDenseJacFn + * ----------------------------------------------------------------- + * + * A dense Jacobian approximation function Jac must be of type + * CVDlsDenseJacFn. Its parameters are: + * + * N is the problem size. + * + * Jac is the dense matrix (of type DlsMat) that will be loaded + * by a CVDlsDenseJacFn with an approximation to the Jacobian + * matrix J = (df_i/dy_j) at the point (t,y). + * + * t is the current value of the independent variable. + * + * y is the current value of the dependent variable vector, + * namely the predicted value of y(t). + * + * fy is the vector f(t,y). + * + * user_data is a pointer to user data - the same as the user_data + * parameter passed to CVodeSetFdata. + * + * tmp1, tmp2, and tmp3 are pointers to memory allocated for + * vectors of length N which can be used by a CVDlsDenseJacFn + * as temporary storage or work space. + * + * A CVDlsDenseJacFn should return 0 if successful, a positive + * value if a recoverable error occurred, and a negative value if + * an unrecoverable error occurred. + * + * ----------------------------------------------------------------- + * + * NOTE: The following are two efficient ways to load a dense Jac: + * (1) (with macros - no explicit data structure references) + * for (j=0; j < Neq; j++) { + * col_j = DENSE_COL(Jac,j); + * for (i=0; i < Neq; i++) { + * generate J_ij = the (i,j)th Jacobian element + * col_j[i] = J_ij; + * } + * } + * (2) (without macros - explicit data structure references) + * for (j=0; j < Neq; j++) { + * col_j = (Jac->data)[j]; + * for (i=0; i < Neq; i++) { + * generate J_ij = the (i,j)th Jacobian element + * col_j[i] = J_ij; + * } + * } + * A third way, using the DENSE_ELEM(A,i,j) macro, is much less + * efficient in general. It is only appropriate for use in small + * problems in which efficiency of access is NOT a major concern. + * + * NOTE: If the user's Jacobian routine needs other quantities, + * they are accessible as follows: hcur (the current stepsize) + * and ewt (the error weight vector) are accessible through + * CVodeGetCurrentStep and CVodeGetErrWeights, respectively + * (see cvode.h). The unit roundoff is available as + * UNIT_ROUNDOFF defined in sundials_types.h. + * + * ----------------------------------------------------------------- + */ + + +typedef int (*CVDlsDenseJacFn)(int N, realtype t, + N_Vector y, N_Vector fy, + DlsMat Jac, void *user_data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +/* + * ----------------------------------------------------------------- + * Type: CVDlsBandJacFn + * ----------------------------------------------------------------- + * + * A band Jacobian approximation function Jac must have the + * prototype given below. Its parameters are: + * + * N is the length of all vector arguments. + * + * mupper is the upper half-bandwidth of the approximate banded + * Jacobian. This parameter is the same as the mupper parameter + * passed by the user to the linear solver initialization function. + * + * mlower is the lower half-bandwidth of the approximate banded + * Jacobian. This parameter is the same as the mlower parameter + * passed by the user to the linear solver initialization function. + * + * t is the current value of the independent variable. + * + * y is the current value of the dependent variable vector, + * namely the predicted value of y(t). + * + * fy is the vector f(t,y). + * + * Jac is the band matrix (of type DlsMat) that will be loaded + * by a CVDlsBandJacFn with an approximation to the Jacobian matrix + * Jac = (df_i/dy_j) at the point (t,y). + * Three efficient ways to load J are: + * + * (1) (with macros - no explicit data structure references) + * for (j=0; j < n; j++) { + * col_j = BAND_COL(Jac,j); + * for (i=j-mupper; i <= j+mlower; i++) { + * generate J_ij = the (i,j)th Jacobian element + * BAND_COL_ELEM(col_j,i,j) = J_ij; + * } + * } + * + * (2) (with BAND_COL macro, but without BAND_COL_ELEM macro) + * for (j=0; j < n; j++) { + * col_j = BAND_COL(Jac,j); + * for (k=-mupper; k <= mlower; k++) { + * generate J_ij = the (i,j)th Jacobian element, i=j+k + * col_j[k] = J_ij; + * } + * } + * + * (3) (without macros - explicit data structure references) + * offset = Jac->smu; + * for (j=0; j < n; j++) { + * col_j = ((Jac->data)[j])+offset; + * for (k=-mupper; k <= mlower; k++) { + * generate J_ij = the (i,j)th Jacobian element, i=j+k + * col_j[k] = J_ij; + * } + * } + * Caution: Jac->smu is generally NOT the same as mupper. + * + * The BAND_ELEM(A,i,j) macro is appropriate for use in small + * problems in which efficiency of access is NOT a major concern. + * + * user_data is a pointer to user data - the same as the user_data + * parameter passed to CVodeSetFdata. + * + * NOTE: If the user's Jacobian routine needs other quantities, + * they are accessible as follows: hcur (the current stepsize) + * and ewt (the error weight vector) are accessible through + * CVodeGetCurrentStep and CVodeGetErrWeights, respectively + * (see cvode.h). The unit roundoff is available as + * UNIT_ROUNDOFF defined in sundials_types.h + * + * tmp1, tmp2, and tmp3 are pointers to memory allocated for + * vectors of length N which can be used by a CVDlsBandJacFn + * as temporary storage or work space. + * + * A CVDlsBandJacFn should return 0 if successful, a positive value + * if a recoverable error occurred, and a negative value if an + * unrecoverable error occurred. + * ----------------------------------------------------------------- + */ + +typedef int (*CVDlsBandJacFn)(int N, int mupper, int mlower, + realtype t, N_Vector y, N_Vector fy, + DlsMat Jac, void *user_data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +/* + * ----------------------------------------------------------------- + * EXPORTED FUNCTIONS + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Optional inputs to the CVDLS linear solver + * ----------------------------------------------------------------- + * + * CVDlsSetDenseJacFn specifies the dense Jacobian approximation + * routine to be used for a direct dense linear solver. + * + * CVDlsSetBandJacFn specifies the band Jacobian approximation + * routine to be used for a direct band linear solver. + * + * By default, a difference quotient approximation, supplied with + * the solver is used. + * + * The return value is one of: + * CVDLS_SUCCESS if successful + * CVDLS_MEM_NULL if the CVODE memory was NULL + * CVDLS_LMEM_NULL if the linear solver memory was NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVDlsSetDenseJacFn(void *cvode_mem, CVDlsDenseJacFn jac); +SUNDIALS_EXPORT int CVDlsSetBandJacFn(void *cvode_mem, CVDlsBandJacFn jac); + +/* + * ----------------------------------------------------------------- + * Optional outputs from the CVSDIRECT linear solver + * ----------------------------------------------------------------- + * + * CVDlsGetWorkSpace returns the real and integer workspace used + * by the direct linear solver. + * CVDlsGetNumJacEvals returns the number of calls made to the + * Jacobian evaluation routine jac. + * CVDlsGetNumRhsEvals returns the number of calls to the user + * f routine due to finite difference Jacobian + * evaluation. + * CVDlsGetLastFlag returns the last error flag set by any of + * the CVSDIRECT interface functions. + * + * The return value of CVDlsGet* is one of: + * CVDLS_SUCCESS if successful + * CVDLS_MEM_NULL if the CVODES memory was NULL + * CVDLS_LMEM_NULL if the linear solver memory was NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVDlsGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS); +SUNDIALS_EXPORT int CVDlsGetNumJacEvals(void *cvode_mem, long int *njevals); +SUNDIALS_EXPORT int CVDlsGetNumRhsEvals(void *cvode_mem, long int *nfevalsLS); +SUNDIALS_EXPORT int CVDlsGetLastFlag(void *cvode_mem, int *flag); + +/* + * ----------------------------------------------------------------- + * The following function returns the name of the constant + * associated with a CVSDIRECT return flag + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT char *CVDlsGetReturnFlagName(int flag); + +/* + * ================================================================= + * PART II: B A C K W A R D P R O B L E M S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * FUNCTION TYPES + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Type: CVDlsDenseJacFnB + * ----------------------------------------------------------------- + * A dense Jacobian approximation function jacB for the adjoint + * (backward) problem must have the prototype given below. + * ----------------------------------------------------------------- + */ + +typedef int (*CVDlsDenseJacFnB)(int nB, realtype t, + N_Vector y, + N_Vector yB, N_Vector fyB, + DlsMat JB, void *user_dataB, + N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B); + +/* + * ----------------------------------------------------------------- + * Type : CVDlsBandJacFnB + * ----------------------------------------------------------------- + * A band Jacobian approximation function jacB for the adjoint + * (backward) problem must have the prototype given below. + * ----------------------------------------------------------------- + */ + +typedef int (*CVDlsBandJacFnB)(int nB, int mupperB, int mlowerB, + realtype t, + N_Vector y, + N_Vector yB, N_Vector fyB, + DlsMat JB, void *user_dataB, + N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B); + +/* + * ----------------------------------------------------------------- + * EXPORTED FUNCTIONS + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Functions: CVDlsSetJacFnB + * ----------------------------------------------------------------- + * CVDlsSetDenseJacFnB and CVDlsSetBandJacFnB specify the dense and + * band, respectively, Jacobian functions to be used by a + * CVSDIRECT linear solver for the bacward integration phase. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVDlsSetDenseJacFnB(void *cvode_mem, int which, + CVDlsDenseJacFnB jacB); +SUNDIALS_EXPORT int CVDlsSetBandJacFnB(void *cvode_mem, int which, + CVDlsBandJacFnB jacB); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/cvodes_lapack.h b/odemex/Parser/CVode/cv_src/include/cvodes_lapack.h new file mode 100644 index 0000000..20eedf8 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/cvodes_lapack.h @@ -0,0 +1,103 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2008/04/18 19:42:37 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Header file for the CVODES dense linear solver CVSLAPACK. + * ----------------------------------------------------------------- + */ + +#ifndef _CVSLAPACK_H +#define _CVSLAPACK_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * Function: CVLapackDense + * ----------------------------------------------------------------- + * A call to the CVLapackDense function links the main integrator + * with the CVSLAPACK linear solver using dense Jacobians. + * + * cvode_mem is the pointer to the integrator memory returned by + * CVodeCreate. + * + * N is the size of the ODE system. + * + * The return value of CVLapackDense is one of: + * CVDLS_SUCCESS if successful + * CVDLS_MEM_NULL if the CVODES memory was NULL + * CVDLS_MEM_FAIL if there was a memory allocation failure + * CVDLS_ILL_INPUT if a required vector operation is missing + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVLapackDense(void *cvode_mem, int N); + +/* + * ----------------------------------------------------------------- + * Function: CVLapackBand + * ----------------------------------------------------------------- + * A call to the CVLapackBand function links the main integrator + * with the CVSLAPACK linear solver using banded Jacobians. + * + * cvode_mem is the pointer to the integrator memory returned by + * CVodeCreate. + * + * N is the size of the ODE system. + * + * mupper is the upper bandwidth of the band Jacobian approximation. + * + * mlower is the lower bandwidth of the band Jacobian approximation. + * + * The return value of CVLapackBand is one of: + * CVDLS_SUCCESS if successful + * CVDLS_MEM_NULL if the CVODES memory was NULL + * CVDLS_MEM_FAIL if there was a memory allocation failure + * CVDLS_ILL_INPUT if a required vector operation is missing or + * if a bandwidth has an illegal value. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVLapackBand(void *cvode_mem, int N, int mupper, int mlower); + +/* + * ----------------------------------------------------------------- + * Function: CVLapackDenseB + * ----------------------------------------------------------------- + * CVLapackDenseB links the main CVODE integrator with the dense + * CVSLAPACK linear solver for the backward integration. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVLapackDenseB(void *cvode_mem, int which, int nB); + +/* + * ----------------------------------------------------------------- + * Function: CVLapackBandB + * ----------------------------------------------------------------- + * CVLapackBandB links the main CVODE integrator with the band + * CVSLAPACK linear solver for the backward integration. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVLapackBandB(void *cvode_mem, int which, + int nB, int mupperB, int mlowerB); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/cvodes_spbcgs.h b/odemex/Parser/CVode/cv_src/include/cvodes_spbcgs.h new file mode 100644 index 0000000..acc56c9 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/cvodes_spbcgs.h @@ -0,0 +1,87 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.4 $ + * $Date: 2007/03/22 18:05:50 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the CVODES scaled preconditioned + * Bi-CGSTAB linear solver, CVSPBCG. + * + * Part I contains function prototypes for using CVSPBCG on forward + * problems (IVP integration and/or FSA) + * + * Part II contains function prototypes for using CVSPBCG on adjoint + * (backward) problems + * ----------------------------------------------------------------- + */ + +#ifndef _CVSSPBCG_H +#define _CVSSPBCG_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * PART I - forward problems + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Function : CVSpbcg + * ----------------------------------------------------------------- + * A call to the CVSpbcg function links the main CVODE integrator + * with the CVSPBCG linear solver. + * + * cvode_mem is the pointer to the integrator memory returned by + * CVodeCreate. + * + * pretype is the type of user preconditioning to be done. + * This must be one of the four enumeration constants + * PREC_NONE, PREC_LEFT, PREC_RIGHT, or PREC_BOTH defined + * in iterative.h. These correspond to no preconditioning, + * left preconditioning only, right preconditioning + * only, and both left and right preconditioning, + * respectively. + * + * maxl is the maximum Krylov dimension. This is an + * optional input to the CVSPBCG solver. Pass 0 to + * use the default value CVSPILS_MAXL=5. + * + * The return value of CVSpbcg is one of: + * CVSPILS_SUCCESS if successful + * CVSPILS_MEM_NULL if the cvode memory was NULL + * CVSPILS_MEM_FAIL if there was a memory allocation failure + * CVSPILS_ILL_INPUT if a required vector operation is missing + * The above constants are defined in cvodes_spils.h + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVSpbcg(void *cvode_mem, int pretype, int maxl); + +/* + * ----------------------------------------------------------------- + * PART II - backward problems + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVSpbcgB(void *cvode_mem, int which, + int pretypeB, int maxlB); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/cvodes_spgmr.h b/odemex/Parser/CVode/cv_src/include/cvodes_spgmr.h new file mode 100644 index 0000000..73f2420 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/cvodes_spgmr.h @@ -0,0 +1,88 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.4 $ + * $Date: 2007/03/22 18:05:50 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the CVODES scaled preconditioned + * GMRES linear solver, CVSPGMR. + * + * Part I contains function prototypes for using CVSPGMR on forward + * problems (IVP integration and/or FSA) + * + * Part II contains function prototypes for using CVSPGMR on adjoint + * (backward) problems + * ----------------------------------------------------------------- + */ + +#ifndef _CVSSPGMR_H +#define _CVSSPGMR_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * PART I - forward problems + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Function : CVSpgmr + * ----------------------------------------------------------------- + * A call to the CVSpgmr function links the main CVODE integrator + * with the CVSPGMR linear solver. + * + * cvode_mem is the pointer to the integrator memory returned by + * CVodeCreate. + * + * pretype is the type of user preconditioning to be done. + * This must be one of the four enumeration constants + * NONE, LEFT, RIGHT, or BOTH defined in iterative.h. + * These correspond to no preconditioning, + * left preconditioning only, right preconditioning + * only, and both left and right preconditioning, + * respectively. + * + * maxl is the maximum Krylov dimension. This is an + * optional input to the CVSPGMR solver. Pass 0 to + * use the default value CVSPILS_MAXL=5. + * + * The return value of CVSpgmr is one of: + * CVSPILS_SUCCESS if successful + * CVSPILS_MEM_NULL if the cvode memory was NULL + * CVSPILS_MEM_FAIL if there was a memory allocation failure + * CVSPILS_ILL_INPUT if a required vector operation is missing + * The above constants are defined in cvodes_spils.h + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVSpgmr(void *cvode_mem, int pretype, int maxl); + +/* + * ----------------------------------------------------------------- + * PART II - backward problems + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVSpgmrB(void *cvode_mem, int which, + int pretypeB, int maxlB); + + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/cvodes_spils.h b/odemex/Parser/CVode/cv_src/include/cvodes_spils.h new file mode 100644 index 0000000..928a1ef --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/cvodes_spils.h @@ -0,0 +1,450 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.11 $ + * $Date: 2008/09/03 20:24:48 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the common header file for the Scaled, Preconditioned + * Iterative Linear Solvers in CVODES. + * + * Part I contains type definitions and functions for using the + * iterative linear solvers on forward problems + * (IVP integration and/or FSA) + * + * Part II contains type definitions and functions for using the + * iterative linear solvers on adjoint (backward) problems + * ----------------------------------------------------------------- + */ + +#ifndef _CVSSPILS_H +#define _CVSSPILS_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * CVSPILS return values + * ----------------------------------------------------------------- + */ + +#define CVSPILS_SUCCESS 0 +#define CVSPILS_MEM_NULL -1 +#define CVSPILS_LMEM_NULL -2 +#define CVSPILS_ILL_INPUT -3 +#define CVSPILS_MEM_FAIL -4 +#define CVSPILS_PMEM_NULL -5 + +/* Return values for the adjoint module */ + +#define CVSPILS_NO_ADJ -101 +#define CVSPILS_LMEMB_NULL -102 + +/* + * ----------------------------------------------------------------- + * CVSPILS solver constants + * ----------------------------------------------------------------- + * CVSPILS_MAXL : default value for the maximum Krylov + * dimension + * + * CVSPILS_MSBPRE : maximum number of steps between + * preconditioner evaluations + * + * CVSPILS_DGMAX : maximum change in gamma between + * preconditioner evaluations + * + * CVSPILS_EPLIN : default value for factor by which the + * tolerance on the nonlinear iteration is + * multiplied to get a tolerance on the linear + * iteration + * ----------------------------------------------------------------- + */ + +#define CVSPILS_MAXL 5 +#define CVSPILS_MSBPRE 50 +#define CVSPILS_DGMAX RCONST(0.2) +#define CVSPILS_EPLIN RCONST(0.05) + +/* + * ----------------------------------------------------------------- + * PART I - forward problems + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Type : CVSpilsPrecSetupFn + * ----------------------------------------------------------------- + * The user-supplied preconditioner setup function PrecSetup and + * the user-supplied preconditioner solve function PrecSolve + * together must define left and right preconditoner matrices + * P1 and P2 (either of which may be trivial), such that the + * product P1*P2 is an approximation to the Newton matrix + * M = I - gamma*J. Here J is the system Jacobian J = df/dy, + * and gamma is a scalar proportional to the integration step + * size h. The solution of systems P z = r, with P = P1 or P2, + * is to be carried out by the PrecSolve function, and PrecSetup + * is to do any necessary setup operations. + * + * The user-supplied preconditioner setup function PrecSetup + * is to evaluate and preprocess any Jacobian-related data + * needed by the preconditioner solve function PrecSolve. + * This might include forming a crude approximate Jacobian, + * and performing an LU factorization on the resulting + * approximation to M. This function will not be called in + * advance of every call to PrecSolve, but instead will be called + * only as often as necessary to achieve convergence within the + * Newton iteration. If the PrecSolve function needs no + * preparation, the PrecSetup function can be NULL. + * + * For greater efficiency, the PrecSetup function may save + * Jacobian-related data and reuse it, rather than generating it + * from scratch. In this case, it should use the input flag jok + * to decide whether to recompute the data, and set the output + * flag *jcurPtr accordingly. + * + * Each call to the PrecSetup function is preceded by a call to + * the RhsFn f with the same (t,y) arguments. Thus the PrecSetup + * function can use any auxiliary data that is computed and + * saved by the f function and made accessible to PrecSetup. + * + * A function PrecSetup must have the prototype given below. + * Its parameters are as follows: + * + * t is the current value of the independent variable. + * + * y is the current value of the dependent variable vector, + * namely the predicted value of y(t). + * + * fy is the vector f(t,y). + * + * jok is an input flag indicating whether Jacobian-related + * data needs to be recomputed, as follows: + * jok == FALSE means recompute Jacobian-related data + * from scratch. + * jok == TRUE means that Jacobian data, if saved from + * the previous PrecSetup call, can be reused + * (with the current value of gamma). + * A Precset call with jok == TRUE can only occur after + * a call with jok == FALSE. + * + * jcurPtr is a pointer to an output integer flag which is + * to be set by PrecSetup as follows: + * Set *jcurPtr = TRUE if Jacobian data was recomputed. + * Set *jcurPtr = FALSE if Jacobian data was not recomputed, + * but saved data was reused. + * + * gamma is the scalar appearing in the Newton matrix. + * + * user_data is a pointer to user data - the same as the user_data + * parameter passed to the CVodeSetUserData function. + * + * tmp1, tmp2, and tmp3 are pointers to memory allocated + * for N_Vectors which can be used by + * CVSpilsPrecSetupFn as temporary storage or + * work space. + * + * NOTE: If the user's preconditioner needs other quantities, + * they are accessible as follows: hcur (the current stepsize) + * and ewt (the error weight vector) are accessible through + * CVodeGetCurrentStep and CVodeGetErrWeights, respectively). + * The unit roundoff is available as UNIT_ROUNDOFF defined in + * sundials_types.h. + * + * Returned value: + * The value to be returned by the PrecSetup function is a flag + * indicating whether it was successful. This value should be + * 0 if successful, + * > 0 for a recoverable error (step will be retried), + * < 0 for an unrecoverable error (integration is halted). + * ----------------------------------------------------------------- + */ + +typedef int (*CVSpilsPrecSetupFn)(realtype t, N_Vector y, N_Vector fy, + booleantype jok, booleantype *jcurPtr, + realtype gamma, void *user_data, + N_Vector tmp1, N_Vector tmp2, + N_Vector tmp3); + +/* + * ----------------------------------------------------------------- + * Type : CVSpilsPrecSolveFn + * ----------------------------------------------------------------- + * The user-supplied preconditioner solve function PrecSolve + * is to solve a linear system P z = r in which the matrix P is + * one of the preconditioner matrices P1 or P2, depending on the + * type of preconditioning chosen. + * + * A function PrecSolve must have the prototype given below. + * Its parameters are as follows: + * + * t is the current value of the independent variable. + * + * y is the current value of the dependent variable vector. + * + * fy is the vector f(t,y). + * + * r is the right-hand side vector of the linear system. + * + * z is the output vector computed by PrecSolve. + * + * gamma is the scalar appearing in the Newton matrix. + * + * delta is an input tolerance for use by PSolve if it uses + * an iterative method in its solution. In that case, + * the residual vector Res = r - P z of the system + * should be made less than delta in weighted L2 norm, + * i.e., sqrt [ Sum (Res[i]*ewt[i])^2 ] < delta. + * Note: the error weight vector ewt can be obtained + * through a call to the routine CVodeGetErrWeights. + * + * lr is an input flag indicating whether PrecSolve is to use + * the left preconditioner P1 or right preconditioner + * P2: lr = 1 means use P1, and lr = 2 means use P2. + * + * user_data is a pointer to user data - the same as the user_data + * parameter passed to the CVodeSetUserData function. + * + * tmp is a pointer to memory allocated for an N_Vector + * which can be used by PSolve for work space. + * + * Returned value: + * The value to be returned by the PrecSolve function is a flag + * indicating whether it was successful. This value should be + * 0 if successful, + * positive for a recoverable error (step will be retried), + * negative for an unrecoverable error (integration is halted). + * ----------------------------------------------------------------- + */ + +typedef int (*CVSpilsPrecSolveFn)(realtype t, N_Vector y, N_Vector fy, + N_Vector r, N_Vector z, + realtype gamma, realtype delta, + int lr, void *user_data, N_Vector tmp); + +/* + * ----------------------------------------------------------------- + * Type : CVSpilsJacTimesVecFn + * ----------------------------------------------------------------- + * The user-supplied function jtimes is to generate the product + * J*v for given v, where J is the Jacobian df/dy, or an + * approximation to it, and v is a given vector. It should return + * 0 if successful a positive value for a recoverable error or + * a negative value for an unrecoverable failure. + * + * A function jtimes must have the prototype given below. Its + * parameters are as follows: + * + * v is the N_Vector to be multiplied by J. + * + * Jv is the output N_Vector containing J*v. + * + * t is the current value of the independent variable. + * + * y is the current value of the dependent variable + * vector. + * + * fy is the vector f(t,y). + * + * user_data is a pointer to user data, the same as the user_data + * parameter passed to the CVodeSetUserData function. + * + * tmp is a pointer to memory allocated for an N_Vector + * which can be used by Jtimes for work space. + * ----------------------------------------------------------------- + */ + +typedef int (*CVSpilsJacTimesVecFn)(N_Vector v, N_Vector Jv, realtype t, + N_Vector y, N_Vector fy, + void *user_data, N_Vector tmp); + + +/* + * ----------------------------------------------------------------- + * Optional inputs to the CVSPILS linear solver + * ----------------------------------------------------------------- + * + * CVSpilsSetPrecType resets the type of preconditioner, pretype, + * from the value previously set. + * This must be one of PREC_NONE, PREC_LEFT, + * PREC_RIGHT, or PREC_BOTH. + * + * CVSpilsSetGSType specifies the type of Gram-Schmidt + * orthogonalization to be used. This must be one of + * the two enumeration constants MODIFIED_GS or + * CLASSICAL_GS defined in iterative.h. These correspond + * to using modified Gram-Schmidt and classical + * Gram-Schmidt, respectively. + * Default value is MODIFIED_GS. + * + * CVSpilsSetMaxl resets the maximum Krylov subspace size, maxl, + * from the value previously set. + * An input value <= 0, gives the default value. + * + * CVSpilsSetEpsLin specifies the factor by which the tolerance on + * the nonlinear iteration is multiplied to get a + * tolerance on the linear iteration. + * Default value is 0.05. + * + * CVSpilsSetPreconditioner specifies the PrecSetup and PrecSolve functions. + * Default is NULL for both arguments (no preconditioning). + * + * CVSpilsSetJacTimesVecFn specifies the jtimes function. Default is to use + * an internal finite difference approximation routine. + * + * The return value of CVSpilsSet* is one of: + * CVSPILS_SUCCESS if successful + * CVSPILS_MEM_NULL if the cvode memory was NULL + * CVSPILS_LMEM_NULL if the linear solver memory was NULL + * CVSPILS_ILL_INPUT if an input has an illegal value + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVSpilsSetPrecType(void *cvode_mem, int pretype); +SUNDIALS_EXPORT int CVSpilsSetGSType(void *cvode_mem, int gstype); +SUNDIALS_EXPORT int CVSpilsSetMaxl(void *cvode_mem, int maxl); +SUNDIALS_EXPORT int CVSpilsSetEpsLin(void *cvode_mem, realtype eplifac); +SUNDIALS_EXPORT int CVSpilsSetPreconditioner(void *cvode_mem, + CVSpilsPrecSetupFn pset, + CVSpilsPrecSolveFn psolve); +SUNDIALS_EXPORT int CVSpilsSetJacTimesVecFn(void *cvode_mem, + CVSpilsJacTimesVecFn jtv); + +/* + * ----------------------------------------------------------------- + * Optional outputs from the CVSPILS linear solver + * ----------------------------------------------------------------- + * CVSpilsGetWorkSpace returns the real and integer workspace used + * by the SPILS module. + * + * CVSpilsGetNumPrecEvals returns the number of preconditioner + * evaluations, i.e. the number of calls made + * to PrecSetup with jok==FALSE. + * + * CVSpilsGetNumPrecSolves returns the number of calls made to + * PrecSolve. + * + * CVSpilsGetNumLinIters returns the number of linear iterations. + * + * CVSpilsGetNumConvFails returns the number of linear + * convergence failures. + * + * CVSpilsGetNumJtimesEvals returns the number of calls to jtimes. + * + * CVSpilsGetNumRhsEvals returns the number of calls to the user + * f routine due to finite difference Jacobian + * times vector evaluation. + * + * CVSpilsGetLastFlag returns the last error flag set by any of + * the CVSPILS interface functions. + * + * The return value of CVSpilsGet* is one of: + * CVSPILS_SUCCESS if successful + * CVSPILS_MEM_NULL if the cvode memory was NULL + * CVSPILS_LMEM_NULL if the linear solver memory was NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVSpilsGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS); +SUNDIALS_EXPORT int CVSpilsGetNumPrecEvals(void *cvode_mem, long int *npevals); +SUNDIALS_EXPORT int CVSpilsGetNumPrecSolves(void *cvode_mem, long int *npsolves); +SUNDIALS_EXPORT int CVSpilsGetNumLinIters(void *cvode_mem, long int *nliters); +SUNDIALS_EXPORT int CVSpilsGetNumConvFails(void *cvode_mem, long int *nlcfails); +SUNDIALS_EXPORT int CVSpilsGetNumJtimesEvals(void *cvode_mem, long int *njvevals); +SUNDIALS_EXPORT int CVSpilsGetNumRhsEvals(void *cvode_mem, long int *nfevalsLS); +SUNDIALS_EXPORT int CVSpilsGetLastFlag(void *cvode_mem, int *flag); + +/* + * ----------------------------------------------------------------- + * The following function returns the name of the constant + * associated with a CVSPILS return flag + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT char *CVSpilsGetReturnFlagName(int flag); + + +/* + * ----------------------------------------------------------------- + * PART II - backward problems + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Type : CVSpilsPrecSetupFnB + * ----------------------------------------------------------------- + * A function PrecSetupB for the adjoint (backward) problem must have + * the prototype given below. + * ----------------------------------------------------------------- + */ + +typedef int (*CVSpilsPrecSetupFnB)(realtype t, N_Vector y, + N_Vector yB, N_Vector fyB, + booleantype jokB, + booleantype *jcurPtrB, realtype gammaB, + void *user_dataB, + N_Vector tmp1B, N_Vector tmp2B, + N_Vector tmp3B); + + +/* + * ----------------------------------------------------------------- + * Type : CVSpilsPrecSolveFnB + * ----------------------------------------------------------------- + * A function PrecSolveB for the adjoint (backward) problem must + * have the prototype given below. + * ----------------------------------------------------------------- + */ + +typedef int (*CVSpilsPrecSolveFnB)(realtype t, N_Vector y, + N_Vector yB, N_Vector fyB, + N_Vector rB, N_Vector zB, + realtype gammaB, realtype deltaB, + int lrB, void *user_dataB, N_Vector tmpB); + +/* + * ----------------------------------------------------------------- + * Type : CVSpilsJacTimesVecFnB + * ----------------------------------------------------------------- + * A function jtimesB for the adjoint (backward) problem must have + * the prototype given below. + * ----------------------------------------------------------------- + */ + +typedef int (*CVSpilsJacTimesVecFnB)(N_Vector vB, N_Vector JvB, realtype t, + N_Vector y, N_Vector yB, N_Vector fyB, + void *jac_dataB, N_Vector tmpB); + +/* + * ----------------------------------------------------------------- + * Functions + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVSpilsSetPrecTypeB(void *cvode_mem, int which, int pretypeB); +SUNDIALS_EXPORT int CVSpilsSetGSTypeB(void *cvode_mem, int which, int gstypeB); +SUNDIALS_EXPORT int CVSpilsSetEpslinB(void *cvode_mem, int which, realtype eplifacB); +SUNDIALS_EXPORT int CVSpilsSetMaxlB(void *cvode_mem, int which, int maxlB); +SUNDIALS_EXPORT int CVSpilsSetPreconditionerB(void *cvode_mem, int which, + CVSpilsPrecSetupFnB psetB, + CVSpilsPrecSolveFnB psolveB); +SUNDIALS_EXPORT int CVSpilsSetJacTimesVecFnB(void *cvode_mem, int which, + CVSpilsJacTimesVecFnB jtvB); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/cvodes_sptfqmr.h b/odemex/Parser/CVode/cv_src/include/cvodes_sptfqmr.h new file mode 100644 index 0000000..2b91a3a --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/cvodes_sptfqmr.h @@ -0,0 +1,88 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.4 $ + * $Date: 2007/03/22 18:05:50 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the CVODES scaled preconditioned TFQMR + * linear solver, CVSPTFQMR. + * + * Part I contains function prototypes for using CVSPTFQMR on forward + * problems (IVP integration and/or FSA) + * + * Part II contains function prototypes for using CVSPTFQMR on adjoint + * (backward) problems + * ----------------------------------------------------------------- + */ + +#ifndef _CVSSPTFQMR_H +#define _CVSSPTFQMR_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * PART I - forward problems + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Function : CVSptfqmr + * ----------------------------------------------------------------- + * A call to the CVSptfqmr function links the main CVODE integrator + * with the CVSPTFQMR linear solver. + * + * cvode_mem is the pointer to the integrator memory returned by + * CVodeCreate. + * + * pretype is the type of user preconditioning to be done. + * This must be one of the four enumeration constants + * PREC_NONE, PREC_LEFT, PREC_RIGHT, or PREC_BOTH defined + * in iterative.h. These correspond to no preconditioning, + * left preconditioning only, right preconditioning + * only, and both left and right preconditioning, + * respectively. + * + * maxl is the maximum Krylov dimension. This is an + * optional input to the CVSPTFQMR solver. Pass 0 to + * use the default value CVSPILS_MAXL=5. + * + * The return value of CVSptfqmr is one of: + * CVSPILS_SUCCESS if successful + * CVSPILS_MEM_NULL if the cvode memory was NULL + * CVSPILS_MEM_FAIL if there was a memory allocation failure + * CVSPILS_ILL_INPUT if a required vector operation is missing + * The above constants are defined in cvodes_spils.h + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVSptfqmr(void *cvode_mem, int pretype, int maxl); + + +/* + * ----------------------------------------------------------------- + * PART II - backward problems + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVSptfqmrB(void *cvode_mem, int which, + int pretypeB, int maxlB); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/nvector/nvector_parallel.h b/odemex/Parser/CVode/cv_src/include/nvector/nvector_parallel.h new file mode 100644 index 0000000..f8a006c --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/nvector/nvector_parallel.h @@ -0,0 +1,314 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban, + * and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the main header file for the MPI-enabled implementation + * of the NVECTOR module. + * + * Part I contains declarations specific to the parallel + * implementation of the supplied NVECTOR module. + * + * Part II defines accessor macros that allow the user to efficiently + * use the type N_Vector without making explicit references to the + * underlying data structure. + * + * Part III contains the prototype for the constructor + * N_VNew_Parallel as well as implementation-specific prototypes + * for various useful vector operations. + * + * Notes: + * + * - The definition of the generic N_Vector structure can be + * found in the header file sundials_nvector.h. + * + * - The definition of the type realtype can be found in the + * header file sundials_types.h, and it may be changed (at the + * configuration stage) according to the user's needs. + * The sundials_types.h file also contains the definition + * for the type booleantype. + * + * - N_Vector arguments to arithmetic vector operations need not + * be distinct. For example, the following call: + * + * N_VLinearSum_Parallel(a,x,b,y,y); + * + * (which stores the result of the operation a*x+b*y in y) + * is legal. + * ----------------------------------------------------------------- + */ + +#ifndef _NVECTOR_PARALLEL_H +#define _NVECTOR_PARALLEL_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +#include + + +/* + * ----------------------------------------------------------------- + * PART I: PARALLEL implementation of N_Vector + * ----------------------------------------------------------------- + */ + +/* define MPI data types */ + +#if defined(SUNDIALS_SINGLE_PRECISION) + +#define PVEC_REAL_MPI_TYPE MPI_FLOAT + +#elif defined(SUNDIALS_DOUBLE_PRECISION) + +#define PVEC_REAL_MPI_TYPE MPI_DOUBLE + +#elif defined(SUNDIALS_EXTENDED_PRECISION) + +#define PVEC_REAL_MPI_TYPE MPI_LONG_DOUBLE + +#endif + +#define PVEC_INTEGER_MPI_TYPE MPI_LONG + +/* parallel implementation of the N_Vector 'content' structure + contains the global and local lengths of the vector, a pointer + to an array of 'realtype components', the MPI communicator, + and a flag indicating ownership of the data */ + +struct _N_VectorContent_Parallel { + long int local_length; /* local vector length */ + long int global_length; /* global vector length */ + booleantype own_data; /* ownership of data */ + realtype *data; /* local data array */ + MPI_Comm comm; /* pointer to MPI communicator */ +}; + +typedef struct _N_VectorContent_Parallel *N_VectorContent_Parallel; + +/* + * ----------------------------------------------------------------- + * PART II: macros NV_CONTENT_P, NV_DATA_P, NV_OWN_DATA_P, + * NV_LOCLENGTH_P, NV_GLOBLENGTH_P,NV_COMM_P, and NV_Ith_P + * ----------------------------------------------------------------- + * In the descriptions below, the following user declarations + * are assumed: + * + * N_Vector v; + * long int v_len, s_len, i; + * + * (1) NV_CONTENT_P + * + * This routines gives access to the contents of the parallel + * vector N_Vector. + * + * The assignment v_cont = NV_CONTENT_P(v) sets v_cont to be + * a pointer to the parallel N_Vector content structure. + * + * (2) NV_DATA_P, NV_OWN_DATA_P, NV_LOCLENGTH_P, NV_GLOBLENGTH_P, + * and NV_COMM_P + * + * These routines give access to the individual parts of + * the content structure of a parallel N_Vector. + * + * The assignment v_data = NV_DATA_P(v) sets v_data to be + * a pointer to the first component of the local data for + * the vector v. The assignment NV_DATA_P(v) = data_v sets + * the component array of v to be data_V by storing the + * pointer data_v. + * + * The assignment v_llen = NV_LOCLENGTH_P(v) sets v_llen to + * be the length of the local part of the vector v. The call + * NV_LOCLENGTH_P(v) = llen_v sets the local length + * of v to be llen_v. + * + * The assignment v_glen = NV_GLOBLENGTH_P(v) sets v_glen to + * be the global length of the vector v. The call + * NV_GLOBLENGTH_P(v) = glen_v sets the global length of v to + * be glen_v. + * + * The assignment v_comm = NV_COMM_P(v) sets v_comm to be the + * MPI communicator of the vector v. The assignment + * NV_COMM_C(v) = comm_v sets the MPI communicator of v to be + * comm_v. + * + * (3) NV_Ith_P + * + * In the following description, the components of the + * local part of an N_Vector are numbered 0..n-1, where n + * is the local length of (the local part of) v. + * + * The assignment r = NV_Ith_P(v,i) sets r to be the value + * of the ith component of the local part of the vector v. + * The assignment NV_Ith_P(v,i) = r sets the value of the + * ith local component of v to be r. + * + * Note: When looping over the components of an N_Vector v, it is + * more efficient to first obtain the component array via + * v_data = NV_DATA_P(v) and then access v_data[i] within the + * loop than it is to use NV_Ith_P(v,i) within the loop. + * ----------------------------------------------------------------- + */ + +#define NV_CONTENT_P(v) ( (N_VectorContent_Parallel)(v->content) ) + +#define NV_LOCLENGTH_P(v) ( NV_CONTENT_P(v)->local_length ) + +#define NV_GLOBLENGTH_P(v) ( NV_CONTENT_P(v)->global_length ) + +#define NV_OWN_DATA_P(v) ( NV_CONTENT_P(v)->own_data ) + +#define NV_DATA_P(v) ( NV_CONTENT_P(v)->data ) + +#define NV_COMM_P(v) ( NV_CONTENT_P(v)->comm ) + +#define NV_Ith_P(v,i) ( NV_DATA_P(v)[i] ) + +/* + * ----------------------------------------------------------------- + * PART III: functions exported by nvector_parallel + * + * CONSTRUCTORS: + * N_VNew_Parallel + * N_VNewEmpty_Parallel + * N_VMake_Parallel + * N_VCloneVectorArray_Parallel + * N_VCloneVectorArrayEmpty_Parallel + * DESTRUCTORS: + * N_VDestroy_Parallel + * N_VDestroyVectorArray_Parallel + * OTHER: + * N_VPrint_Parallel + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Function : N_VNew_Parallel + * ----------------------------------------------------------------- + * This function creates and allocates memory for a parallel vector. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VNew_Parallel(MPI_Comm comm, + long int local_length, + long int global_length); + +/* + * ----------------------------------------------------------------- + * Function : N_VNewEmpty_Parallel + * ----------------------------------------------------------------- + * This function creates a new parallel N_Vector with an empty + * (NULL) data array. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VNewEmpty_Parallel(MPI_Comm comm, + long int local_length, + long int global_length); + +/* + * ----------------------------------------------------------------- + * Function : N_VMake_Parallel + * ----------------------------------------------------------------- + * This function creates and allocates memory for a parallel vector + * with a user-supplied data array. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VMake_Parallel(MPI_Comm comm, + long int local_length, + long int global_length, + realtype *v_data); + +/* + * ----------------------------------------------------------------- + * Function : N_VCloneVectorArray_Parallel + * ----------------------------------------------------------------- + * This function creates an array of 'count' PARALLEL vectors by + * cloning a given vector w. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector *N_VCloneVectorArray_Parallel(int count, N_Vector w); + +/* + * ----------------------------------------------------------------- + * Function : N_VCloneVectorArrayEmpty_Parallel + * ----------------------------------------------------------------- + * This function creates an array of 'count' PARALLEL vectors each + * with an empty (NULL) data array by cloning w. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector *N_VCloneVectorArrayEmpty_Parallel(int count, N_Vector w); + +/* + * ----------------------------------------------------------------- + * Function : N_VDestroyVectorArray_Parallel + * ----------------------------------------------------------------- + * This function frees an array of N_Vector created with + * N_VCloneVectorArray_Parallel or N_VCloneVectorArrayEmpty_Parallel. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void N_VDestroyVectorArray_Parallel(N_Vector *vs, int count); + +/* + * ----------------------------------------------------------------- + * Function : N_VPrint_Parallel + * ----------------------------------------------------------------- + * This function prints the content of a parallel vector to stdout. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void N_VPrint_Parallel(N_Vector v); + +/* + * ----------------------------------------------------------------- + * parallel implementations of the vector operations + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VCloneEmpty_Parallel(N_Vector w); +SUNDIALS_EXPORT N_Vector N_VClone_Parallel(N_Vector w); +SUNDIALS_EXPORT void N_VDestroy_Parallel(N_Vector v); +SUNDIALS_EXPORT void N_VSpace_Parallel(N_Vector v, long int *lrw, long int *liw); +SUNDIALS_EXPORT realtype *N_VGetArrayPointer_Parallel(N_Vector v); +SUNDIALS_EXPORT void N_VSetArrayPointer_Parallel(realtype *v_data, N_Vector v); +SUNDIALS_EXPORT void N_VLinearSum_Parallel(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VConst_Parallel(realtype c, N_Vector z); +SUNDIALS_EXPORT void N_VProd_Parallel(N_Vector x, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VDiv_Parallel(N_Vector x, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VScale_Parallel(realtype c, N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VAbs_Parallel(N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VInv_Parallel(N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VAddConst_Parallel(N_Vector x, realtype b, N_Vector z); +SUNDIALS_EXPORT realtype N_VDotProd_Parallel(N_Vector x, N_Vector y); +SUNDIALS_EXPORT realtype N_VMaxNorm_Parallel(N_Vector x); +SUNDIALS_EXPORT realtype N_VWrmsNorm_Parallel(N_Vector x, N_Vector w); +SUNDIALS_EXPORT realtype N_VWrmsNormMask_Parallel(N_Vector x, N_Vector w, N_Vector id); +SUNDIALS_EXPORT realtype N_VMin_Parallel(N_Vector x); +SUNDIALS_EXPORT realtype N_VWL2Norm_Parallel(N_Vector x, N_Vector w); +SUNDIALS_EXPORT realtype N_VL1Norm_Parallel(N_Vector x); +SUNDIALS_EXPORT void N_VCompare_Parallel(realtype c, N_Vector x, N_Vector z); +SUNDIALS_EXPORT booleantype N_VInvTest_Parallel(N_Vector x, N_Vector z); +SUNDIALS_EXPORT booleantype N_VConstrMask_Parallel(N_Vector c, N_Vector x, N_Vector m); +SUNDIALS_EXPORT realtype N_VMinQuotient_Parallel(N_Vector num, N_Vector denom); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/nvector/nvector_serial.h b/odemex/Parser/CVode/cv_src/include/nvector/nvector_serial.h new file mode 100644 index 0000000..4301a68 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/nvector/nvector_serial.h @@ -0,0 +1,265 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban, + * and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the serial implementation of the + * NVECTOR module. + * + * Part I contains declarations specific to the serial + * implementation of the supplied NVECTOR module. + * + * Part II defines accessor macros that allow the user to + * efficiently use the type N_Vector without making explicit + * references to the underlying data structure. + * + * Part III contains the prototype for the constructor N_VNew_Serial + * as well as implementation-specific prototypes for various useful + * vector operations. + * + * Notes: + * + * - The definition of the generic N_Vector structure can be found + * in the header file sundials_nvector.h. + * + * - The definition of the type 'realtype' can be found in the + * header file sundials_types.h, and it may be changed (at the + * configuration stage) according to the user's needs. + * The sundials_types.h file also contains the definition + * for the type 'booleantype'. + * + * - N_Vector arguments to arithmetic vector operations need not + * be distinct. For example, the following call: + * + * N_VLinearSum_Serial(a,x,b,y,y); + * + * (which stores the result of the operation a*x+b*y in y) + * is legal. + * ----------------------------------------------------------------- + */ + +#ifndef _NVECTOR_SERIAL_H +#define _NVECTOR_SERIAL_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * PART I: SERIAL implementation of N_Vector + * ----------------------------------------------------------------- + */ + +/* serial implementation of the N_Vector 'content' structure + contains the length of the vector, a pointer to an array + of 'realtype' components, and a flag indicating ownership of + the data */ + +struct _N_VectorContent_Serial { + long int length; + booleantype own_data; + realtype *data; +}; + +typedef struct _N_VectorContent_Serial *N_VectorContent_Serial; + +/* + * ----------------------------------------------------------------- + * PART II: macros NV_CONTENT_S, NV_DATA_S, NV_OWN_DATA_S, + * NV_LENGTH_S, and NV_Ith_S + * ----------------------------------------------------------------- + * In the descriptions below, the following user declarations + * are assumed: + * + * N_Vector v; + * long int i; + * + * (1) NV_CONTENT_S + * + * This routines gives access to the contents of the serial + * vector N_Vector. + * + * The assignment v_cont = NV_CONTENT_S(v) sets v_cont to be + * a pointer to the serial N_Vector content structure. + * + * (2) NV_DATA_S NV_OWN_DATA_S and NV_LENGTH_S + * + * These routines give access to the individual parts of + * the content structure of a serial N_Vector. + * + * The assignment v_data = NV_DATA_S(v) sets v_data to be + * a pointer to the first component of v. The assignment + * NV_DATA_S(v) = data_V sets the component array of v to + * be data_v by storing the pointer data_v. + * + * The assignment v_len = NV_LENGTH_S(v) sets v_len to be + * the length of v. The call NV_LENGTH_S(v) = len_v sets + * the length of v to be len_v. + * + * (3) NV_Ith_S + * + * In the following description, the components of an + * N_Vector are numbered 0..n-1, where n is the length of v. + * + * The assignment r = NV_Ith_S(v,i) sets r to be the value of + * the ith component of v. The assignment NV_Ith_S(v,i) = r + * sets the value of the ith component of v to be r. + * + * Note: When looping over the components of an N_Vector v, it is + * more efficient to first obtain the component array via + * v_data = NV_DATA_S(v) and then access v_data[i] within the + * loop than it is to use NV_Ith_S(v,i) within the loop. + * ----------------------------------------------------------------- + */ + +#define NV_CONTENT_S(v) ( (N_VectorContent_Serial)(v->content) ) + +#define NV_LENGTH_S(v) ( NV_CONTENT_S(v)->length ) + +#define NV_OWN_DATA_S(v) ( NV_CONTENT_S(v)->own_data ) + +#define NV_DATA_S(v) ( NV_CONTENT_S(v)->data ) + +#define NV_Ith_S(v,i) ( NV_DATA_S(v)[i] ) + +/* + * ----------------------------------------------------------------- + * PART III: functions exported by nvector_serial + * + * CONSTRUCTORS: + * N_VNew_Serial + * N_VNewEmpty_Serial + * N_VMake_Serial + * N_VCloneVectorArray_Serial + * N_VCloneVectorArrayEmpty_Serial + * DESTRUCTORS: + * N_VDestroy_Serial + * N_VDestroyVectorArray_Serial + * OTHER: + * N_VPrint_Serial + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Function : N_VNew_Serial + * ----------------------------------------------------------------- + * This function creates and allocates memory for a serial vector. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VNew_Serial(long int vec_length); + +/* + * ----------------------------------------------------------------- + * Function : N_VNewEmpty_Serial + * ----------------------------------------------------------------- + * This function creates a new serial N_Vector with an empty (NULL) + * data array. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VNewEmpty_Serial(long int vec_length); + +/* + * ----------------------------------------------------------------- + * Function : N_VMake_Serial + * ----------------------------------------------------------------- + * This function creates and allocates memory for a serial vector + * with a user-supplied data array. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VMake_Serial(long int vec_length, realtype *v_data); + +/* + * ----------------------------------------------------------------- + * Function : N_VCloneVectorArray_Serial + * ----------------------------------------------------------------- + * This function creates an array of 'count' SERIAL vectors by + * cloning a given vector w. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector *N_VCloneVectorArray_Serial(int count, N_Vector w); + +/* + * ----------------------------------------------------------------- + * Function : N_VCloneVectorArrayEmpty_Serial + * ----------------------------------------------------------------- + * This function creates an array of 'count' SERIAL vectors each + * with an empty (NULL) data array by cloning w. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector *N_VCloneVectorArrayEmpty_Serial(int count, N_Vector w); + +/* + * ----------------------------------------------------------------- + * Function : N_VDestroyVectorArray_Serial + * ----------------------------------------------------------------- + * This function frees an array of SERIAL vectors created with + * N_VCloneVectorArray_Serial or N_VCloneVectorArrayEmpty_Serial. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void N_VDestroyVectorArray_Serial(N_Vector *vs, int count); + +/* + * ----------------------------------------------------------------- + * Function : N_VPrint_Serial + * ----------------------------------------------------------------- + * This function prints the content of a serial vector to stdout. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void N_VPrint_Serial(N_Vector v); + +/* + * ----------------------------------------------------------------- + * serial implementations of various useful vector operations + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VCloneEmpty_Serial(N_Vector w); +SUNDIALS_EXPORT N_Vector N_VClone_Serial(N_Vector w); +SUNDIALS_EXPORT void N_VDestroy_Serial(N_Vector v); +SUNDIALS_EXPORT void N_VSpace_Serial(N_Vector v, long int *lrw, long int *liw); +SUNDIALS_EXPORT realtype *N_VGetArrayPointer_Serial(N_Vector v); +SUNDIALS_EXPORT void N_VSetArrayPointer_Serial(realtype *v_data, N_Vector v); +SUNDIALS_EXPORT void N_VLinearSum_Serial(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VConst_Serial(realtype c, N_Vector z); +SUNDIALS_EXPORT void N_VProd_Serial(N_Vector x, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VDiv_Serial(N_Vector x, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VScale_Serial(realtype c, N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VAbs_Serial(N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VInv_Serial(N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VAddConst_Serial(N_Vector x, realtype b, N_Vector z); +SUNDIALS_EXPORT realtype N_VDotProd_Serial(N_Vector x, N_Vector y); +SUNDIALS_EXPORT realtype N_VMaxNorm_Serial(N_Vector x); +SUNDIALS_EXPORT realtype N_VWrmsNorm_Serial(N_Vector x, N_Vector w); +SUNDIALS_EXPORT realtype N_VWrmsNormMask_Serial(N_Vector x, N_Vector w, N_Vector id); +SUNDIALS_EXPORT realtype N_VMin_Serial(N_Vector x); +SUNDIALS_EXPORT realtype N_VWL2Norm_Serial(N_Vector x, N_Vector w); +SUNDIALS_EXPORT realtype N_VL1Norm_Serial(N_Vector x); +SUNDIALS_EXPORT void N_VCompare_Serial(realtype c, N_Vector x, N_Vector z); +SUNDIALS_EXPORT booleantype N_VInvTest_Serial(N_Vector x, N_Vector z); +SUNDIALS_EXPORT booleantype N_VConstrMask_Serial(N_Vector c, N_Vector x, N_Vector m); +SUNDIALS_EXPORT realtype N_VMinQuotient_Serial(N_Vector num, N_Vector denom); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/nvector_serial.h b/odemex/Parser/CVode/cv_src/include/nvector_serial.h new file mode 100644 index 0000000..4301a68 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/nvector_serial.h @@ -0,0 +1,265 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban, + * and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the serial implementation of the + * NVECTOR module. + * + * Part I contains declarations specific to the serial + * implementation of the supplied NVECTOR module. + * + * Part II defines accessor macros that allow the user to + * efficiently use the type N_Vector without making explicit + * references to the underlying data structure. + * + * Part III contains the prototype for the constructor N_VNew_Serial + * as well as implementation-specific prototypes for various useful + * vector operations. + * + * Notes: + * + * - The definition of the generic N_Vector structure can be found + * in the header file sundials_nvector.h. + * + * - The definition of the type 'realtype' can be found in the + * header file sundials_types.h, and it may be changed (at the + * configuration stage) according to the user's needs. + * The sundials_types.h file also contains the definition + * for the type 'booleantype'. + * + * - N_Vector arguments to arithmetic vector operations need not + * be distinct. For example, the following call: + * + * N_VLinearSum_Serial(a,x,b,y,y); + * + * (which stores the result of the operation a*x+b*y in y) + * is legal. + * ----------------------------------------------------------------- + */ + +#ifndef _NVECTOR_SERIAL_H +#define _NVECTOR_SERIAL_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * PART I: SERIAL implementation of N_Vector + * ----------------------------------------------------------------- + */ + +/* serial implementation of the N_Vector 'content' structure + contains the length of the vector, a pointer to an array + of 'realtype' components, and a flag indicating ownership of + the data */ + +struct _N_VectorContent_Serial { + long int length; + booleantype own_data; + realtype *data; +}; + +typedef struct _N_VectorContent_Serial *N_VectorContent_Serial; + +/* + * ----------------------------------------------------------------- + * PART II: macros NV_CONTENT_S, NV_DATA_S, NV_OWN_DATA_S, + * NV_LENGTH_S, and NV_Ith_S + * ----------------------------------------------------------------- + * In the descriptions below, the following user declarations + * are assumed: + * + * N_Vector v; + * long int i; + * + * (1) NV_CONTENT_S + * + * This routines gives access to the contents of the serial + * vector N_Vector. + * + * The assignment v_cont = NV_CONTENT_S(v) sets v_cont to be + * a pointer to the serial N_Vector content structure. + * + * (2) NV_DATA_S NV_OWN_DATA_S and NV_LENGTH_S + * + * These routines give access to the individual parts of + * the content structure of a serial N_Vector. + * + * The assignment v_data = NV_DATA_S(v) sets v_data to be + * a pointer to the first component of v. The assignment + * NV_DATA_S(v) = data_V sets the component array of v to + * be data_v by storing the pointer data_v. + * + * The assignment v_len = NV_LENGTH_S(v) sets v_len to be + * the length of v. The call NV_LENGTH_S(v) = len_v sets + * the length of v to be len_v. + * + * (3) NV_Ith_S + * + * In the following description, the components of an + * N_Vector are numbered 0..n-1, where n is the length of v. + * + * The assignment r = NV_Ith_S(v,i) sets r to be the value of + * the ith component of v. The assignment NV_Ith_S(v,i) = r + * sets the value of the ith component of v to be r. + * + * Note: When looping over the components of an N_Vector v, it is + * more efficient to first obtain the component array via + * v_data = NV_DATA_S(v) and then access v_data[i] within the + * loop than it is to use NV_Ith_S(v,i) within the loop. + * ----------------------------------------------------------------- + */ + +#define NV_CONTENT_S(v) ( (N_VectorContent_Serial)(v->content) ) + +#define NV_LENGTH_S(v) ( NV_CONTENT_S(v)->length ) + +#define NV_OWN_DATA_S(v) ( NV_CONTENT_S(v)->own_data ) + +#define NV_DATA_S(v) ( NV_CONTENT_S(v)->data ) + +#define NV_Ith_S(v,i) ( NV_DATA_S(v)[i] ) + +/* + * ----------------------------------------------------------------- + * PART III: functions exported by nvector_serial + * + * CONSTRUCTORS: + * N_VNew_Serial + * N_VNewEmpty_Serial + * N_VMake_Serial + * N_VCloneVectorArray_Serial + * N_VCloneVectorArrayEmpty_Serial + * DESTRUCTORS: + * N_VDestroy_Serial + * N_VDestroyVectorArray_Serial + * OTHER: + * N_VPrint_Serial + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Function : N_VNew_Serial + * ----------------------------------------------------------------- + * This function creates and allocates memory for a serial vector. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VNew_Serial(long int vec_length); + +/* + * ----------------------------------------------------------------- + * Function : N_VNewEmpty_Serial + * ----------------------------------------------------------------- + * This function creates a new serial N_Vector with an empty (NULL) + * data array. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VNewEmpty_Serial(long int vec_length); + +/* + * ----------------------------------------------------------------- + * Function : N_VMake_Serial + * ----------------------------------------------------------------- + * This function creates and allocates memory for a serial vector + * with a user-supplied data array. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VMake_Serial(long int vec_length, realtype *v_data); + +/* + * ----------------------------------------------------------------- + * Function : N_VCloneVectorArray_Serial + * ----------------------------------------------------------------- + * This function creates an array of 'count' SERIAL vectors by + * cloning a given vector w. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector *N_VCloneVectorArray_Serial(int count, N_Vector w); + +/* + * ----------------------------------------------------------------- + * Function : N_VCloneVectorArrayEmpty_Serial + * ----------------------------------------------------------------- + * This function creates an array of 'count' SERIAL vectors each + * with an empty (NULL) data array by cloning w. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector *N_VCloneVectorArrayEmpty_Serial(int count, N_Vector w); + +/* + * ----------------------------------------------------------------- + * Function : N_VDestroyVectorArray_Serial + * ----------------------------------------------------------------- + * This function frees an array of SERIAL vectors created with + * N_VCloneVectorArray_Serial or N_VCloneVectorArrayEmpty_Serial. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void N_VDestroyVectorArray_Serial(N_Vector *vs, int count); + +/* + * ----------------------------------------------------------------- + * Function : N_VPrint_Serial + * ----------------------------------------------------------------- + * This function prints the content of a serial vector to stdout. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void N_VPrint_Serial(N_Vector v); + +/* + * ----------------------------------------------------------------- + * serial implementations of various useful vector operations + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VCloneEmpty_Serial(N_Vector w); +SUNDIALS_EXPORT N_Vector N_VClone_Serial(N_Vector w); +SUNDIALS_EXPORT void N_VDestroy_Serial(N_Vector v); +SUNDIALS_EXPORT void N_VSpace_Serial(N_Vector v, long int *lrw, long int *liw); +SUNDIALS_EXPORT realtype *N_VGetArrayPointer_Serial(N_Vector v); +SUNDIALS_EXPORT void N_VSetArrayPointer_Serial(realtype *v_data, N_Vector v); +SUNDIALS_EXPORT void N_VLinearSum_Serial(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VConst_Serial(realtype c, N_Vector z); +SUNDIALS_EXPORT void N_VProd_Serial(N_Vector x, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VDiv_Serial(N_Vector x, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VScale_Serial(realtype c, N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VAbs_Serial(N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VInv_Serial(N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VAddConst_Serial(N_Vector x, realtype b, N_Vector z); +SUNDIALS_EXPORT realtype N_VDotProd_Serial(N_Vector x, N_Vector y); +SUNDIALS_EXPORT realtype N_VMaxNorm_Serial(N_Vector x); +SUNDIALS_EXPORT realtype N_VWrmsNorm_Serial(N_Vector x, N_Vector w); +SUNDIALS_EXPORT realtype N_VWrmsNormMask_Serial(N_Vector x, N_Vector w, N_Vector id); +SUNDIALS_EXPORT realtype N_VMin_Serial(N_Vector x); +SUNDIALS_EXPORT realtype N_VWL2Norm_Serial(N_Vector x, N_Vector w); +SUNDIALS_EXPORT realtype N_VL1Norm_Serial(N_Vector x); +SUNDIALS_EXPORT void N_VCompare_Serial(realtype c, N_Vector x, N_Vector z); +SUNDIALS_EXPORT booleantype N_VInvTest_Serial(N_Vector x, N_Vector z); +SUNDIALS_EXPORT booleantype N_VConstrMask_Serial(N_Vector c, N_Vector x, N_Vector m); +SUNDIALS_EXPORT realtype N_VMinQuotient_Serial(N_Vector num, N_Vector denom); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/sundials/sundials_band.h b/odemex/Parser/CVode/cv_src/include/sundials/sundials_band.h new file mode 100644 index 0000000..95ee54c --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials/sundials_band.h @@ -0,0 +1,153 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.5 $ + * $Date: 2009/02/17 02:39:26 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for a generic BAND linear solver + * package, based on the DlsMat type defined in sundials_direct.h. + * + * There are two sets of band solver routines listed in + * this file: one set uses type DlsMat defined below and the + * other set uses the type realtype ** for band matrix arguments. + * Routines that work with the type DlsMat begin with "Band". + * Routines that work with realtype ** begin with "band" + * ----------------------------------------------------------------- + */ + +#ifndef _SUNDIALS_BAND_H +#define _SUNDIALS_BAND_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Function : BandGBTRF + * ----------------------------------------------------------------- + * Usage : ier = BandGBTRF(A, p); + * if (ier != 0) ... A is singular + * ----------------------------------------------------------------- + * BandGBTRF performs the LU factorization of the N by N band + * matrix A. This is done using standard Gaussian elimination + * with partial pivoting. + * + * A successful LU factorization leaves the "matrix" A and the + * pivot array p with the following information: + * + * (1) p[k] contains the row number of the pivot element chosen + * at the beginning of elimination step k, k=0, 1, ..., N-1. + * + * (2) If the unique LU factorization of A is given by PA = LU, + * where P is a permutation matrix, L is a lower triangular + * matrix with all 1's on the diagonal, and U is an upper + * triangular matrix, then the upper triangular part of A + * (including its diagonal) contains U and the strictly lower + * triangular part of A contains the multipliers, I-L. + * + * BandGBTRF returns 0 if successful. Otherwise it encountered + * a zero diagonal element during the factorization. In this case + * it returns the column index (numbered from one) at which + * it encountered the zero. + * + * Important Note: A must be allocated to accommodate the increase + * in upper bandwidth that occurs during factorization. If + * mathematically, A is a band matrix with upper bandwidth mu and + * lower bandwidth ml, then the upper triangular factor U can + * have upper bandwidth as big as smu = MIN(n-1,mu+ml). The lower + * triangular factor L has lower bandwidth ml. Allocate A with + * call A = BandAllocMat(N,mu,ml,smu), where mu, ml, and smu are + * as defined above. The user does not have to zero the "extra" + * storage allocated for the purpose of factorization. This will + * handled by the BandGBTRF routine. + * + * BandGBTRF is only a wrapper around bandGBTRF. All work is done + * in bandGBTRF works directly on the data in the DlsMat A (i.e., + * the field cols). + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int BandGBTRF(DlsMat A, int *p); +SUNDIALS_EXPORT int bandGBTRF(realtype **a, int n, int mu, int ml, int smu, int *p); + +/* + * ----------------------------------------------------------------- + * Function : BandGBTRS + * ----------------------------------------------------------------- + * Usage : BandGBTRS(A, p, b); + * ----------------------------------------------------------------- + * BandGBTRS solves the N-dimensional system A x = b using + * the LU factorization in A and the pivot information in p + * computed in BandGBTRF. The solution x is returned in b. This + * routine cannot fail if the corresponding call to BandGBTRF + * did not fail. + * + * BandGBTRS is only a wrapper around bandGBTRS which does all the + * work directly on the data in the DlsMat A (i.e., the field cols). + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void BandGBTRS(DlsMat A, int *p, realtype *b); +SUNDIALS_EXPORT void bandGBTRS(realtype **a, int n, int smu, int ml, int *p, realtype *b); + +/* + * ----------------------------------------------------------------- + * Function : BandCopy + * ----------------------------------------------------------------- + * Usage : BandCopy(A, B, copymu, copyml); + * ----------------------------------------------------------------- + * BandCopy copies the submatrix with upper and lower bandwidths + * copymu, copyml of the N by N band matrix A into the N by N + * band matrix B. + * + * BandCopy is a wrapper around bandCopy which accesses the data + * in the DlsMat A and B (i.e. the fields cols) + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void BandCopy(DlsMat A, DlsMat B, int copymu, int copyml); +SUNDIALS_EXPORT void bandCopy(realtype **a, realtype **b, int n, int a_smu, int b_smu, + int copymu, int copyml); + +/* + * ----------------------------------------------------------------- + * Function: BandScale + * ----------------------------------------------------------------- + * Usage : BandScale(c, A); + * ----------------------------------------------------------------- + * A(i,j) <- c*A(i,j), j-(A->mu) <= i <= j+(A->ml). + * + * BandScale is a wrapper around bandScale which performs the actual + * scaling by accessing the data in the DlsMat A (i.e. the field + * cols). + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void BandScale(realtype c, DlsMat A); +SUNDIALS_EXPORT void bandScale(realtype c, realtype **a, int n, int mu, int ml, int smu); + +/* + * ----------------------------------------------------------------- + * Function: bandAddIdentity + * ----------------------------------------------------------------- + * bandAddIdentity adds the identity matrix to the n-by-n matrix + * stored in the realtype** arrays. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void bandAddIdentity(realtype **a, int n, int smu); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/sundials/sundials_config.h b/odemex/Parser/CVode/cv_src/include/sundials/sundials_config.h new file mode 100644 index 0000000..3ba4096 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials/sundials_config.h @@ -0,0 +1,80 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.4 $ + * $Date: 2007/12/19 20:34:00 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + *------------------------------------------------------------------ + * SUNDIALS configuration header file + *------------------------------------------------------------------ + */ + +#include "winDefine.h" + +/* Define SUNDIALS version number */ +#define SUNDIALS_PACKAGE_VERSION "2.4.0" + +/* FCMIX: Define Fortran name-mangling macro for C identifiers. + * Depending on the inferred scheme, one of the following six + * macros will be defined: + * #define SUNDIALS_F77_FUNC(name,NAME) name + * #define SUNDIALS_F77_FUNC(name,NAME) name ## _ + * #define SUNDIALS_F77_FUNC(name,NAME) name ## __ + * #define SUNDIALS_F77_FUNC(name,NAME) NAME + * #define SUNDIALS_F77_FUNC(name,NAME) NAME ## _ + * #define SUNDIALS_F77_FUNC(name,NAME) NAME ## __ + */ + + +/* FCMIX: Define Fortran name-mangling macro for C identifiers + * which contain underscores. + */ + + +/* Define precision of SUNDIALS data type 'realtype' + * Depending on the precision level, one of the following + * three macros will be defined: + * #define SUNDIALS_SINGLE_PRECISION 1 + * #define SUNDIALS_DOUBLE_PRECISION 1 + * #define SUNDIALS_EXTENDED_PRECISION 1 + */ +#define SUNDIALS_DOUBLE_PRECISION 1 + +/* Use generic math functions + * If it was decided that generic math functions can be used, then + * #define SUNDIALS_USE_GENERIC_MATH 1 + * otherwise + * #define SUNDIALS_USE_GENERIC_MATH 0 + */ + + +/* Blas/Lapack available + * If working libraries for Blas/lapack support were found, then + * #define SUNDIALS_BLAS_LAPACK 1 + * otherwise + * #define SUNDIALS_BLAS_LAPACK 0 + */ +#define SUNDIALS_BLAS_LAPACK 1 + +/* FNVECTOR: Allow user to specify different MPI communicator + * If it was found that the MPI implementation supports MPI_Comm_f2c, then + * #define SUNDIALS_MPI_COMM_F2C 1 + * otherwise + * #define SUNDIALS_MPI_COMM_F2C 0 + */ + + +/* Mark SUNDIALS API functions for export/import + * When building shared SUNDIALS libraries under Windows, use + * #define SUNDIALS_EXPORT __declspec(dllexport) + * When linking to shared SUNDIALS libraries under Windows, use + * #define SUNDIALS_EXPORT __declspec(dllimport) + * In all other cases (other platforms or static libraries under + * Windows), the SUNDIALS_EXPORT macro is empty + */ +#define SUNDIALS_EXPORT diff --git a/odemex/Parser/CVode/cv_src/include/sundials/sundials_config.in b/odemex/Parser/CVode/cv_src/include/sundials/sundials_config.in new file mode 100644 index 0000000..f43aeae --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials/sundials_config.in @@ -0,0 +1,78 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.4 $ + * $Date: 2007/12/19 20:34:00 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + *------------------------------------------------------------------ + * SUNDIALS configuration header file + *------------------------------------------------------------------ + */ + +/* Define SUNDIALS version number */ +#define SUNDIALS_PACKAGE_VERSION "@PACKAGE_VERSION@" + +/* FCMIX: Define Fortran name-mangling macro for C identifiers. + * Depending on the inferred scheme, one of the following six + * macros will be defined: + * #define SUNDIALS_F77_FUNC(name,NAME) name + * #define SUNDIALS_F77_FUNC(name,NAME) name ## _ + * #define SUNDIALS_F77_FUNC(name,NAME) name ## __ + * #define SUNDIALS_F77_FUNC(name,NAME) NAME + * #define SUNDIALS_F77_FUNC(name,NAME) NAME ## _ + * #define SUNDIALS_F77_FUNC(name,NAME) NAME ## __ + */ +@F77_MANGLE_MACRO1@ + +/* FCMIX: Define Fortran name-mangling macro for C identifiers + * which contain underscores. + */ +@F77_MANGLE_MACRO2@ + +/* Define precision of SUNDIALS data type 'realtype' + * Depending on the precision level, one of the following + * three macros will be defined: + * #define SUNDIALS_SINGLE_PRECISION 1 + * #define SUNDIALS_DOUBLE_PRECISION 1 + * #define SUNDIALS_EXTENDED_PRECISION 1 + */ +@PRECISION_LEVEL@ + +/* Use generic math functions + * If it was decided that generic math functions can be used, then + * #define SUNDIALS_USE_GENERIC_MATH 1 + * otherwise + * #define SUNDIALS_USE_GENERIC_MATH 0 + */ +@GENERIC_MATH_LIB@ + +/* Blas/Lapack available + * If working libraries for Blas/lapack support were found, then + * #define SUNDIALS_BLAS_LAPACK 1 + * otherwise + * #define SUNDIALS_BLAS_LAPACK 0 + */ +@BLAS_LAPACK_MACRO@ + +/* FNVECTOR: Allow user to specify different MPI communicator + * If it was found that the MPI implementation supports MPI_Comm_f2c, then + * #define SUNDIALS_MPI_COMM_F2C 1 + * otherwise + * #define SUNDIALS_MPI_COMM_F2C 0 + */ +@F77_MPI_COMM_F2C@ + +/* Mark SUNDIALS API functions for export/import + * When building shared SUNDIALS libraries under Windows, use + * #define SUNDIALS_EXPORT __declspec(dllexport) + * When linking to shared SUNDIALS libraries under Windows, use + * #define SUNDIALS_EXPORT __declspec(dllimport) + * In all other cases (other platforms or static libraries under + * Windows), the SUNDIALS_EXPORT macro is empty + */ +@SUNDIALS_EXPORT@ diff --git a/odemex/Parser/CVode/cv_src/include/sundials/sundials_dense.h b/odemex/Parser/CVode/cv_src/include/sundials/sundials_dense.h new file mode 100644 index 0000000..a3b1431 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials/sundials_dense.h @@ -0,0 +1,187 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.7 $ + * $Date: 2009/02/17 02:39:26 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for a generic package of DENSE matrix + * operations, based on the DlsMat type defined in sundials_direct.h. + * + * There are two sets of dense solver routines listed in + * this file: one set uses type DlsMat defined below and the + * other set uses the type realtype ** for dense matrix arguments. + * Routines that work with the type DlsMat begin with "Dense". + * Routines that work with realtype** begin with "dense". + * ----------------------------------------------------------------- + */ + +#ifndef _SUNDIALS_DENSE_H +#define _SUNDIALS_DENSE_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Functions: DenseGETRF and DenseGETRS + * ----------------------------------------------------------------- + * DenseGETRF performs the LU factorization of the M by N dense + * matrix A. This is done using standard Gaussian elimination + * with partial (row) pivoting. Note that this applies only + * to matrices with M >= N and full column rank. + * + * A successful LU factorization leaves the matrix A and the + * pivot array p with the following information: + * + * (1) p[k] contains the row number of the pivot element chosen + * at the beginning of elimination step k, k=0, 1, ..., N-1. + * + * (2) If the unique LU factorization of A is given by PA = LU, + * where P is a permutation matrix, L is a lower trapezoidal + * matrix with all 1's on the diagonal, and U is an upper + * triangular matrix, then the upper triangular part of A + * (including its diagonal) contains U and the strictly lower + * trapezoidal part of A contains the multipliers, I-L. + * + * For square matrices (M=N), L is unit lower triangular. + * + * DenseGETRF returns 0 if successful. Otherwise it encountered + * a zero diagonal element during the factorization. In this case + * it returns the column index (numbered from one) at which + * it encountered the zero. + * + * DenseGETRS solves the N-dimensional system A x = b using + * the LU factorization in A and the pivot information in p + * computed in DenseGETRF. The solution x is returned in b. This + * routine cannot fail if the corresponding call to DenseGETRF + * did not fail. + * DenseGETRS does NOT check for a square matrix! + * + * ----------------------------------------------------------------- + * DenseGETRF and DenseGETRS are simply wrappers around denseGETRF + * and denseGETRS, respectively, which perform all the work by + * directly accessing the data in the DlsMat A (i.e. the field cols) + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int DenseGETRF(DlsMat A, int *p); +SUNDIALS_EXPORT void DenseGETRS(DlsMat A, int *p, realtype *b); + +SUNDIALS_EXPORT int denseGETRF(realtype **a, int m, int n, int *p); +SUNDIALS_EXPORT void denseGETRS(realtype **a, int n, int *p, realtype *b); + +/* + * ----------------------------------------------------------------- + * Functions : DensePOTRF and DensePOTRS + * ----------------------------------------------------------------- + * DensePOTRF computes the Cholesky factorization of a real symmetric + * positive definite matrix A. + * ----------------------------------------------------------------- + * DensePOTRS solves a system of linear equations A*X = B with a + * symmetric positive definite matrix A using the Cholesky factorization + * A = L*L**T computed by DensePOTRF. + * + * ----------------------------------------------------------------- + * DensePOTRF and DensePOTRS are simply wrappers around densePOTRF + * and densePOTRS, respectively, which perform all the work by + * directly accessing the data in the DlsMat A (i.e. the field cols) + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int DensePOTRF(DlsMat A); +SUNDIALS_EXPORT void DensePOTRS(DlsMat A, realtype *b); + +SUNDIALS_EXPORT int densePOTRF(realtype **a, int m); +SUNDIALS_EXPORT void densePOTRS(realtype **a, int m, realtype *b); + +/* + * ----------------------------------------------------------------- + * Functions : DenseGEQRF and DenseORMQR + * ----------------------------------------------------------------- + * DenseGEQRF computes a QR factorization of a real M-by-N matrix A: + * A = Q * R (with M>= N). + * + * DenseGEQRF requires a temporary work vector wrk of length M. + * ----------------------------------------------------------------- + * DenseORMQR computes the product w = Q * v where Q is a real + * orthogonal matrix defined as the product of k elementary reflectors + * + * Q = H(1) H(2) . . . H(k) + * + * as returned by DenseGEQRF. Q is an M-by-N matrix, v is a vector + * of length N and w is a vector of length M (with M>=N). + * + * DenseORMQR requires a temporary work vector wrk of length M. + * + * ----------------------------------------------------------------- + * DenseGEQRF and DenseORMQR are simply wrappers around denseGEQRF + * and denseORMQR, respectively, which perform all the work by + * directly accessing the data in the DlsMat A (i.e. the field cols) + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int DenseGEQRF(DlsMat A, realtype *beta, realtype *wrk); +SUNDIALS_EXPORT int DenseORMQR(DlsMat A, realtype *beta, realtype *vn, realtype *vm, + realtype *wrk); + +SUNDIALS_EXPORT int denseGEQRF(realtype **a, int m, int n, realtype *beta, realtype *v); +SUNDIALS_EXPORT int denseORMQR(realtype **a, int m, int n, realtype *beta, + realtype *v, realtype *w, realtype *wrk); + +/* + * ----------------------------------------------------------------- + * Function : DenseCopy + * ----------------------------------------------------------------- + * DenseCopy copies the contents of the M-by-N matrix A into the + * M-by-N matrix B. + * + * DenseCopy is a wrapper around denseCopy which accesses the data + * in the DlsMat A and B (i.e. the fields cols) + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void DenseCopy(DlsMat A, DlsMat B); +SUNDIALS_EXPORT void denseCopy(realtype **a, realtype **b, int m, int n); + +/* + * ----------------------------------------------------------------- + * Function: DenseScale + * ----------------------------------------------------------------- + * DenseScale scales the elements of the M-by-N matrix A by the + * constant c and stores the result back in A. + * + * DenseScale is a wrapper around denseScale which performs the actual + * scaling by accessing the data in the DlsMat A (i.e. the field + * cols). + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void DenseScale(realtype c, DlsMat A); +SUNDIALS_EXPORT void denseScale(realtype c, realtype **a, int m, int n); + + +/* + * ----------------------------------------------------------------- + * Function: denseAddIdentity + * ----------------------------------------------------------------- + * denseAddIdentity adds the identity matrix to the n-by-n matrix + * stored in the realtype** arrays. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void denseAddIdentity(realtype **a, int n); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/sundials/sundials_direct.h b/odemex/Parser/CVode/cv_src/include/sundials/sundials_direct.h new file mode 100644 index 0000000..f3d823b --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials/sundials_direct.h @@ -0,0 +1,323 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.3 $ + * $Date: 2009/02/17 02:39:26 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This header file contains definitions and declarations for use by + * generic direct linear solvers for Ax = b. It defines types for + * dense and banded matrices and corresponding accessor macros. + * ----------------------------------------------------------------- + */ + +#ifndef _SUNDIALS_DIRECT_H +#define _SUNDIALS_DIRECT_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ================================================================= + * C O N S T A N T S + * ================================================================= + */ + +/* + * SUNDIALS_DENSE: dense matrix + * SUNDIALS_BAND: banded matrix + */ + +#define SUNDIALS_DENSE 1 +#define SUNDIALS_BAND 2 + +/* + * ================================================================== + * Type definitions + * ================================================================== + */ + +/* + * ----------------------------------------------------------------- + * Type : DlsMat + * ----------------------------------------------------------------- + * The type DlsMat is defined to be a pointer to a structure + * with various sizes, a data field, and an array of pointers to + * the columns which defines a dense or band matrix for use in + * direct linear solvers. The M and N fields indicates the number + * of rows and columns, respectively. The data field is a one + * dimensional array used for component storage. The cols field + * stores the pointers in data for the beginning of each column. + * ----------------------------------------------------------------- + * For DENSE matrices, the relevant fields in DlsMat are: + * type = SUNDIALS_DENSE + * M - number of rows + * N - number of columns + * ldim - leading dimension (ldim >= M) + * data - pointer to a contiguous block of realtype variables + * ldata - length of the data array =ldim*N + * cols - array of pointers. cols[j] points to the first element + * of the j-th column of the matrix in the array data. + * + * The elements of a dense matrix are stored columnwise (i.e columns + * are stored one on top of the other in memory). + * If A is of type DlsMat, then the (i,j)th element of A (with + * 0 <= i < M and 0 <= j < N) is given by (A->data)[j*n+i]. + * + * The DENSE_COL and DENSE_ELEM macros below allow a user to access + * efficiently individual matrix elements without writing out explicit + * data structure references and without knowing too much about the + * underlying element storage. The only storage assumption needed is + * that elements are stored columnwise and that a pointer to the + * jth column of elements can be obtained via the DENSE_COL macro. + * ----------------------------------------------------------------- + * For BAND matrices, the relevant fields in DlsMat are: + * type = SUNDIALS_BAND + * M - number of rows + * N - number of columns + * mu - upper bandwidth, 0 <= mu <= min(M,N) + * ml - lower bandwidth, 0 <= ml <= min(M,N) + * s_mu - storage upper bandwidth, mu <= s_mu <= N-1. + * The dgbtrf routine writes the LU factors into the storage + * for A. The upper triangular factor U, however, may have + * an upper bandwidth as big as MIN(N-1,mu+ml) because of + * partial pivoting. The s_mu field holds the upper + * bandwidth allocated for A. + * ldim - leading dimension (ldim >= s_mu) + * data - pointer to a contiguous block of realtype variables + * ldata - length of the data array =ldim*(s_mu+ml+1) + * cols - array of pointers. cols[j] points to the first element + * of the j-th column of the matrix in the array data. + * + * The BAND_COL, BAND_COL_ELEM, and BAND_ELEM macros below allow a + * user to access individual matrix elements without writing out + * explicit data structure references and without knowing too much + * about the underlying element storage. The only storage assumption + * needed is that elements are stored columnwise and that a pointer + * into the jth column of elements can be obtained via the BAND_COL + * macro. The BAND_COL_ELEM macro selects an element from a column + * which has already been isolated via BAND_COL. The macro + * BAND_COL_ELEM allows the user to avoid the translation + * from the matrix location (i,j) to the index in the array returned + * by BAND_COL at which the (i,j)th element is stored. + * ----------------------------------------------------------------- + */ + +typedef struct _DlsMat { + int type; + int M; + int N; + int ldim; + int mu; + int ml; + int s_mu; + realtype *data; + int ldata; + realtype **cols; +} *DlsMat; + +/* + * ================================================================== + * Data accessor macros + * ================================================================== + */ + +/* + * ----------------------------------------------------------------- + * DENSE_COL and DENSE_ELEM + * ----------------------------------------------------------------- + * + * DENSE_COL(A,j) references the jth column of the M-by-N dense + * matrix A, 0 <= j < N. The type of the expression DENSE_COL(A,j) + * is (realtype *). After the assignment in the usage above, col_j + * may be treated as an array indexed from 0 to M-1. The (i,j)-th + * element of A is thus referenced by col_j[i]. + * + * DENSE_ELEM(A,i,j) references the (i,j)th element of the dense + * M-by-N matrix A, 0 <= i < M ; 0 <= j < N. + * + * ----------------------------------------------------------------- + */ + +#define DENSE_COL(A,j) ((A->cols)[j]) +#define DENSE_ELEM(A,i,j) ((A->cols)[j][i]) + +/* + * ----------------------------------------------------------------- + * BAND_COL, BAND_COL_ELEM, and BAND_ELEM + * ----------------------------------------------------------------- + * + * BAND_COL(A,j) references the diagonal element of the jth column + * of the N by N band matrix A, 0 <= j <= N-1. The type of the + * expression BAND_COL(A,j) is realtype *. The pointer returned by + * the call BAND_COL(A,j) can be treated as an array which is + * indexed from -(A->mu) to (A->ml). + * + * BAND_COL_ELEM references the (i,j)th entry of the band matrix A + * when used in conjunction with BAND_COL. The index (i,j) should + * satisfy j-(A->mu) <= i <= j+(A->ml). + * + * BAND_ELEM(A,i,j) references the (i,j)th element of the M-by-N + * band matrix A, where 0 <= i,j <= N-1. The location (i,j) should + * further satisfy j-(A->mu) <= i <= j+(A->ml). + * + * ----------------------------------------------------------------- + */ + +#define BAND_COL(A,j) (((A->cols)[j])+(A->s_mu)) +#define BAND_COL_ELEM(col_j,i,j) (col_j[(i)-(j)]) +#define BAND_ELEM(A,i,j) ((A->cols)[j][(i)-(j)+(A->s_mu)]) + +/* + * ================================================================== + * Exported function prototypes (functions working on dlsMat) + * ================================================================== + */ + +/* + * ----------------------------------------------------------------- + * Function: NewDenseMat + * ----------------------------------------------------------------- + * NewDenseMat allocates memory for an M-by-N dense matrix and + * returns the storage allocated (type DlsMat). NewDenseMat + * returns NULL if the request for matrix storage cannot be + * satisfied. See the above documentation for the type DlsMat + * for matrix storage details. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT DlsMat NewDenseMat(int M, int N); + +/* + * ----------------------------------------------------------------- + * Function: NewBandMat + * ----------------------------------------------------------------- + * NewBandMat allocates memory for an M-by-N band matrix + * with upper bandwidth mu, lower bandwidth ml, and storage upper + * bandwidth smu. Pass smu as follows depending on whether A will + * be LU factored: + * + * (1) Pass smu = mu if A will not be factored. + * + * (2) Pass smu = MIN(N-1,mu+ml) if A will be factored. + * + * NewBandMat returns the storage allocated (type DlsMat) or + * NULL if the request for matrix storage cannot be satisfied. + * See the documentation for the type DlsMat for matrix storage + * details. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT DlsMat NewBandMat(int N, int mu, int ml, int smu); + +/* + * ----------------------------------------------------------------- + * Functions: DestroyMat + * ----------------------------------------------------------------- + * DestroyMat frees the memory allocated by NewDenseMat or NewBandMat + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void DestroyMat(DlsMat A); + +/* + * ----------------------------------------------------------------- + * Function: NewIntArray + * ----------------------------------------------------------------- + * NewIntArray allocates memory an array of N integers and returns + * the pointer to the memory it allocates. If the request for + * memory storage cannot be satisfied, it returns NULL. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int *NewIntArray(int N); + +/* + * ----------------------------------------------------------------- + * Function: NewRealArray + * ----------------------------------------------------------------- + * NewRealArray allocates memory an array of N realtype and returns + * the pointer to the memory it allocates. If the request for + * memory storage cannot be satisfied, it returns NULL. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT realtype *NewRealArray(int N); + +/* + * ----------------------------------------------------------------- + * Function: DestroyArray + * ----------------------------------------------------------------- + * DestroyArray frees memory allocated by NewIntArray or by + * NewRealArray. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void DestroyArray(void *p); + +/* + * ----------------------------------------------------------------- + * Function : AddIdentity + * ----------------------------------------------------------------- + * AddIdentity adds 1.0 to the main diagonal (A_ii, i=1,2,...,N-1) of + * the M-by-N matrix A (M>= N) and stores the result back in A. + * AddIdentity is typically used with square matrices. + * AddIdentity does not check for M >= N and therefore a segmentation + * fault will occur if M < N! + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void AddIdentity(DlsMat A); + +/* + * ----------------------------------------------------------------- + * Function : SetToZero + * ----------------------------------------------------------------- + * SetToZero sets all the elements of the M-by-N matrix A to 0.0. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void SetToZero(DlsMat A); + +/* + * ----------------------------------------------------------------- + * Functions: PrintMat + * ----------------------------------------------------------------- + * This function prints the M-by-N (dense or band) matrix A to + * standard output as it would normally appear on paper. + * It is intended as debugging tools with small values of M and N. + * The elements are printed using the %g/%lg/%Lg option. + * A blank line is printed before and after the matrix. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void PrintMat(DlsMat A); + + +/* + * ================================================================== + * Exported function prototypes (functions working on realtype**) + * ================================================================== + */ + +SUNDIALS_EXPORT realtype **newDenseMat(int m, int n); +SUNDIALS_EXPORT realtype **newBandMat(int n, int smu, int ml); +SUNDIALS_EXPORT void destroyMat(realtype **a); +SUNDIALS_EXPORT int *newIntArray(int n); +SUNDIALS_EXPORT realtype *newRealArray(int m); +SUNDIALS_EXPORT void destroyArray(void *v); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/sundials/sundials_fnvector.h b/odemex/Parser/CVode/cv_src/include/sundials/sundials_fnvector.h new file mode 100644 index 0000000..bbc9a95 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials/sundials_fnvector.h @@ -0,0 +1,41 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.1 $ + * $Date: 2006/07/05 15:27:52 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This file (companion of nvector.h) contains definitions + * needed for the initialization of vector operations in Fortran. + * ----------------------------------------------------------------- + */ + + +#ifndef _FNVECTOR_H +#define _FNVECTOR_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#ifndef _SUNDIALS_CONFIG_H +#define _SUNDIALS_CONFIG_H +#include +#endif + +/* SUNDIALS solver IDs */ + +#define FCMIX_CVODE 1 +#define FCMIX_IDA 2 +#define FCMIX_KINSOL 3 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/sundials/sundials_iterative.h b/odemex/Parser/CVode/cv_src/include/sundials/sundials_iterative.h new file mode 100644 index 0000000..5e7e4bf --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials/sundials_iterative.h @@ -0,0 +1,242 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen and Alan C. Hindmarsh @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This header file contains declarations intended for use by + * generic iterative solvers of Ax = b. The enumeration gives + * symbolic names for the type of preconditioning to be used. + * The function type declarations give the prototypes for the + * functions to be called within an iterative linear solver, that + * are responsible for + * multiplying A by a given vector v (ATimesFn), and + * solving the preconditioner equation Pz = r (PSolveFn). + * ----------------------------------------------------------------- + */ + +#ifndef _ITERATIVE_H +#define _ITERATIVE_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + + +/* + * ----------------------------------------------------------------- + * enum : types of preconditioning + * ----------------------------------------------------------------- + * PREC_NONE : The iterative linear solver should not use + * preconditioning. + * + * PREC_LEFT : The iterative linear solver uses preconditioning on + * the left only. + * + * PREC_RIGHT : The iterative linear solver uses preconditioning on + * the right only. + * + * PREC_BOTH : The iterative linear solver uses preconditioning on + * both the left and the right. + * ----------------------------------------------------------------- + */ + +enum { PREC_NONE, PREC_LEFT, PREC_RIGHT, PREC_BOTH }; + +/* + * ----------------------------------------------------------------- + * enum : types of Gram-Schmidt routines + * ----------------------------------------------------------------- + * MODIFIED_GS : The iterative solver uses the modified + * Gram-Schmidt routine ModifiedGS listed in this + * file. + * + * CLASSICAL_GS : The iterative solver uses the classical + * Gram-Schmidt routine ClassicalGS listed in this + * file. + * ----------------------------------------------------------------- + */ + +enum { MODIFIED_GS = 1, CLASSICAL_GS = 2 }; + +/* + * ----------------------------------------------------------------- + * Type: ATimesFn + * ----------------------------------------------------------------- + * An ATimesFn multiplies Av and stores the result in z. The + * caller is responsible for allocating memory for the z vector. + * The parameter A_data is a pointer to any information about A + * which the function needs in order to do its job. The vector v + * is unchanged. An ATimesFn returns 0 if successful and a + * non-zero value if unsuccessful. + * ----------------------------------------------------------------- + */ + +typedef int (*ATimesFn)(void *A_data, N_Vector v, N_Vector z); + +/* + * ----------------------------------------------------------------- + * Type: PSolveFn + * ----------------------------------------------------------------- + * A PSolveFn solves the preconditioner equation Pz = r for the + * vector z. The caller is responsible for allocating memory for + * the z vector. The parameter P_data is a pointer to any + * information about P which the function needs in order to do + * its job. The parameter lr is input, and indicates whether P + * is to be taken as the left preconditioner or the right + * preconditioner: lr = 1 for left and lr = 2 for right. + * If preconditioning is on one side only, lr can be ignored. + * The vector r is unchanged. + * A PSolveFn returns 0 if successful and a non-zero value if + * unsuccessful. On a failure, a negative return value indicates + * an unrecoverable condition, while a positive value indicates + * a recoverable one, in which the calling routine may reattempt + * the solution after updating preconditioner data. + * ----------------------------------------------------------------- + */ + +typedef int (*PSolveFn)(void *P_data, N_Vector r, N_Vector z, int lr); + +/* + * ----------------------------------------------------------------- + * Function: ModifiedGS + * ----------------------------------------------------------------- + * ModifiedGS performs a modified Gram-Schmidt orthogonalization + * of the N_Vector v[k] against the p unit N_Vectors at + * v[k-1], v[k-2], ..., v[k-p]. + * + * v is an array of (k+1) N_Vectors v[i], i=0, 1, ..., k. + * v[k-1], v[k-2], ..., v[k-p] are assumed to have L2-norm + * equal to 1. + * + * h is the output k by k Hessenberg matrix of inner products. + * This matrix must be allocated row-wise so that the (i,j)th + * entry is h[i][j]. The inner products (v[i],v[k]), + * i=i0, i0+1, ..., k-1, are stored at h[i][k-1]. Here + * i0=MAX(0,k-p). + * + * k is the index of the vector in the v array that needs to be + * orthogonalized against previous vectors in the v array. + * + * p is the number of previous vectors in the v array against + * which v[k] is to be orthogonalized. + * + * new_vk_norm is a pointer to memory allocated by the caller to + * hold the Euclidean norm of the orthogonalized vector v[k]. + * + * If (k-p) < 0, then ModifiedGS uses p=k. The orthogonalized + * v[k] is NOT normalized and is stored over the old v[k]. Once + * the orthogonalization has been performed, the Euclidean norm + * of v[k] is stored in (*new_vk_norm). + * + * ModifiedGS returns 0 to indicate success. It cannot fail. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int ModifiedGS(N_Vector *v, realtype **h, int k, int p, + realtype *new_vk_norm); + +/* + * ----------------------------------------------------------------- + * Function: ClassicalGS + * ----------------------------------------------------------------- + * ClassicalGS performs a classical Gram-Schmidt + * orthogonalization of the N_Vector v[k] against the p unit + * N_Vectors at v[k-1], v[k-2], ..., v[k-p]. The parameters v, h, + * k, p, and new_vk_norm are as described in the documentation + * for ModifiedGS. + * + * temp is an N_Vector which can be used as workspace by the + * ClassicalGS routine. + * + * s is a length k array of realtype which can be used as + * workspace by the ClassicalGS routine. + * + * ClassicalGS returns 0 to indicate success. It cannot fail. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int ClassicalGS(N_Vector *v, realtype **h, int k, int p, + realtype *new_vk_norm, N_Vector temp, realtype *s); + +/* + * ----------------------------------------------------------------- + * Function: QRfact + * ----------------------------------------------------------------- + * QRfact performs a QR factorization of the Hessenberg matrix H. + * + * n is the problem size; the matrix H is (n+1) by n. + * + * h is the (n+1) by n Hessenberg matrix H to be factored. It is + * stored row-wise. + * + * q is an array of length 2*n containing the Givens rotations + * computed by this function. A Givens rotation has the form: + * | c -s | + * | s c |. + * The components of the Givens rotations are stored in q as + * (c, s, c, s, ..., c, s). + * + * job is a control flag. If job==0, then a new QR factorization + * is performed. If job!=0, then it is assumed that the first + * n-1 columns of h have already been factored and only the last + * column needs to be updated. + * + * QRfact returns 0 if successful. If a zero is encountered on + * the diagonal of the triangular factor R, then QRfact returns + * the equation number of the zero entry, where the equations are + * numbered from 1, not 0. If QRsol is subsequently called in + * this situation, it will return an error because it could not + * divide by the zero diagonal entry. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int QRfact(int n, realtype **h, realtype *q, int job); + +/* + * ----------------------------------------------------------------- + * Function: QRsol + * ----------------------------------------------------------------- + * QRsol solves the linear least squares problem + * + * min (b - H*x, b - H*x), x in R^n, + * + * where H is a Hessenberg matrix, and b is in R^(n+1). + * It uses the QR factors of H computed by QRfact. + * + * n is the problem size; the matrix H is (n+1) by n. + * + * h is a matrix (computed by QRfact) containing the upper + * triangular factor R of the original Hessenberg matrix H. + * + * q is an array of length 2*n (computed by QRfact) containing + * the Givens rotations used to factor H. + * + * b is the (n+1)-vector appearing in the least squares problem + * above. + * + * On return, b contains the solution x of the least squares + * problem, if QRsol was successful. + * + * QRsol returns a 0 if successful. Otherwise, a zero was + * encountered on the diagonal of the triangular factor R. + * In this case, QRsol returns the equation number (numbered + * from 1, not 0) of the zero entry. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int QRsol(int n, realtype **h, realtype *q, realtype *b); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/sundials/sundials_lapack.h b/odemex/Parser/CVode/cv_src/include/sundials/sundials_lapack.h new file mode 100644 index 0000000..4af89df --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials/sundials_lapack.h @@ -0,0 +1,126 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2009/02/17 02:39:26 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for a generic package of direct matrix + * operations for use with BLAS/LAPACK. + * ----------------------------------------------------------------- + */ + +#ifndef _SUNDIALS_LAPACK_H +#define _SUNDIALS_LAPACK_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +/* + * ================================================================== + * Blas and Lapack functions + * ================================================================== + */ + +#if defined(SUNDIALS_F77_FUNC) + +#define dcopy_f77 SUNDIALS_F77_FUNC(dcopy, DCOPY) +#define dscal_f77 SUNDIALS_F77_FUNC(dscal, DSCAL) +#define dgemv_f77 SUNDIALS_F77_FUNC(dgemv, DGEMV) +#define dtrsv_f77 SUNDIALS_F77_FUNC(dtrsv, DTRSV) +#define dsyrk_f77 SUNDIALS_F77_FUNC(dsyrk, DSKYR) + +#define dgbtrf_f77 SUNDIALS_F77_FUNC(dgbtrf, DGBTRF) +#define dgbtrs_f77 SUNDIALS_F77_FUNC(dgbtrs, DGBTRS) +#define dgetrf_f77 SUNDIALS_F77_FUNC(dgetrf, DGETRF) +#define dgetrs_f77 SUNDIALS_F77_FUNC(dgetrs, DGETRS) +#define dgeqp3_f77 SUNDIALS_F77_FUNC(dgeqp3, DGEQP3) +#define dgeqrf_f77 SUNDIALS_F77_FUNC(dgeqrf, DGEQRF) +#define dormqr_f77 SUNDIALS_F77_FUNC(dormqr, DORMQR) +#define dpotrf_f77 SUNDIALS_F77_FUNC(dpotrf, DPOTRF) +#define dpotrs_f77 SUNDIALS_F77_FUNC(dpotrs, DPOTRS) + +#else + +#define dcopy_f77 dcopy_ +#define dscal_f77 dscal_ +#define dgemv_f77 dgemv_ +#define dtrsv_f77 dtrsv_ +#define dsyrk_f77 dsyrk_ + +#define dgbtrf_f77 dgbtrf_ +#define dgbtrs_f77 dgbtrs_ +#define dgeqp3_f77 dgeqp3_ +#define dgeqrf_f77 dgeqrf_ +#define dgetrf_f77 dgetrf_ +#define dgetrs_f77 dgetrs_ +#define dormqr_f77 dormqr_ +#define dpotrf_f77 dpotrf_ +#define dpotrs_f77 dpotrs_ + +#endif + +/* Level-1 BLAS */ + +extern void dcopy_f77(int *n, const double *x, const int *inc_x, double *y, const int *inc_y); +extern void dscal_f77(int *n, const double *alpha, double *x, const int *inc_x); + +/* Level-2 BLAS */ + +extern void dgemv_f77(const char *trans, int *m, int *n, const double *alpha, const double *a, + int *lda, const double *x, int *inc_x, const double *beta, double *y, int *inc_y, + int len_trans); + +extern void dtrsv_f77(const char *uplo, const char *trans, const char *diag, const int *n, + const double *a, const int *lda, double *x, const int *inc_x, + int len_uplo, int len_trans, int len_diag); + +/* Level-3 BLAS */ + +extern void dsyrk_f77(const char *uplo, const char *trans, const int *n, const int *k, + const double *alpha, const double *a, const int *lda, const double *beta, + const double *c, const int *ldc, int len_uplo, int len_trans); + +/* LAPACK */ + +extern void dgbtrf_f77(const int *m, const int *n, const int *kl, const int *ku, + double *ab, int *ldab, int *ipiv, int *info); + +extern void dgbtrs_f77(const char *trans, const int *n, const int *kl, const int *ku, const int *nrhs, + double *ab, const int *ldab, int *ipiv, double *b, const int *ldb, + int *info, int len_trans); + + +extern void dgeqp3_f77(const int *m, const int *n, double *a, const int *lda, int *jpvt, double *tau, + double *work, const int *lwork, int *info); + +extern void dgeqrf_f77(const int *m, const int *n, double *a, const int *lda, double *tau, double *work, + const int *lwork, int *info); + +extern void dgetrf_f77(const int *m, const int *n, double *a, int *lda, int *ipiv, int *info); + +extern void dgetrs_f77(const char *trans, const int *n, const int *nrhs, double *a, const int *lda, + int *ipiv, double *b, const int *ldb, int *info, int len_trans); + + +extern void dormqr_f77(const char *side, const char *trans, const int *m, const int *n, const int *k, + double *a, const int *lda, double *tau, double *c, const int *ldc, + double *work, const int *lwork, int *info, int len_side, int len_trans); + +extern void dpotrf_f77(const char *uplo, const int *n, double *a, int *lda, int *info, int len_uplo); + +extern void dpotrs_f77(const char *uplo, const int *n, const int *nrhs, double *a, const int *lda, + double *b, const int *ldb, int * info, int len_uplo); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/sundials/sundials_math.h b/odemex/Parser/CVode/cv_src/include/sundials/sundials_math.h new file mode 100644 index 0000000..99de085 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials/sundials_math.h @@ -0,0 +1,139 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for a simple C-language math library. The + * routines listed here work with the type realtype as defined in + * the header file sundials_types.h. + * ----------------------------------------------------------------- + */ + +#ifndef _SUNDIALSMATH_H +#define _SUNDIALSMATH_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Macros : MIN and MAX + * ----------------------------------------------------------------- + * MIN(A,B) returns the minimum of A and B + * + * MAX(A,B) returns the maximum of A and B + * + * SQR(A) returns A^2 + * ----------------------------------------------------------------- + */ + +#ifndef MIN +#define MIN(A, B) ((A) < (B) ? (A) : (B)) +#endif + +#ifndef MAX +#define MAX(A, B) ((A) > (B) ? (A) : (B)) +#endif + +#ifndef SQR +#define SQR(A) ((A)*(A)) +#endif + +#ifndef ABS +#define ABS RAbs +#endif + +#ifndef SQRT +#define SQRT RSqrt +#endif + +#ifndef EXP +#define EXP RExp +#endif + +/* + * ----------------------------------------------------------------- + * Function : RPowerI + * ----------------------------------------------------------------- + * Usage : int exponent; + * realtype base, ans; + * ans = RPowerI(base,exponent); + * ----------------------------------------------------------------- + * RPowerI returns the value of base^exponent, where base is of type + * realtype and exponent is of type int. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT realtype RPowerI(realtype base, int exponent); + +/* + * ----------------------------------------------------------------- + * Function : RPowerR + * ----------------------------------------------------------------- + * Usage : realtype base, exponent, ans; + * ans = RPowerR(base,exponent); + * ----------------------------------------------------------------- + * RPowerR returns the value of base^exponent, where both base and + * exponent are of type realtype. If base < ZERO, then RPowerR + * returns ZERO. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT realtype RPowerR(realtype base, realtype exponent); + +/* + * ----------------------------------------------------------------- + * Function : RSqrt + * ----------------------------------------------------------------- + * Usage : realtype sqrt_x; + * sqrt_x = RSqrt(x); + * ----------------------------------------------------------------- + * RSqrt(x) returns the square root of x. If x < ZERO, then RSqrt + * returns ZERO. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT realtype RSqrt(realtype x); + +/* + * ----------------------------------------------------------------- + * Function : RAbs (a.k.a. ABS) + * ----------------------------------------------------------------- + * Usage : realtype abs_x; + * abs_x = RAbs(x); + * ----------------------------------------------------------------- + * RAbs(x) returns the absolute value of x. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT realtype RAbs(realtype x); + +/* + * ----------------------------------------------------------------- + * Function : RExp (a.k.a. EXP) + * ----------------------------------------------------------------- + * Usage : realtype exp_x; + * exp_x = RExp(x); + * ----------------------------------------------------------------- + * RExp(x) returns e^x (base-e exponential function). + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT realtype RExp(realtype x); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/sundials/sundials_nvector.h b/odemex/Parser/CVode/cv_src/include/sundials/sundials_nvector.h new file mode 100644 index 0000000..6142b32 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials/sundials_nvector.h @@ -0,0 +1,373 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for a generic NVECTOR package. + * It defines the N_Vector structure (_generic_N_Vector) which + * contains the following fields: + * - an implementation-dependent 'content' field which contains + * the description and actual data of the vector + * - an 'ops' filed which contains a structure listing operations + * acting on such vectors + * + * Part I of this file contains type declarations for the + * _generic_N_Vector and _generic_N_Vector_Ops structures, as well + * as references to pointers to such structures (N_Vector). + * + * Part II of this file contains the prototypes for the vector + * functions which operate on N_Vector. + * + * At a minimum, a particular implementation of an NVECTOR must + * do the following: + * - specify the 'content' field of N_Vector, + * - implement the operations on those N_Vectors, + * - provide a constructor routine for new vectors + * + * Additionally, an NVECTOR implementation may provide the following: + * - macros to access the underlying N_Vector data + * - a constructor for an array of N_Vectors + * - a constructor for an empty N_Vector (i.e., a new N_Vector with + * a NULL data pointer). + * - a routine to print the content of an N_Vector + * ----------------------------------------------------------------- + */ + +#ifndef _NVECTOR_H +#define _NVECTOR_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Generic definition of N_Vector + * ----------------------------------------------------------------- + */ + +/* Forward reference for pointer to N_Vector_Ops object */ +typedef struct _generic_N_Vector_Ops *N_Vector_Ops; + +/* Forward reference for pointer to N_Vector object */ +typedef struct _generic_N_Vector *N_Vector; + +/* Define array of N_Vectors */ +typedef N_Vector *N_Vector_S; + +/* Structure containing function pointers to vector operations */ +struct _generic_N_Vector_Ops { + N_Vector (*nvclone)(N_Vector); + N_Vector (*nvcloneempty)(N_Vector); + void (*nvdestroy)(N_Vector); + void (*nvspace)(N_Vector, long int *, long int *); + realtype* (*nvgetarraypointer)(N_Vector); + void (*nvsetarraypointer)(realtype *, N_Vector); + void (*nvlinearsum)(realtype, N_Vector, realtype, N_Vector, N_Vector); + void (*nvconst)(realtype, N_Vector); + void (*nvprod)(N_Vector, N_Vector, N_Vector); + void (*nvdiv)(N_Vector, N_Vector, N_Vector); + void (*nvscale)(realtype, N_Vector, N_Vector); + void (*nvabs)(N_Vector, N_Vector); + void (*nvinv)(N_Vector, N_Vector); + void (*nvaddconst)(N_Vector, realtype, N_Vector); + realtype (*nvdotprod)(N_Vector, N_Vector); + realtype (*nvmaxnorm)(N_Vector); + realtype (*nvwrmsnorm)(N_Vector, N_Vector); + realtype (*nvwrmsnormmask)(N_Vector, N_Vector, N_Vector); + realtype (*nvmin)(N_Vector); + realtype (*nvwl2norm)(N_Vector, N_Vector); + realtype (*nvl1norm)(N_Vector); + void (*nvcompare)(realtype, N_Vector, N_Vector); + booleantype (*nvinvtest)(N_Vector, N_Vector); + booleantype (*nvconstrmask)(N_Vector, N_Vector, N_Vector); + realtype (*nvminquotient)(N_Vector, N_Vector); +}; + +/* + * ----------------------------------------------------------------- + * A vector is a structure with an implementation-dependent + * 'content' field, and a pointer to a structure of vector + * operations corresponding to that implementation. + * ----------------------------------------------------------------- + */ + +struct _generic_N_Vector { + void *content; + struct _generic_N_Vector_Ops *ops; +}; + +/* + * ----------------------------------------------------------------- + * Functions exported by NVECTOR module + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * N_VClone + * Creates a new vector of the same type as an existing vector. + * It does not copy the vector, but rather allocates storage for + * the new vector. + * + * N_VCloneEmpty + * Creates a new vector of the same type as an existing vector, + * but does not allocate storage. + * + * N_VDestroy + * Destroys a vector created with N_VClone. + * + * N_VSpace + * Returns space requirements for one N_Vector (type 'realtype' in + * lrw and type 'long int' in liw). + * + * N_VGetArrayPointer + * Returns a pointer to the data component of the given N_Vector. + * NOTE: This function assumes that the internal data is stored + * as a contiguous 'realtype' array. This routine is only used in + * the solver-specific interfaces to the dense and banded linear + * solvers, as well as the interfaces to the banded preconditioners + * distributed with SUNDIALS. + * + * N_VSetArrayPointer + * Overwrites the data field in the given N_Vector with a user-supplied + * array of type 'realtype'. + * NOTE: This function assumes that the internal data is stored + * as a contiguous 'realtype' array. This routine is only used in + * the interfaces to the dense linear solver. + * + * N_VLinearSum + * Performs the operation z = a*x + b*y + * + * N_VConst + * Performs the operation z[i] = c for i = 0, 1, ..., N-1 + * + * N_VProd + * Performs the operation z[i] = x[i]*y[i] for i = 0, 1, ..., N-1 + * + * N_VDiv + * Performs the operation z[i] = x[i]/y[i] for i = 0, 1, ..., N-1 + * + * N_VScale + * Performs the operation z = c*x + * + * N_VAbs + * Performs the operation z[i] = |x[i]| for i = 0, 1, ..., N-1 + * + * N_VInv + * Performs the operation z[i] = 1/x[i] for i = 0, 1, ..., N-1 + * This routine does not check for division by 0. It should be + * called only with an N_Vector x which is guaranteed to have + * all non-zero components. + * + * N_VAddConst + * Performs the operation z[i] = x[i] + b for i = 0, 1, ..., N-1 + * + * N_VDotProd + * Returns the dot product of two vectors: + * sum (i = 0 to N-1) {x[i]*y[i]} + * + * N_VMaxNorm + * Returns the maximum norm of x: + * max (i = 0 to N-1) ABS(x[i]) + * + * N_VWrmsNorm + * Returns the weighted root mean square norm of x with weight + * vector w: + * sqrt [(sum (i = 0 to N-1) {(x[i]*w[i])^2})/N] + * + * N_VWrmsNormMask + * Returns the weighted root mean square norm of x with weight + * vector w, masked by the elements of id: + * sqrt [(sum (i = 0 to N-1) {(x[i]*w[i]*msk[i])^2})/N] + * where msk[i] = 1.0 if id[i] > 0 and + * msk[i] = 0.0 if id[i] < 0 + * + * N_VMin + * Returns the smallest element of x: + * min (i = 0 to N-1) x[i] + * + * N_VWL2Norm + * Returns the weighted Euclidean L2 norm of x with weight + * vector w: + * sqrt [(sum (i = 0 to N-1) {(x[i]*w[i])^2})] + * + * N_VL1Norm + * Returns the L1 norm of x: + * sum (i = 0 to N-1) {ABS(x[i])} + * + * N_VCompare + * Performs the operation + * z[i] = 1.0 if ABS(x[i]) >= c i = 0, 1, ..., N-1 + * 0.0 otherwise + * + * N_VInvTest + * Performs the operation z[i] = 1/x[i] with a test for + * x[i] == 0.0 before inverting x[i]. + * This routine returns TRUE if all components of x are non-zero + * (successful inversion) and returns FALSE otherwise. + * + * N_VConstrMask + * Performs the operation : + * m[i] = 1.0 if constraint test fails for x[i] + * m[i] = 0.0 if constraint test passes for x[i] + * where the constraint tests are as follows: + * If c[i] = +2.0, then x[i] must be > 0.0. + * If c[i] = +1.0, then x[i] must be >= 0.0. + * If c[i] = -1.0, then x[i] must be <= 0.0. + * If c[i] = -2.0, then x[i] must be < 0.0. + * This routine returns a boolean FALSE if any element failed + * the constraint test, TRUE if all passed. It also sets a + * mask vector m, with elements equal to 1.0 where the + * corresponding constraint test failed, and equal to 0.0 + * where the constraint test passed. + * This routine is specialized in that it is used only for + * constraint checking. + * + * N_VMinQuotient + * Performs the operation : + * minq = min ( num[i]/denom[i]) over all i such that + * denom[i] != 0. + * This routine returns the minimum of the quotients obtained + * by term-wise dividing num[i] by denom[i]. A zero element + * in denom will be skipped. If no such quotients are found, + * then the large value BIG_REAL is returned. + * + * ----------------------------------------------------------------- + * + * The following table lists the vector functions used by + * different modules in SUNDIALS. The symbols in the table + * have the following meaning: + * S - called by the solver; + * D - called by the dense linear solver module + * B - called by the band linear solver module + * Di - called by the diagonal linear solver module + * I - called by the iterative linear solver module + * BP - called by the band preconditioner module + * BBDP - called by the band-block diagonal preconditioner module + * F - called by the Fortran-to-C interface + * + * ------------------------------------------------ + * MODULES + * NVECTOR ------------------------------------------------ + * FUNCTIONS CVODE/CVODES IDA KINSOL + * ----------------------------------------------------------------- + * N_VClone S Di I S I BBDP S I BBDP + * ----------------------------------------------------------------- + * N_VCloneEmpty F F F + * ----------------------------------------------------------------- + * N_VDestroy S Di I S I BBDP S I BBDP + * ----------------------------------------------------------------- + * N_VSpace S S S + * ----------------------------------------------------------------- + * N_VGetArrayPointer D B BP BBDP F D B BBDP BBDP F + * ----------------------------------------------------------------- + * N_VSetArrayPointer D F D F + * ----------------------------------------------------------------- + * N_VLinearSum S D Di I S D I S I + * ----------------------------------------------------------------- + * N_VConst S I S I I + * ----------------------------------------------------------------- + * N_VProd S Di I S I S I + * ----------------------------------------------------------------- + * N_VDiv S Di I S I S I + * ----------------------------------------------------------------- + * N_VScale S D B Di I BP BBDP S D B I BBDP S I BBDP + * ----------------------------------------------------------------- + * N_VAbs S S S + * ----------------------------------------------------------------- + * N_VInv S Di S S + * ----------------------------------------------------------------- + * N_VAddConst S Di S + * ----------------------------------------------------------------- + * N_VDotProd I I I + * ----------------------------------------------------------------- + * N_VMaxNorm S S S + * ----------------------------------------------------------------- + * N_VWrmsNorm S D B I BP BBDP S + * ----------------------------------------------------------------- + * N_VWrmsNormMask S + * ----------------------------------------------------------------- + * N_VMin S S S + * ----------------------------------------------------------------- + * N_VWL2Norm S I + * ----------------------------------------------------------------- + * N_VL1Norm I + * ----------------------------------------------------------------- + * N_VCompare Di S + * ----------------------------------------------------------------- + * N_VInvTest Di + * ----------------------------------------------------------------- + * N_VConstrMask S S + * ----------------------------------------------------------------- + * N_VMinQuotient S S + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VClone(N_Vector w); +SUNDIALS_EXPORT N_Vector N_VCloneEmpty(N_Vector w); +SUNDIALS_EXPORT void N_VDestroy(N_Vector v); +SUNDIALS_EXPORT void N_VSpace(N_Vector v, long int *lrw, long int *liw); +SUNDIALS_EXPORT realtype *N_VGetArrayPointer(N_Vector v); +SUNDIALS_EXPORT void N_VSetArrayPointer(realtype *v_data, N_Vector v); +SUNDIALS_EXPORT void N_VLinearSum(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VConst(realtype c, N_Vector z); +SUNDIALS_EXPORT void N_VProd(N_Vector x, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VDiv(N_Vector x, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VScale(realtype c, N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VAbs(N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VInv(N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VAddConst(N_Vector x, realtype b, N_Vector z); +SUNDIALS_EXPORT realtype N_VDotProd(N_Vector x, N_Vector y); +SUNDIALS_EXPORT realtype N_VMaxNorm(N_Vector x); +SUNDIALS_EXPORT realtype N_VWrmsNorm(N_Vector x, N_Vector w); +SUNDIALS_EXPORT realtype N_VWrmsNormMask(N_Vector x, N_Vector w, N_Vector id); +SUNDIALS_EXPORT realtype N_VMin(N_Vector x); +SUNDIALS_EXPORT realtype N_VWL2Norm(N_Vector x, N_Vector w); +SUNDIALS_EXPORT realtype N_VL1Norm(N_Vector x); +SUNDIALS_EXPORT void N_VCompare(realtype c, N_Vector x, N_Vector z); +SUNDIALS_EXPORT booleantype N_VInvTest(N_Vector x, N_Vector z); +SUNDIALS_EXPORT booleantype N_VConstrMask(N_Vector c, N_Vector x, N_Vector m); +SUNDIALS_EXPORT realtype N_VMinQuotient(N_Vector num, N_Vector denom); + +/* + * ----------------------------------------------------------------- + * Additional functions exported by NVECTOR module + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * N_VCloneEmptyVectorArray + * Creates (by cloning 'w') an array of 'count' empty N_Vectors + * + * N_VCloneVectorArray + * Creates (by cloning 'w') an array of 'count' N_Vectors + * + * N_VDestroyVectorArray + * Frees memory for an array of 'count' N_Vectors that was + * created by a call to N_VCloneVectorArray + * + * These functions are used by the SPGMR iterative linear solver + * module and by the CVODES and IDAS solvers. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector *N_VCloneEmptyVectorArray(int count, N_Vector w); +SUNDIALS_EXPORT N_Vector *N_VCloneVectorArray(int count, N_Vector w); +SUNDIALS_EXPORT void N_VDestroyVectorArray(N_Vector *vs, int count); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/sundials/sundials_spbcgs.h b/odemex/Parser/CVode/cv_src/include/sundials/sundials_spbcgs.h new file mode 100644 index 0000000..d569d1d --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials/sundials_spbcgs.h @@ -0,0 +1,199 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Peter Brown and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2004, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the implementation of the scaled, + * preconditioned Bi-CGSTAB (SPBCG) iterative linear solver. + * ----------------------------------------------------------------- + */ + +#ifndef _SPBCG_H +#define _SPBCG_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Types: struct SpbcgMemRec and struct *SpbcgMem + * ----------------------------------------------------------------- + * A variable declaration of type struct *SpbcgMem denotes a pointer + * to a data structure of type struct SpbcgMemRec. The SpbcgMemRec + * structure contains numerous fields that must be accessed by the + * SPBCG linear solver module. + * + * l_max maximum Krylov subspace dimension that SpbcgSolve will + * be permitted to use + * + * r vector (type N_Vector) which holds the scaled, preconditioned + * linear system residual + * + * r_star vector (type N_Vector) which holds the initial scaled, + * preconditioned linear system residual + * + * p, q, u and Ap vectors (type N_Vector) used for workspace by + * the SPBCG algorithm + * + * vtemp scratch vector (type N_Vector) used as temporary vector + * storage + * ----------------------------------------------------------------- + */ + +typedef struct { + + int l_max; + + N_Vector r_star; + N_Vector r; + N_Vector p; + N_Vector q; + N_Vector u; + N_Vector Ap; + N_Vector vtemp; + +} SpbcgMemRec, *SpbcgMem; + +/* + * ----------------------------------------------------------------- + * Function : SpbcgMalloc + * ----------------------------------------------------------------- + * SpbcgMalloc allocates additional memory needed by the SPBCG + * linear solver module. + * + * l_max maximum Krylov subspace dimension that SpbcgSolve will + * be permitted to use + * + * vec_tmpl implementation-specific template vector (type N_Vector) + * (created using either N_VNew_Serial or N_VNew_Parallel) + * + * If successful, SpbcgMalloc returns a non-NULL memory pointer. If + * an error occurs, then a NULL pointer is returned. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT SpbcgMem SpbcgMalloc(int l_max, N_Vector vec_tmpl); + +/* + * ----------------------------------------------------------------- + * Function : SpbcgSolve + * ----------------------------------------------------------------- + * SpbcgSolve solves the linear system Ax = b by means of a scaled + * preconditioned Bi-CGSTAB (SPBCG) iterative method. + * + * mem pointer to an internal memory block allocated during a + * prior call to SpbcgMalloc + * + * A_data pointer to a data structure containing information + * about the coefficient matrix A (passed to user-supplied + * function referenced by atimes (function pointer)) + * + * x vector (type N_Vector) containing initial guess x_0 upon + * entry, but which upon return contains an approximate solution + * of the linear system Ax = b (solution only valid if return + * value is either SPBCG_SUCCESS or SPBCG_RES_REDUCED) + * + * b vector (type N_Vector) set to the right-hand side vector b + * of the linear system (undisturbed by function) + * + * pretype variable (type int) indicating the type of + * preconditioning to be used (see sundials_iterative.h) + * + * delta tolerance on the L2 norm of the scaled, preconditioned + * residual (if return value == SPBCG_SUCCESS, then + * ||sb*P1_inv*(b-Ax)||_L2 <= delta) + * + * P_data pointer to a data structure containing preconditioner + * information (passed to user-supplied function referenced + * by psolve (function pointer)) + * + * sx vector (type N_Vector) containing positive scaling factors + * for x (pass sx == NULL if scaling NOT required) + * + * sb vector (type N_Vector) containing positive scaling factors + * for b (pass sb == NULL if scaling NOT required) + * + * atimes user-supplied routine responsible for computing the + * matrix-vector product Ax (see sundials_iterative.h) + * + * psolve user-supplied routine responsible for solving the + * preconditioned linear system Pz = r (ignored if + * pretype == PREC_NONE) (see sundials_iterative.h) + * + * res_norm pointer (type realtype*) to the L2 norm of the + * scaled, preconditioned residual (if return value + * is either SPBCG_SUCCESS or SPBCG_RES_REDUCED, then + * *res_norm = ||sb*P1_inv*(b-Ax)||_L2, where x is + * the computed approximate solution, sb is the diagonal + * scaling matrix for the right-hand side b, and P1_inv + * is the inverse of the left-preconditioner matrix) + * + * nli pointer (type int*) to the total number of linear + * iterations performed + * + * nps pointer (type int*) to the total number of calls made + * to the psolve routine + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int SpbcgSolve(SpbcgMem mem, void *A_data, N_Vector x, N_Vector b, + int pretype, realtype delta, void *P_data, N_Vector sx, + N_Vector sb, ATimesFn atimes, PSolveFn psolve, + realtype *res_norm, int *nli, int *nps); + +/* Return values for SpbcgSolve */ + +#define SPBCG_SUCCESS 0 /* SPBCG algorithm converged */ +#define SPBCG_RES_REDUCED 1 /* SPBCG did NOT converge, but the + residual was reduced */ +#define SPBCG_CONV_FAIL 2 /* SPBCG algorithm failed to converge */ +#define SPBCG_PSOLVE_FAIL_REC 3 /* psolve failed recoverably */ +#define SPBCG_ATIMES_FAIL_REC 4 /* atimes failed recoverably */ +#define SPBCG_PSET_FAIL_REC 5 /* pset faild recoverably */ + +#define SPBCG_MEM_NULL -1 /* mem argument is NULL */ +#define SPBCG_ATIMES_FAIL_UNREC -2 /* atimes returned failure flag */ +#define SPBCG_PSOLVE_FAIL_UNREC -3 /* psolve failed unrecoverably */ +#define SPBCG_PSET_FAIL_UNREC -4 /* pset failed unrecoverably */ + +/* + * ----------------------------------------------------------------- + * Function : SpbcgFree + * ----------------------------------------------------------------- + * SpbcgFree frees the memory allocated by a call to SpbcgMalloc. + * It is illegal to use the pointer mem after a call to SpbcgFree. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void SpbcgFree(SpbcgMem mem); + +/* + * ----------------------------------------------------------------- + * Macro : SPBCG_VTEMP + * ----------------------------------------------------------------- + * This macro provides access to the vector r in the + * memory block of the SPBCG module. The argument mem is the + * memory pointer returned by SpbcgMalloc, of type SpbcgMem, + * and the macro value is of type N_Vector. + * + * Note: Only used by IDA (r contains P_inverse F if nli_inc == 0). + * ----------------------------------------------------------------- + */ + +#define SPBCG_VTEMP(mem) (mem->r) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/sundials/sundials_spgmr.h b/odemex/Parser/CVode/cv_src/include/sundials/sundials_spgmr.h new file mode 100644 index 0000000..c557acd --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials/sundials_spgmr.h @@ -0,0 +1,296 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the implementation of SPGMR Krylov + * iterative linear solver. The SPGMR algorithm is based on the + * Scaled Preconditioned GMRES (Generalized Minimal Residual) + * method. + * + * The SPGMR algorithm solves a linear system A x = b. + * Preconditioning is allowed on the left, right, or both. + * Scaling is allowed on both sides, and restarts are also allowed. + * We denote the preconditioner and scaling matrices as follows: + * P1 = left preconditioner + * P2 = right preconditioner + * S1 = diagonal matrix of scale factors for P1-inverse b + * S2 = diagonal matrix of scale factors for P2 x + * The matrices A, P1, and P2 are not required explicitly; only + * routines that provide A, P1-inverse, and P2-inverse as + * operators are required. + * + * In this notation, SPGMR applies the underlying GMRES method to + * the equivalent transformed system + * Abar xbar = bbar , where + * Abar = S1 (P1-inverse) A (P2-inverse) (S2-inverse) , + * bbar = S1 (P1-inverse) b , and xbar = S2 P2 x . + * + * The scaling matrices must be chosen so that vectors S1 + * P1-inverse b and S2 P2 x have dimensionless components. + * If preconditioning is done on the left only (P2 = I), by a + * matrix P, then S2 must be a scaling for x, while S1 is a + * scaling for P-inverse b, and so may also be taken as a scaling + * for x. Similarly, if preconditioning is done on the right only + * (P1 = I, P2 = P), then S1 must be a scaling for b, while S2 is + * a scaling for P x, and may also be taken as a scaling for b. + * + * The stopping test for the SPGMR iterations is on the L2 norm of + * the scaled preconditioned residual: + * || bbar - Abar xbar ||_2 < delta + * with an input test constant delta. + * + * The usage of this SPGMR solver involves supplying two routines + * and making three calls. The user-supplied routines are + * atimes (A_data, x, y) to compute y = A x, given x, + * and + * psolve (P_data, x, y, lr) + * to solve P1 x = y or P2 x = y for x, given y. + * The three user calls are: + * mem = SpgmrMalloc(lmax, vec_tmpl); + * to initialize memory, + * flag = SpgmrSolve(mem,A_data,x,b,..., + * P_data,s1,s2,atimes,psolve,...); + * to solve the system, and + * SpgmrFree(mem); + * to free the memory created by SpgmrMalloc. + * Complete details for specifying atimes and psolve and for the + * usage calls are given in the paragraphs below and in iterative.h. + * ----------------------------------------------------------------- + */ + +#ifndef _SPGMR_H +#define _SPGMR_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Types: SpgmrMemRec, SpgmrMem + * ----------------------------------------------------------------- + * SpgmrMem is a pointer to an SpgmrMemRec which contains + * the memory needed by SpgmrSolve. The SpgmrMalloc routine + * returns a pointer of type SpgmrMem which should then be passed + * in subsequent calls to SpgmrSolve. The SpgmrFree routine frees + * the memory allocated by SpgmrMalloc. + * + * l_max is the maximum Krylov dimension that SpgmrSolve will be + * permitted to use. + * + * V is the array of Krylov basis vectors v_1, ..., v_(l_max+1), + * stored in V[0], ..., V[l_max], where l_max is the second + * parameter to SpgmrMalloc. Each v_i is a vector of type + * N_Vector. + * + * Hes is the (l_max+1) x l_max Hessenberg matrix. It is stored + * row-wise so that the (i,j)th element is given by Hes[i][j]. + * + * givens is a length 2*l_max array which represents the + * Givens rotation matrices that arise in the algorithm. The + * Givens rotation matrices F_0, F_1, ..., F_j, where F_i is + * + * 1 + * 1 + * c_i -s_i <--- row i + * s_i c_i + * 1 + * 1 + * + * are represented in the givens vector as + * givens[0]=c_0, givens[1]=s_0, givens[2]=c_1, givens[3]=s_1, + * ..., givens[2j]=c_j, givens[2j+1]=s_j. + * + * xcor is a vector (type N_Vector) which holds the scaled, + * preconditioned correction to the initial guess. + * + * yg is a length (l_max+1) array of realtype used to hold "short" + * vectors (e.g. y and g). + * + * vtemp is a vector (type N_Vector) used as temporary vector + * storage during calculations. + * ----------------------------------------------------------------- + */ + +typedef struct _SpgmrMemRec { + + int l_max; + + N_Vector *V; + realtype **Hes; + realtype *givens; + N_Vector xcor; + realtype *yg; + N_Vector vtemp; + +} SpgmrMemRec, *SpgmrMem; + +/* + * ----------------------------------------------------------------- + * Function : SpgmrMalloc + * ----------------------------------------------------------------- + * SpgmrMalloc allocates the memory used by SpgmrSolve. It + * returns a pointer of type SpgmrMem which the user of the + * SPGMR package should pass to SpgmrSolve. The parameter l_max + * is the maximum Krylov dimension that SpgmrSolve will be + * permitted to use. The parameter vec_tmpl is a pointer to an + * N_Vector used as a template to create new vectors by duplication. + * This routine returns NULL if there is a memory request failure. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT SpgmrMem SpgmrMalloc(int l_max, N_Vector vec_tmpl); + +/* + * ----------------------------------------------------------------- + * Function : SpgmrSolve + * ----------------------------------------------------------------- + * SpgmrSolve solves the linear system Ax = b using the SPGMR + * method. The return values are given by the symbolic constants + * below. The first SpgmrSolve parameter is a pointer to memory + * allocated by a prior call to SpgmrMalloc. + * + * mem is the pointer returned by SpgmrMalloc to the structure + * containing the memory needed by SpgmrSolve. + * + * A_data is a pointer to information about the coefficient + * matrix A. This pointer is passed to the user-supplied function + * atimes. + * + * x is the initial guess x_0 upon entry and the solution + * N_Vector upon exit with return value SPGMR_SUCCESS or + * SPGMR_RES_REDUCED. For all other return values, the output x + * is undefined. + * + * b is the right hand side N_Vector. It is undisturbed by this + * function. + * + * pretype is the type of preconditioning to be used. Its + * legal possible values are enumerated in iterativ.h. These + * values are PREC_NONE=0, PREC_LEFT=1, PREC_RIGHT=2, and + * PREC_BOTH=3. + * + * gstype is the type of Gram-Schmidt orthogonalization to be + * used. Its legal values are enumerated in iterativ.h. These + * values are MODIFIED_GS=0 and CLASSICAL_GS=1. + * + * delta is the tolerance on the L2 norm of the scaled, + * preconditioned residual. On return with value SPGMR_SUCCESS, + * this residual satisfies || s1 P1_inv (b - Ax) ||_2 <= delta. + * + * max_restarts is the maximum number of times the algorithm is + * allowed to restart. + * + * P_data is a pointer to preconditioner information. This + * pointer is passed to the user-supplied function psolve. + * + * s1 is an N_Vector of positive scale factors for P1-inv b, where + * P1 is the left preconditioner. (Not tested for positivity.) + * Pass NULL if no scaling on P1-inv b is required. + * + * s2 is an N_Vector of positive scale factors for P2 x, where + * P2 is the right preconditioner. (Not tested for positivity.) + * Pass NULL if no scaling on P2 x is required. + * + * atimes is the user-supplied function which performs the + * operation of multiplying A by a given vector. Its description + * is given in iterative.h. + * + * psolve is the user-supplied function which solves a + * preconditioner system Pz = r, where P is P1 or P2. Its full + * description is given in iterativ.h. The psolve function will + * not be called if pretype is NONE; in that case, the user + * should pass NULL for psolve. + * + * res_norm is a pointer to the L2 norm of the scaled, + * preconditioned residual. On return with value SPGMR_SUCCESS or + * SPGMR_RES_REDUCED, (*res_norm) contains the value + * || s1 P1_inv (b - Ax) ||_2 for the computed solution x. + * For all other return values, (*res_norm) is undefined. The + * caller is responsible for allocating the memory (*res_norm) + * to be filled in by SpgmrSolve. + * + * nli is a pointer to the number of linear iterations done in + * the execution of SpgmrSolve. The caller is responsible for + * allocating the memory (*nli) to be filled in by SpgmrSolve. + * + * nps is a pointer to the number of calls made to psolve during + * the execution of SpgmrSolve. The caller is responsible for + * allocating the memory (*nps) to be filled in by SpgmrSolve. + * + * Note: Repeated calls can be made to SpgmrSolve with varying + * input arguments. If, however, the problem size N or the + * maximum Krylov dimension l_max changes, then a call to + * SpgmrMalloc must be made to obtain new memory for SpgmrSolve + * to use. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int SpgmrSolve(SpgmrMem mem, void *A_data, N_Vector x, N_Vector b, + int pretype, int gstype, realtype delta, + int max_restarts, void *P_data, N_Vector s1, + N_Vector s2, ATimesFn atimes, PSolveFn psolve, + realtype *res_norm, int *nli, int *nps); + + +/* Return values for SpgmrSolve */ + +#define SPGMR_SUCCESS 0 /* Converged */ +#define SPGMR_RES_REDUCED 1 /* Did not converge, but reduced + norm of residual */ +#define SPGMR_CONV_FAIL 2 /* Failed to converge */ +#define SPGMR_QRFACT_FAIL 3 /* QRfact found singular matrix */ +#define SPGMR_PSOLVE_FAIL_REC 4 /* psolve failed recoverably */ +#define SPGMR_ATIMES_FAIL_REC 5 /* atimes failed recoverably */ +#define SPGMR_PSET_FAIL_REC 6 /* pset faild recoverably */ + +#define SPGMR_MEM_NULL -1 /* mem argument is NULL */ +#define SPGMR_ATIMES_FAIL_UNREC -2 /* atimes returned failure flag */ +#define SPGMR_PSOLVE_FAIL_UNREC -3 /* psolve failed unrecoverably */ +#define SPGMR_GS_FAIL -4 /* Gram-Schmidt routine faiuled */ +#define SPGMR_QRSOL_FAIL -5 /* QRsol found singular R */ +#define SPGMR_PSET_FAIL_UNREC -6 /* pset failed unrecoverably */ + +/* + * ----------------------------------------------------------------- + * Function : SpgmrFree + * ----------------------------------------------------------------- + * SpgmrMalloc frees the memory allocated by SpgmrMalloc. It is + * illegal to use the pointer mem after a call to SpgmrFree. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void SpgmrFree(SpgmrMem mem); + +/* + * ----------------------------------------------------------------- + * Macro: SPGMR_VTEMP + * ----------------------------------------------------------------- + * This macro provides access to the work vector vtemp in the + * memory block of the SPGMR module. The argument mem is the + * memory pointer returned by SpgmrMalloc, of type SpgmrMem, + * and the macro value is of type N_Vector. + * On a return from SpgmrSolve with *nli = 0, this vector + * contains the scaled preconditioned initial residual, + * s1 * P1_inverse * (b - A x_0). + * ----------------------------------------------------------------- + */ + +#define SPGMR_VTEMP(mem) (mem->vtemp) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/sundials/sundials_sptfqmr.h b/odemex/Parser/CVode/cv_src/include/sundials/sundials_sptfqmr.h new file mode 100644 index 0000000..2ba5c37 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials/sundials_sptfqmr.h @@ -0,0 +1,254 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the implementation of the scaled + * preconditioned Transpose-Free Quasi-Minimal Residual (SPTFQMR) + * linear solver. + * + * The SPTFQMR algorithm solves a linear system of the form Ax = b. + * Preconditioning is allowed on the left (PREC_LEFT), right + * (PREC_RIGHT), or both (PREC_BOTH). Scaling is allowed on both + * sides. We denote the preconditioner and scaling matrices as + * follows: + * P1 = left preconditioner + * P2 = right preconditioner + * S1 = diagonal matrix of scale factors for P1-inverse b + * S2 = diagonal matrix of scale factors for P2 x + * The matrices A, P1, and P2 are not required explicitly; only + * routines that provide A, P1-inverse, and P2-inverse as operators + * are required. + * + * In this notation, SPTFQMR applies the underlying TFQMR method to + * the equivalent transformed system: + * Abar xbar = bbar, where + * Abar = S1 (P1-inverse) A (P2-inverse) (S2-inverse), + * bbar = S1 (P1-inverse) b, and + * xbar = S2 P2 x. + * + * The scaling matrices must be chosen so that vectors + * S1 P1-inverse b and S2 P2 x have dimensionless components. If + * preconditioning is done on the left only (P2 = I), by a matrix P, + * then S2 must be a scaling for x, while S1 is a scaling for + * P-inverse b, and so may also be taken as a scaling for x. + * Similarly, if preconditioning is done on the right only (P1 = I, + * P2 = P), then S1 must be a scaling for b, while S2 is a scaling + * for P x, and may also be taken as a scaling for b. + * + * The stopping test for the SPTFQMR iterations is on the L2-norm of + * the scaled preconditioned residual: + * || bbar - Abar xbar ||_2 < delta + * with an input test constant delta. + * + * The usage of this SPTFQMR solver involves supplying two routines + * and making three calls. The user-supplied routines are: + * atimes(A_data, x, y) to compute y = A x, given x, + * and + * psolve(P_data, x, y, lr) to solve P1 x = y or P2 x = y for x, + * given y. + * The three user calls are: + * mem = SptfqmrMalloc(lmax, vec_tmpl); + * to initialize memory + * flag = SptfqmrSolve(mem, A_data, x, b, pretype, delta, P_data, + * sx, sb, atimes, psolve, res_norm, nli, nps); + * to solve the system, and + * SptfqmrFree(mem); + * to free the memory allocated by SptfqmrMalloc(). + * Complete details for specifying atimes() and psolve() and for the + * usage calls are given in the paragraphs below and in the header + * file sundials_iterative.h. + * ----------------------------------------------------------------- + */ + +#ifndef _SPTFQMR_H +#define _SPTFQMR_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Types: struct SptfqmrMemRec and struct *SptfqmrMem + * ----------------------------------------------------------------- + * A variable declaration of type struct *SptfqmrMem denotes a pointer + * to a data structure of type struct SptfqmrMemRec. The SptfqmrMemRec + * structure contains numerous fields that must be accessed by the + * SPTFQMR linear solver module. + * + * l_max maximum Krylov subspace dimension that SptfqmrSolve will + * be permitted to use + * + * r_star vector (type N_Vector) which holds the initial scaled, + * preconditioned linear system residual + * + * q/d/v/p/u/r vectors (type N_Vector) used for workspace by + * the SPTFQMR algorithm + * + * vtemp1/vtemp2/vtemp3 scratch vectors (type N_Vector) used as + * temporary storage + * ----------------------------------------------------------------- + */ + +typedef struct { + + int l_max; + + N_Vector r_star; + N_Vector q; + N_Vector d; + N_Vector v; + N_Vector p; + N_Vector *r; + N_Vector u; + N_Vector vtemp1; + N_Vector vtemp2; + N_Vector vtemp3; + +} SptfqmrMemRec, *SptfqmrMem; + +/* + * ----------------------------------------------------------------- + * Function : SptfqmrMalloc + * ----------------------------------------------------------------- + * SptfqmrMalloc allocates additional memory needed by the SPTFQMR + * linear solver module. + * + * l_max maximum Krylov subspace dimension that SptfqmrSolve will + * be permitted to use + * + * vec_tmpl implementation-specific template vector (type N_Vector) + * (created using either N_VNew_Serial or N_VNew_Parallel) + * + * If successful, SptfqmrMalloc returns a non-NULL memory pointer. If + * an error occurs, then a NULL pointer is returned. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT SptfqmrMem SptfqmrMalloc(int l_max, N_Vector vec_tmpl); + +/* + * ----------------------------------------------------------------- + * Function : SptfqmrSolve + * ----------------------------------------------------------------- + * SptfqmrSolve solves the linear system Ax = b by means of a scaled + * preconditioned Transpose-Free Quasi-Minimal Residual (SPTFQMR) + * method. + * + * mem pointer to an internal memory block allocated during a + * prior call to SptfqmrMalloc + * + * A_data pointer to a data structure containing information + * about the coefficient matrix A (passed to user-supplied + * function referenced by atimes (function pointer)) + * + * x vector (type N_Vector) containing initial guess x_0 upon + * entry, but which upon return contains an approximate solution + * of the linear system Ax = b (solution only valid if return + * value is either SPTFQMR_SUCCESS or SPTFQMR_RES_REDUCED) + * + * b vector (type N_Vector) set to the right-hand side vector b + * of the linear system (undisturbed by function) + * + * pretype variable (type int) indicating the type of + * preconditioning to be used (see sundials_iterative.h) + * + * delta tolerance on the L2 norm of the scaled, preconditioned + * residual (if return value == SPTFQMR_SUCCESS, then + * ||sb*P1_inv*(b-Ax)||_L2 <= delta) + * + * P_data pointer to a data structure containing preconditioner + * information (passed to user-supplied function referenced + * by psolve (function pointer)) + * + * sx vector (type N_Vector) containing positive scaling factors + * for x (pass sx == NULL if scaling NOT required) + * + * sb vector (type N_Vector) containing positive scaling factors + * for b (pass sb == NULL if scaling NOT required) + * + * atimes user-supplied routine responsible for computing the + * matrix-vector product Ax (see sundials_iterative.h) + * + * psolve user-supplied routine responsible for solving the + * preconditioned linear system Pz = r (ignored if + * pretype == PREC_NONE) (see sundials_iterative.h) + * + * res_norm pointer (type realtype*) to the L2 norm of the + * scaled, preconditioned residual (if return value + * is either SPTFQMR_SUCCESS or SPTFQMR_RES_REDUCED, then + * *res_norm = ||sb*P1_inv*(b-Ax)||_L2, where x is + * the computed approximate solution, sb is the diagonal + * scaling matrix for the right-hand side b, and P1_inv + * is the inverse of the left-preconditioner matrix) + * + * nli pointer (type int*) to the total number of linear + * iterations performed + * + * nps pointer (type int*) to the total number of calls made + * to the psolve routine + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int SptfqmrSolve(SptfqmrMem mem, void *A_data, N_Vector x, N_Vector b, + int pretype, realtype delta, void *P_data, N_Vector sx, + N_Vector sb, ATimesFn atimes, PSolveFn psolve, + realtype *res_norm, int *nli, int *nps); + +/* Return values for SptfqmrSolve */ + +#define SPTFQMR_SUCCESS 0 /* SPTFQMR algorithm converged */ +#define SPTFQMR_RES_REDUCED 1 /* SPTFQMR did NOT converge, but the + residual was reduced */ +#define SPTFQMR_CONV_FAIL 2 /* SPTFQMR algorithm failed to converge */ +#define SPTFQMR_PSOLVE_FAIL_REC 3 /* psolve failed recoverably */ +#define SPTFQMR_ATIMES_FAIL_REC 4 /* atimes failed recoverably */ +#define SPTFQMR_PSET_FAIL_REC 5 /* pset faild recoverably */ + +#define SPTFQMR_MEM_NULL -1 /* mem argument is NULL */ +#define SPTFQMR_ATIMES_FAIL_UNREC -2 /* atimes returned failure flag */ +#define SPTFQMR_PSOLVE_FAIL_UNREC -3 /* psolve failed unrecoverably */ +#define SPTFQMR_PSET_FAIL_UNREC -4 /* pset failed unrecoverably */ + +/* + * ----------------------------------------------------------------- + * Function : SptfqmrFree + * ----------------------------------------------------------------- + * SptfqmrFree frees the memory allocated by a call to SptfqmrMalloc. + * It is illegal to use the pointer mem after a call to SptfqmrFree. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void SptfqmrFree(SptfqmrMem mem); + +/* + * ----------------------------------------------------------------- + * Macro : SPTFQMR_VTEMP + * ----------------------------------------------------------------- + * This macro provides access to the work vector vtemp1 in the + * memory block of the SPTFQMR module. The argument mem is the + * memory pointer returned by SptfqmrMalloc, of type SptfqmrMem, + * and the macro value is of type N_Vector. + * + * Note: Only used by IDA (vtemp1 contains P_inverse F if + * nli_inc == 0). + * ----------------------------------------------------------------- + */ + +#define SPTFQMR_VTEMP(mem) (mem->vtemp1) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/sundials/sundials_types.h b/odemex/Parser/CVode/cv_src/include/sundials/sundials_types.h new file mode 100644 index 0000000..953f6e0 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials/sundials_types.h @@ -0,0 +1,122 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott Cohen, Alan Hindmarsh, Radu Serban, and + * Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + *------------------------------------------------------------------ + * This header file exports two types: realtype and booleantype, + * as well as the constants TRUE and FALSE. + * + * Users should include the header file sundials_types.h in every + * program file and use the exported name realtype instead of + * float, double or long double. + * + * The constants SUNDIALS_SINGLE_PRECISION, SUNDIALS_DOUBLE_PRECISION + * and SUNDIALS_LONG_DOUBLE_PRECISION indicate the underlying data + * type of realtype. It is set at the configuration stage. + * + * The legal types for realtype are float, double and long double. + * + * The macro RCONST gives the user a convenient way to define + * real-valued constants. To use the constant 1.0, for example, + * the user should write the following: + * + * #define ONE RCONST(1.0) + * + * If realtype is defined as a double, then RCONST(1.0) expands + * to 1.0. If realtype is defined as a float, then RCONST(1.0) + * expands to 1.0F. If realtype is defined as a long double, + * then RCONST(1.0) expands to 1.0L. There is never a need to + * explicitly cast 1.0 to (realtype). + *------------------------------------------------------------------ + */ + +#ifndef _SUNDIALSTYPES_H +#define _SUNDIALSTYPES_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#ifndef _SUNDIALS_CONFIG_H +#define _SUNDIALS_CONFIG_H +#include +#endif + +#include + +/* + *------------------------------------------------------------------ + * Type realtype + * Macro RCONST + * Constants BIG_REAL, SMALL_REAL, and UNIT_ROUNDOFF + *------------------------------------------------------------------ + */ + +#if defined(SUNDIALS_SINGLE_PRECISION) + +typedef float realtype; +# define RCONST(x) x##F +# define BIG_REAL FLT_MAX +# define SMALL_REAL FLT_MIN +# define UNIT_ROUNDOFF FLT_EPSILON + +#elif defined(SUNDIALS_DOUBLE_PRECISION) + +typedef double realtype; +# define RCONST(x) x +# define BIG_REAL DBL_MAX +# define SMALL_REAL DBL_MIN +# define UNIT_ROUNDOFF DBL_EPSILON + +#elif defined(SUNDIALS_EXTENDED_PRECISION) + +typedef long double realtype; +# define RCONST(x) x##L +# define BIG_REAL LDBL_MAX +# define SMALL_REAL LDBL_MIN +# define UNIT_ROUNDOFF LDBL_EPSILON + +#endif + +/* + *------------------------------------------------------------------ + * Type : booleantype + *------------------------------------------------------------------ + * Constants : FALSE and TRUE + *------------------------------------------------------------------ + * ANSI C does not have a built-in boolean data type. Below is the + * definition for a new type called booleantype. The advantage of + * using the name booleantype (instead of int) is an increase in + * code readability. It also allows the programmer to make a + * distinction between int and boolean data. Variables of type + * booleantype are intended to have only the two values FALSE and + * TRUE which are defined below to be equal to 0 and 1, + * respectively. + *------------------------------------------------------------------ + */ + +#ifndef booleantype +#define booleantype int +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/sundials/winDefine.h b/odemex/Parser/CVode/cv_src/include/sundials/winDefine.h new file mode 100644 index 0000000..1b97a07 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials/winDefine.h @@ -0,0 +1,44 @@ +/* + Joep Vanlier, 2011 + + Licensing: + Copyright (C) 2009-2011 Joep Vanlier. All rights + reserved. + + Contact:joep.vanlier@gmail.com + + This file is part of the puaMAT. + + puaMAT is free software: you can redistribute it + and/or modify it under the terms of the GNU General + Public License as published by the Free Software + Foundation, either version 3 of the License, or (at + your option) any later version. + + puaMAT is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A + PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General + Public License along with puaMAT. If not, see + http://www.gnu.org/licenses/ +*/ + + + #define dcopy_ dcopy + #define dscal_ dscal + #define dgemv_ dgemv + #define dtrsv_ dtrsv + #define dgetrf_ dgetrf + #define dgetrs_ dgetrs + #define dgbtrs_ dgbtrs + #define dgbtrf_ dgbtrf + #define dsyrk_ dsyrk + #define dgeqp3_ dgeqp3 + #define dormqr_ dormqr + #define dpotrf_ dpotrf_ + #define dgeqrf_ dgeqrf + #define dpotrs_ dpotrs + diff --git a/odemex/Parser/CVode/cv_src/include/sundials_band.h b/odemex/Parser/CVode/cv_src/include/sundials_band.h new file mode 100644 index 0000000..95ee54c --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials_band.h @@ -0,0 +1,153 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.5 $ + * $Date: 2009/02/17 02:39:26 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for a generic BAND linear solver + * package, based on the DlsMat type defined in sundials_direct.h. + * + * There are two sets of band solver routines listed in + * this file: one set uses type DlsMat defined below and the + * other set uses the type realtype ** for band matrix arguments. + * Routines that work with the type DlsMat begin with "Band". + * Routines that work with realtype ** begin with "band" + * ----------------------------------------------------------------- + */ + +#ifndef _SUNDIALS_BAND_H +#define _SUNDIALS_BAND_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Function : BandGBTRF + * ----------------------------------------------------------------- + * Usage : ier = BandGBTRF(A, p); + * if (ier != 0) ... A is singular + * ----------------------------------------------------------------- + * BandGBTRF performs the LU factorization of the N by N band + * matrix A. This is done using standard Gaussian elimination + * with partial pivoting. + * + * A successful LU factorization leaves the "matrix" A and the + * pivot array p with the following information: + * + * (1) p[k] contains the row number of the pivot element chosen + * at the beginning of elimination step k, k=0, 1, ..., N-1. + * + * (2) If the unique LU factorization of A is given by PA = LU, + * where P is a permutation matrix, L is a lower triangular + * matrix with all 1's on the diagonal, and U is an upper + * triangular matrix, then the upper triangular part of A + * (including its diagonal) contains U and the strictly lower + * triangular part of A contains the multipliers, I-L. + * + * BandGBTRF returns 0 if successful. Otherwise it encountered + * a zero diagonal element during the factorization. In this case + * it returns the column index (numbered from one) at which + * it encountered the zero. + * + * Important Note: A must be allocated to accommodate the increase + * in upper bandwidth that occurs during factorization. If + * mathematically, A is a band matrix with upper bandwidth mu and + * lower bandwidth ml, then the upper triangular factor U can + * have upper bandwidth as big as smu = MIN(n-1,mu+ml). The lower + * triangular factor L has lower bandwidth ml. Allocate A with + * call A = BandAllocMat(N,mu,ml,smu), where mu, ml, and smu are + * as defined above. The user does not have to zero the "extra" + * storage allocated for the purpose of factorization. This will + * handled by the BandGBTRF routine. + * + * BandGBTRF is only a wrapper around bandGBTRF. All work is done + * in bandGBTRF works directly on the data in the DlsMat A (i.e., + * the field cols). + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int BandGBTRF(DlsMat A, int *p); +SUNDIALS_EXPORT int bandGBTRF(realtype **a, int n, int mu, int ml, int smu, int *p); + +/* + * ----------------------------------------------------------------- + * Function : BandGBTRS + * ----------------------------------------------------------------- + * Usage : BandGBTRS(A, p, b); + * ----------------------------------------------------------------- + * BandGBTRS solves the N-dimensional system A x = b using + * the LU factorization in A and the pivot information in p + * computed in BandGBTRF. The solution x is returned in b. This + * routine cannot fail if the corresponding call to BandGBTRF + * did not fail. + * + * BandGBTRS is only a wrapper around bandGBTRS which does all the + * work directly on the data in the DlsMat A (i.e., the field cols). + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void BandGBTRS(DlsMat A, int *p, realtype *b); +SUNDIALS_EXPORT void bandGBTRS(realtype **a, int n, int smu, int ml, int *p, realtype *b); + +/* + * ----------------------------------------------------------------- + * Function : BandCopy + * ----------------------------------------------------------------- + * Usage : BandCopy(A, B, copymu, copyml); + * ----------------------------------------------------------------- + * BandCopy copies the submatrix with upper and lower bandwidths + * copymu, copyml of the N by N band matrix A into the N by N + * band matrix B. + * + * BandCopy is a wrapper around bandCopy which accesses the data + * in the DlsMat A and B (i.e. the fields cols) + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void BandCopy(DlsMat A, DlsMat B, int copymu, int copyml); +SUNDIALS_EXPORT void bandCopy(realtype **a, realtype **b, int n, int a_smu, int b_smu, + int copymu, int copyml); + +/* + * ----------------------------------------------------------------- + * Function: BandScale + * ----------------------------------------------------------------- + * Usage : BandScale(c, A); + * ----------------------------------------------------------------- + * A(i,j) <- c*A(i,j), j-(A->mu) <= i <= j+(A->ml). + * + * BandScale is a wrapper around bandScale which performs the actual + * scaling by accessing the data in the DlsMat A (i.e. the field + * cols). + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void BandScale(realtype c, DlsMat A); +SUNDIALS_EXPORT void bandScale(realtype c, realtype **a, int n, int mu, int ml, int smu); + +/* + * ----------------------------------------------------------------- + * Function: bandAddIdentity + * ----------------------------------------------------------------- + * bandAddIdentity adds the identity matrix to the n-by-n matrix + * stored in the realtype** arrays. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void bandAddIdentity(realtype **a, int n, int smu); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/sundials_config.in b/odemex/Parser/CVode/cv_src/include/sundials_config.in new file mode 100644 index 0000000..24e9be8 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials_config.in @@ -0,0 +1,78 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.4 $ + * $Date: 2007/12/19 20:34:00 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + *------------------------------------------------------------------ + * SUNDIALS configuration header file + *------------------------------------------------------------------ + */ + +/* Define SUNDIALS version number */ +#define SUNDIALS_PACKAGE_VERSION "@PACKAGE_VERSION@" + +/* FCMIX: Define Fortran name-mangling macro for C identifiers. + * Depending on the inferred scheme, one of the following six + * macros will be defined: + * #define SUNDIALS_F77_FUNC(name,NAME) name + * #define SUNDIALS_F77_FUNC(name,NAME) name ## _ + * #define SUNDIALS_F77_FUNC(name,NAME) name ## __ + * #define SUNDIALS_F77_FUNC(name,NAME) NAME + * #define SUNDIALS_F77_FUNC(name,NAME) NAME ## _ + * #define SUNDIALS_F77_FUNC(name,NAME) NAME ## __ + */ +@F77_MANGLE_MACRO1@ + +/* FCMIX: Define Fortran name-mangling macro for C identifiers + * which contain underscores. + */ +@F77_MANGLE_MACRO2@ + +/* Define precision of SUNDIALS data type 'realtype' + * Depending on the precision level, one of the following + * three macros will be defined: + * #define SUNDIALS_SINGLE_PRECISION 1 + * #define SUNDIALS_DOUBLE_PRECISION 1 + * #define SUNDIALS_EXTENDED_PRECISION 1 + */ +@PRECISION_LEVEL@ + +/* Use generic math functions + * If it was decided that generic math functions can be used, then + * #define SUNDIALS_USE_GENERIC_MATH 1 + * otherwise + * #define SUNDIALS_USE_GENERIC_MATH 0 + */ +@GENERIC_MATH_LIB@ +#define SUNDIALS_BLAS_LAPACK 1 +/* Blas/Lapack available + * If working libraries for Blas/lapack support were found, then + * #define SUNDIALS_BLAS_LAPACK 1 + * otherwise + * #define SUNDIALS_BLAS_LAPACK 0 + */ +@BLAS_LAPACK_MACRO@ + +/* FNVECTOR: Allow user to specify different MPI communicator + * If it was found that the MPI implementation supports MPI_Comm_f2c, then + * #define SUNDIALS_MPI_COMM_F2C 1 + * otherwise + * #define SUNDIALS_MPI_COMM_F2C 0 + */ +@F77_MPI_COMM_F2C@ + +/* Mark SUNDIALS API functions for export/import + * When building shared SUNDIALS libraries under Windows, use + * #define SUNDIALS_EXPORT __declspec(dllexport) + * When linking to shared SUNDIALS libraries under Windows, use + * #define SUNDIALS_EXPORT __declspec(dllimport) + * In all other cases (other platforms or static libraries under + * Windows), the SUNDIALS_EXPORT macro is empty + */ +@SUNDIALS_EXPORT@ diff --git a/odemex/Parser/CVode/cv_src/include/sundials_dense.h b/odemex/Parser/CVode/cv_src/include/sundials_dense.h new file mode 100644 index 0000000..a3b1431 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials_dense.h @@ -0,0 +1,187 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.7 $ + * $Date: 2009/02/17 02:39:26 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for a generic package of DENSE matrix + * operations, based on the DlsMat type defined in sundials_direct.h. + * + * There are two sets of dense solver routines listed in + * this file: one set uses type DlsMat defined below and the + * other set uses the type realtype ** for dense matrix arguments. + * Routines that work with the type DlsMat begin with "Dense". + * Routines that work with realtype** begin with "dense". + * ----------------------------------------------------------------- + */ + +#ifndef _SUNDIALS_DENSE_H +#define _SUNDIALS_DENSE_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Functions: DenseGETRF and DenseGETRS + * ----------------------------------------------------------------- + * DenseGETRF performs the LU factorization of the M by N dense + * matrix A. This is done using standard Gaussian elimination + * with partial (row) pivoting. Note that this applies only + * to matrices with M >= N and full column rank. + * + * A successful LU factorization leaves the matrix A and the + * pivot array p with the following information: + * + * (1) p[k] contains the row number of the pivot element chosen + * at the beginning of elimination step k, k=0, 1, ..., N-1. + * + * (2) If the unique LU factorization of A is given by PA = LU, + * where P is a permutation matrix, L is a lower trapezoidal + * matrix with all 1's on the diagonal, and U is an upper + * triangular matrix, then the upper triangular part of A + * (including its diagonal) contains U and the strictly lower + * trapezoidal part of A contains the multipliers, I-L. + * + * For square matrices (M=N), L is unit lower triangular. + * + * DenseGETRF returns 0 if successful. Otherwise it encountered + * a zero diagonal element during the factorization. In this case + * it returns the column index (numbered from one) at which + * it encountered the zero. + * + * DenseGETRS solves the N-dimensional system A x = b using + * the LU factorization in A and the pivot information in p + * computed in DenseGETRF. The solution x is returned in b. This + * routine cannot fail if the corresponding call to DenseGETRF + * did not fail. + * DenseGETRS does NOT check for a square matrix! + * + * ----------------------------------------------------------------- + * DenseGETRF and DenseGETRS are simply wrappers around denseGETRF + * and denseGETRS, respectively, which perform all the work by + * directly accessing the data in the DlsMat A (i.e. the field cols) + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int DenseGETRF(DlsMat A, int *p); +SUNDIALS_EXPORT void DenseGETRS(DlsMat A, int *p, realtype *b); + +SUNDIALS_EXPORT int denseGETRF(realtype **a, int m, int n, int *p); +SUNDIALS_EXPORT void denseGETRS(realtype **a, int n, int *p, realtype *b); + +/* + * ----------------------------------------------------------------- + * Functions : DensePOTRF and DensePOTRS + * ----------------------------------------------------------------- + * DensePOTRF computes the Cholesky factorization of a real symmetric + * positive definite matrix A. + * ----------------------------------------------------------------- + * DensePOTRS solves a system of linear equations A*X = B with a + * symmetric positive definite matrix A using the Cholesky factorization + * A = L*L**T computed by DensePOTRF. + * + * ----------------------------------------------------------------- + * DensePOTRF and DensePOTRS are simply wrappers around densePOTRF + * and densePOTRS, respectively, which perform all the work by + * directly accessing the data in the DlsMat A (i.e. the field cols) + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int DensePOTRF(DlsMat A); +SUNDIALS_EXPORT void DensePOTRS(DlsMat A, realtype *b); + +SUNDIALS_EXPORT int densePOTRF(realtype **a, int m); +SUNDIALS_EXPORT void densePOTRS(realtype **a, int m, realtype *b); + +/* + * ----------------------------------------------------------------- + * Functions : DenseGEQRF and DenseORMQR + * ----------------------------------------------------------------- + * DenseGEQRF computes a QR factorization of a real M-by-N matrix A: + * A = Q * R (with M>= N). + * + * DenseGEQRF requires a temporary work vector wrk of length M. + * ----------------------------------------------------------------- + * DenseORMQR computes the product w = Q * v where Q is a real + * orthogonal matrix defined as the product of k elementary reflectors + * + * Q = H(1) H(2) . . . H(k) + * + * as returned by DenseGEQRF. Q is an M-by-N matrix, v is a vector + * of length N and w is a vector of length M (with M>=N). + * + * DenseORMQR requires a temporary work vector wrk of length M. + * + * ----------------------------------------------------------------- + * DenseGEQRF and DenseORMQR are simply wrappers around denseGEQRF + * and denseORMQR, respectively, which perform all the work by + * directly accessing the data in the DlsMat A (i.e. the field cols) + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int DenseGEQRF(DlsMat A, realtype *beta, realtype *wrk); +SUNDIALS_EXPORT int DenseORMQR(DlsMat A, realtype *beta, realtype *vn, realtype *vm, + realtype *wrk); + +SUNDIALS_EXPORT int denseGEQRF(realtype **a, int m, int n, realtype *beta, realtype *v); +SUNDIALS_EXPORT int denseORMQR(realtype **a, int m, int n, realtype *beta, + realtype *v, realtype *w, realtype *wrk); + +/* + * ----------------------------------------------------------------- + * Function : DenseCopy + * ----------------------------------------------------------------- + * DenseCopy copies the contents of the M-by-N matrix A into the + * M-by-N matrix B. + * + * DenseCopy is a wrapper around denseCopy which accesses the data + * in the DlsMat A and B (i.e. the fields cols) + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void DenseCopy(DlsMat A, DlsMat B); +SUNDIALS_EXPORT void denseCopy(realtype **a, realtype **b, int m, int n); + +/* + * ----------------------------------------------------------------- + * Function: DenseScale + * ----------------------------------------------------------------- + * DenseScale scales the elements of the M-by-N matrix A by the + * constant c and stores the result back in A. + * + * DenseScale is a wrapper around denseScale which performs the actual + * scaling by accessing the data in the DlsMat A (i.e. the field + * cols). + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void DenseScale(realtype c, DlsMat A); +SUNDIALS_EXPORT void denseScale(realtype c, realtype **a, int m, int n); + + +/* + * ----------------------------------------------------------------- + * Function: denseAddIdentity + * ----------------------------------------------------------------- + * denseAddIdentity adds the identity matrix to the n-by-n matrix + * stored in the realtype** arrays. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void denseAddIdentity(realtype **a, int n); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/sundials_direct.h b/odemex/Parser/CVode/cv_src/include/sundials_direct.h new file mode 100644 index 0000000..f3d823b --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials_direct.h @@ -0,0 +1,323 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.3 $ + * $Date: 2009/02/17 02:39:26 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This header file contains definitions and declarations for use by + * generic direct linear solvers for Ax = b. It defines types for + * dense and banded matrices and corresponding accessor macros. + * ----------------------------------------------------------------- + */ + +#ifndef _SUNDIALS_DIRECT_H +#define _SUNDIALS_DIRECT_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ================================================================= + * C O N S T A N T S + * ================================================================= + */ + +/* + * SUNDIALS_DENSE: dense matrix + * SUNDIALS_BAND: banded matrix + */ + +#define SUNDIALS_DENSE 1 +#define SUNDIALS_BAND 2 + +/* + * ================================================================== + * Type definitions + * ================================================================== + */ + +/* + * ----------------------------------------------------------------- + * Type : DlsMat + * ----------------------------------------------------------------- + * The type DlsMat is defined to be a pointer to a structure + * with various sizes, a data field, and an array of pointers to + * the columns which defines a dense or band matrix for use in + * direct linear solvers. The M and N fields indicates the number + * of rows and columns, respectively. The data field is a one + * dimensional array used for component storage. The cols field + * stores the pointers in data for the beginning of each column. + * ----------------------------------------------------------------- + * For DENSE matrices, the relevant fields in DlsMat are: + * type = SUNDIALS_DENSE + * M - number of rows + * N - number of columns + * ldim - leading dimension (ldim >= M) + * data - pointer to a contiguous block of realtype variables + * ldata - length of the data array =ldim*N + * cols - array of pointers. cols[j] points to the first element + * of the j-th column of the matrix in the array data. + * + * The elements of a dense matrix are stored columnwise (i.e columns + * are stored one on top of the other in memory). + * If A is of type DlsMat, then the (i,j)th element of A (with + * 0 <= i < M and 0 <= j < N) is given by (A->data)[j*n+i]. + * + * The DENSE_COL and DENSE_ELEM macros below allow a user to access + * efficiently individual matrix elements without writing out explicit + * data structure references and without knowing too much about the + * underlying element storage. The only storage assumption needed is + * that elements are stored columnwise and that a pointer to the + * jth column of elements can be obtained via the DENSE_COL macro. + * ----------------------------------------------------------------- + * For BAND matrices, the relevant fields in DlsMat are: + * type = SUNDIALS_BAND + * M - number of rows + * N - number of columns + * mu - upper bandwidth, 0 <= mu <= min(M,N) + * ml - lower bandwidth, 0 <= ml <= min(M,N) + * s_mu - storage upper bandwidth, mu <= s_mu <= N-1. + * The dgbtrf routine writes the LU factors into the storage + * for A. The upper triangular factor U, however, may have + * an upper bandwidth as big as MIN(N-1,mu+ml) because of + * partial pivoting. The s_mu field holds the upper + * bandwidth allocated for A. + * ldim - leading dimension (ldim >= s_mu) + * data - pointer to a contiguous block of realtype variables + * ldata - length of the data array =ldim*(s_mu+ml+1) + * cols - array of pointers. cols[j] points to the first element + * of the j-th column of the matrix in the array data. + * + * The BAND_COL, BAND_COL_ELEM, and BAND_ELEM macros below allow a + * user to access individual matrix elements without writing out + * explicit data structure references and without knowing too much + * about the underlying element storage. The only storage assumption + * needed is that elements are stored columnwise and that a pointer + * into the jth column of elements can be obtained via the BAND_COL + * macro. The BAND_COL_ELEM macro selects an element from a column + * which has already been isolated via BAND_COL. The macro + * BAND_COL_ELEM allows the user to avoid the translation + * from the matrix location (i,j) to the index in the array returned + * by BAND_COL at which the (i,j)th element is stored. + * ----------------------------------------------------------------- + */ + +typedef struct _DlsMat { + int type; + int M; + int N; + int ldim; + int mu; + int ml; + int s_mu; + realtype *data; + int ldata; + realtype **cols; +} *DlsMat; + +/* + * ================================================================== + * Data accessor macros + * ================================================================== + */ + +/* + * ----------------------------------------------------------------- + * DENSE_COL and DENSE_ELEM + * ----------------------------------------------------------------- + * + * DENSE_COL(A,j) references the jth column of the M-by-N dense + * matrix A, 0 <= j < N. The type of the expression DENSE_COL(A,j) + * is (realtype *). After the assignment in the usage above, col_j + * may be treated as an array indexed from 0 to M-1. The (i,j)-th + * element of A is thus referenced by col_j[i]. + * + * DENSE_ELEM(A,i,j) references the (i,j)th element of the dense + * M-by-N matrix A, 0 <= i < M ; 0 <= j < N. + * + * ----------------------------------------------------------------- + */ + +#define DENSE_COL(A,j) ((A->cols)[j]) +#define DENSE_ELEM(A,i,j) ((A->cols)[j][i]) + +/* + * ----------------------------------------------------------------- + * BAND_COL, BAND_COL_ELEM, and BAND_ELEM + * ----------------------------------------------------------------- + * + * BAND_COL(A,j) references the diagonal element of the jth column + * of the N by N band matrix A, 0 <= j <= N-1. The type of the + * expression BAND_COL(A,j) is realtype *. The pointer returned by + * the call BAND_COL(A,j) can be treated as an array which is + * indexed from -(A->mu) to (A->ml). + * + * BAND_COL_ELEM references the (i,j)th entry of the band matrix A + * when used in conjunction with BAND_COL. The index (i,j) should + * satisfy j-(A->mu) <= i <= j+(A->ml). + * + * BAND_ELEM(A,i,j) references the (i,j)th element of the M-by-N + * band matrix A, where 0 <= i,j <= N-1. The location (i,j) should + * further satisfy j-(A->mu) <= i <= j+(A->ml). + * + * ----------------------------------------------------------------- + */ + +#define BAND_COL(A,j) (((A->cols)[j])+(A->s_mu)) +#define BAND_COL_ELEM(col_j,i,j) (col_j[(i)-(j)]) +#define BAND_ELEM(A,i,j) ((A->cols)[j][(i)-(j)+(A->s_mu)]) + +/* + * ================================================================== + * Exported function prototypes (functions working on dlsMat) + * ================================================================== + */ + +/* + * ----------------------------------------------------------------- + * Function: NewDenseMat + * ----------------------------------------------------------------- + * NewDenseMat allocates memory for an M-by-N dense matrix and + * returns the storage allocated (type DlsMat). NewDenseMat + * returns NULL if the request for matrix storage cannot be + * satisfied. See the above documentation for the type DlsMat + * for matrix storage details. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT DlsMat NewDenseMat(int M, int N); + +/* + * ----------------------------------------------------------------- + * Function: NewBandMat + * ----------------------------------------------------------------- + * NewBandMat allocates memory for an M-by-N band matrix + * with upper bandwidth mu, lower bandwidth ml, and storage upper + * bandwidth smu. Pass smu as follows depending on whether A will + * be LU factored: + * + * (1) Pass smu = mu if A will not be factored. + * + * (2) Pass smu = MIN(N-1,mu+ml) if A will be factored. + * + * NewBandMat returns the storage allocated (type DlsMat) or + * NULL if the request for matrix storage cannot be satisfied. + * See the documentation for the type DlsMat for matrix storage + * details. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT DlsMat NewBandMat(int N, int mu, int ml, int smu); + +/* + * ----------------------------------------------------------------- + * Functions: DestroyMat + * ----------------------------------------------------------------- + * DestroyMat frees the memory allocated by NewDenseMat or NewBandMat + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void DestroyMat(DlsMat A); + +/* + * ----------------------------------------------------------------- + * Function: NewIntArray + * ----------------------------------------------------------------- + * NewIntArray allocates memory an array of N integers and returns + * the pointer to the memory it allocates. If the request for + * memory storage cannot be satisfied, it returns NULL. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int *NewIntArray(int N); + +/* + * ----------------------------------------------------------------- + * Function: NewRealArray + * ----------------------------------------------------------------- + * NewRealArray allocates memory an array of N realtype and returns + * the pointer to the memory it allocates. If the request for + * memory storage cannot be satisfied, it returns NULL. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT realtype *NewRealArray(int N); + +/* + * ----------------------------------------------------------------- + * Function: DestroyArray + * ----------------------------------------------------------------- + * DestroyArray frees memory allocated by NewIntArray or by + * NewRealArray. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void DestroyArray(void *p); + +/* + * ----------------------------------------------------------------- + * Function : AddIdentity + * ----------------------------------------------------------------- + * AddIdentity adds 1.0 to the main diagonal (A_ii, i=1,2,...,N-1) of + * the M-by-N matrix A (M>= N) and stores the result back in A. + * AddIdentity is typically used with square matrices. + * AddIdentity does not check for M >= N and therefore a segmentation + * fault will occur if M < N! + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void AddIdentity(DlsMat A); + +/* + * ----------------------------------------------------------------- + * Function : SetToZero + * ----------------------------------------------------------------- + * SetToZero sets all the elements of the M-by-N matrix A to 0.0. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void SetToZero(DlsMat A); + +/* + * ----------------------------------------------------------------- + * Functions: PrintMat + * ----------------------------------------------------------------- + * This function prints the M-by-N (dense or band) matrix A to + * standard output as it would normally appear on paper. + * It is intended as debugging tools with small values of M and N. + * The elements are printed using the %g/%lg/%Lg option. + * A blank line is printed before and after the matrix. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void PrintMat(DlsMat A); + + +/* + * ================================================================== + * Exported function prototypes (functions working on realtype**) + * ================================================================== + */ + +SUNDIALS_EXPORT realtype **newDenseMat(int m, int n); +SUNDIALS_EXPORT realtype **newBandMat(int n, int smu, int ml); +SUNDIALS_EXPORT void destroyMat(realtype **a); +SUNDIALS_EXPORT int *newIntArray(int n); +SUNDIALS_EXPORT realtype *newRealArray(int m); +SUNDIALS_EXPORT void destroyArray(void *v); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/sundials_fnvector.h b/odemex/Parser/CVode/cv_src/include/sundials_fnvector.h new file mode 100644 index 0000000..bbc9a95 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials_fnvector.h @@ -0,0 +1,41 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.1 $ + * $Date: 2006/07/05 15:27:52 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This file (companion of nvector.h) contains definitions + * needed for the initialization of vector operations in Fortran. + * ----------------------------------------------------------------- + */ + + +#ifndef _FNVECTOR_H +#define _FNVECTOR_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#ifndef _SUNDIALS_CONFIG_H +#define _SUNDIALS_CONFIG_H +#include +#endif + +/* SUNDIALS solver IDs */ + +#define FCMIX_CVODE 1 +#define FCMIX_IDA 2 +#define FCMIX_KINSOL 3 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/sundials_iterative.h b/odemex/Parser/CVode/cv_src/include/sundials_iterative.h new file mode 100644 index 0000000..5e7e4bf --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials_iterative.h @@ -0,0 +1,242 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen and Alan C. Hindmarsh @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This header file contains declarations intended for use by + * generic iterative solvers of Ax = b. The enumeration gives + * symbolic names for the type of preconditioning to be used. + * The function type declarations give the prototypes for the + * functions to be called within an iterative linear solver, that + * are responsible for + * multiplying A by a given vector v (ATimesFn), and + * solving the preconditioner equation Pz = r (PSolveFn). + * ----------------------------------------------------------------- + */ + +#ifndef _ITERATIVE_H +#define _ITERATIVE_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + + +/* + * ----------------------------------------------------------------- + * enum : types of preconditioning + * ----------------------------------------------------------------- + * PREC_NONE : The iterative linear solver should not use + * preconditioning. + * + * PREC_LEFT : The iterative linear solver uses preconditioning on + * the left only. + * + * PREC_RIGHT : The iterative linear solver uses preconditioning on + * the right only. + * + * PREC_BOTH : The iterative linear solver uses preconditioning on + * both the left and the right. + * ----------------------------------------------------------------- + */ + +enum { PREC_NONE, PREC_LEFT, PREC_RIGHT, PREC_BOTH }; + +/* + * ----------------------------------------------------------------- + * enum : types of Gram-Schmidt routines + * ----------------------------------------------------------------- + * MODIFIED_GS : The iterative solver uses the modified + * Gram-Schmidt routine ModifiedGS listed in this + * file. + * + * CLASSICAL_GS : The iterative solver uses the classical + * Gram-Schmidt routine ClassicalGS listed in this + * file. + * ----------------------------------------------------------------- + */ + +enum { MODIFIED_GS = 1, CLASSICAL_GS = 2 }; + +/* + * ----------------------------------------------------------------- + * Type: ATimesFn + * ----------------------------------------------------------------- + * An ATimesFn multiplies Av and stores the result in z. The + * caller is responsible for allocating memory for the z vector. + * The parameter A_data is a pointer to any information about A + * which the function needs in order to do its job. The vector v + * is unchanged. An ATimesFn returns 0 if successful and a + * non-zero value if unsuccessful. + * ----------------------------------------------------------------- + */ + +typedef int (*ATimesFn)(void *A_data, N_Vector v, N_Vector z); + +/* + * ----------------------------------------------------------------- + * Type: PSolveFn + * ----------------------------------------------------------------- + * A PSolveFn solves the preconditioner equation Pz = r for the + * vector z. The caller is responsible for allocating memory for + * the z vector. The parameter P_data is a pointer to any + * information about P which the function needs in order to do + * its job. The parameter lr is input, and indicates whether P + * is to be taken as the left preconditioner or the right + * preconditioner: lr = 1 for left and lr = 2 for right. + * If preconditioning is on one side only, lr can be ignored. + * The vector r is unchanged. + * A PSolveFn returns 0 if successful and a non-zero value if + * unsuccessful. On a failure, a negative return value indicates + * an unrecoverable condition, while a positive value indicates + * a recoverable one, in which the calling routine may reattempt + * the solution after updating preconditioner data. + * ----------------------------------------------------------------- + */ + +typedef int (*PSolveFn)(void *P_data, N_Vector r, N_Vector z, int lr); + +/* + * ----------------------------------------------------------------- + * Function: ModifiedGS + * ----------------------------------------------------------------- + * ModifiedGS performs a modified Gram-Schmidt orthogonalization + * of the N_Vector v[k] against the p unit N_Vectors at + * v[k-1], v[k-2], ..., v[k-p]. + * + * v is an array of (k+1) N_Vectors v[i], i=0, 1, ..., k. + * v[k-1], v[k-2], ..., v[k-p] are assumed to have L2-norm + * equal to 1. + * + * h is the output k by k Hessenberg matrix of inner products. + * This matrix must be allocated row-wise so that the (i,j)th + * entry is h[i][j]. The inner products (v[i],v[k]), + * i=i0, i0+1, ..., k-1, are stored at h[i][k-1]. Here + * i0=MAX(0,k-p). + * + * k is the index of the vector in the v array that needs to be + * orthogonalized against previous vectors in the v array. + * + * p is the number of previous vectors in the v array against + * which v[k] is to be orthogonalized. + * + * new_vk_norm is a pointer to memory allocated by the caller to + * hold the Euclidean norm of the orthogonalized vector v[k]. + * + * If (k-p) < 0, then ModifiedGS uses p=k. The orthogonalized + * v[k] is NOT normalized and is stored over the old v[k]. Once + * the orthogonalization has been performed, the Euclidean norm + * of v[k] is stored in (*new_vk_norm). + * + * ModifiedGS returns 0 to indicate success. It cannot fail. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int ModifiedGS(N_Vector *v, realtype **h, int k, int p, + realtype *new_vk_norm); + +/* + * ----------------------------------------------------------------- + * Function: ClassicalGS + * ----------------------------------------------------------------- + * ClassicalGS performs a classical Gram-Schmidt + * orthogonalization of the N_Vector v[k] against the p unit + * N_Vectors at v[k-1], v[k-2], ..., v[k-p]. The parameters v, h, + * k, p, and new_vk_norm are as described in the documentation + * for ModifiedGS. + * + * temp is an N_Vector which can be used as workspace by the + * ClassicalGS routine. + * + * s is a length k array of realtype which can be used as + * workspace by the ClassicalGS routine. + * + * ClassicalGS returns 0 to indicate success. It cannot fail. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int ClassicalGS(N_Vector *v, realtype **h, int k, int p, + realtype *new_vk_norm, N_Vector temp, realtype *s); + +/* + * ----------------------------------------------------------------- + * Function: QRfact + * ----------------------------------------------------------------- + * QRfact performs a QR factorization of the Hessenberg matrix H. + * + * n is the problem size; the matrix H is (n+1) by n. + * + * h is the (n+1) by n Hessenberg matrix H to be factored. It is + * stored row-wise. + * + * q is an array of length 2*n containing the Givens rotations + * computed by this function. A Givens rotation has the form: + * | c -s | + * | s c |. + * The components of the Givens rotations are stored in q as + * (c, s, c, s, ..., c, s). + * + * job is a control flag. If job==0, then a new QR factorization + * is performed. If job!=0, then it is assumed that the first + * n-1 columns of h have already been factored and only the last + * column needs to be updated. + * + * QRfact returns 0 if successful. If a zero is encountered on + * the diagonal of the triangular factor R, then QRfact returns + * the equation number of the zero entry, where the equations are + * numbered from 1, not 0. If QRsol is subsequently called in + * this situation, it will return an error because it could not + * divide by the zero diagonal entry. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int QRfact(int n, realtype **h, realtype *q, int job); + +/* + * ----------------------------------------------------------------- + * Function: QRsol + * ----------------------------------------------------------------- + * QRsol solves the linear least squares problem + * + * min (b - H*x, b - H*x), x in R^n, + * + * where H is a Hessenberg matrix, and b is in R^(n+1). + * It uses the QR factors of H computed by QRfact. + * + * n is the problem size; the matrix H is (n+1) by n. + * + * h is a matrix (computed by QRfact) containing the upper + * triangular factor R of the original Hessenberg matrix H. + * + * q is an array of length 2*n (computed by QRfact) containing + * the Givens rotations used to factor H. + * + * b is the (n+1)-vector appearing in the least squares problem + * above. + * + * On return, b contains the solution x of the least squares + * problem, if QRsol was successful. + * + * QRsol returns a 0 if successful. Otherwise, a zero was + * encountered on the diagonal of the triangular factor R. + * In this case, QRsol returns the equation number (numbered + * from 1, not 0) of the zero entry. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int QRsol(int n, realtype **h, realtype *q, realtype *b); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/sundials_lapack.h b/odemex/Parser/CVode/cv_src/include/sundials_lapack.h new file mode 100644 index 0000000..4af89df --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials_lapack.h @@ -0,0 +1,126 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2009/02/17 02:39:26 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for a generic package of direct matrix + * operations for use with BLAS/LAPACK. + * ----------------------------------------------------------------- + */ + +#ifndef _SUNDIALS_LAPACK_H +#define _SUNDIALS_LAPACK_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +/* + * ================================================================== + * Blas and Lapack functions + * ================================================================== + */ + +#if defined(SUNDIALS_F77_FUNC) + +#define dcopy_f77 SUNDIALS_F77_FUNC(dcopy, DCOPY) +#define dscal_f77 SUNDIALS_F77_FUNC(dscal, DSCAL) +#define dgemv_f77 SUNDIALS_F77_FUNC(dgemv, DGEMV) +#define dtrsv_f77 SUNDIALS_F77_FUNC(dtrsv, DTRSV) +#define dsyrk_f77 SUNDIALS_F77_FUNC(dsyrk, DSKYR) + +#define dgbtrf_f77 SUNDIALS_F77_FUNC(dgbtrf, DGBTRF) +#define dgbtrs_f77 SUNDIALS_F77_FUNC(dgbtrs, DGBTRS) +#define dgetrf_f77 SUNDIALS_F77_FUNC(dgetrf, DGETRF) +#define dgetrs_f77 SUNDIALS_F77_FUNC(dgetrs, DGETRS) +#define dgeqp3_f77 SUNDIALS_F77_FUNC(dgeqp3, DGEQP3) +#define dgeqrf_f77 SUNDIALS_F77_FUNC(dgeqrf, DGEQRF) +#define dormqr_f77 SUNDIALS_F77_FUNC(dormqr, DORMQR) +#define dpotrf_f77 SUNDIALS_F77_FUNC(dpotrf, DPOTRF) +#define dpotrs_f77 SUNDIALS_F77_FUNC(dpotrs, DPOTRS) + +#else + +#define dcopy_f77 dcopy_ +#define dscal_f77 dscal_ +#define dgemv_f77 dgemv_ +#define dtrsv_f77 dtrsv_ +#define dsyrk_f77 dsyrk_ + +#define dgbtrf_f77 dgbtrf_ +#define dgbtrs_f77 dgbtrs_ +#define dgeqp3_f77 dgeqp3_ +#define dgeqrf_f77 dgeqrf_ +#define dgetrf_f77 dgetrf_ +#define dgetrs_f77 dgetrs_ +#define dormqr_f77 dormqr_ +#define dpotrf_f77 dpotrf_ +#define dpotrs_f77 dpotrs_ + +#endif + +/* Level-1 BLAS */ + +extern void dcopy_f77(int *n, const double *x, const int *inc_x, double *y, const int *inc_y); +extern void dscal_f77(int *n, const double *alpha, double *x, const int *inc_x); + +/* Level-2 BLAS */ + +extern void dgemv_f77(const char *trans, int *m, int *n, const double *alpha, const double *a, + int *lda, const double *x, int *inc_x, const double *beta, double *y, int *inc_y, + int len_trans); + +extern void dtrsv_f77(const char *uplo, const char *trans, const char *diag, const int *n, + const double *a, const int *lda, double *x, const int *inc_x, + int len_uplo, int len_trans, int len_diag); + +/* Level-3 BLAS */ + +extern void dsyrk_f77(const char *uplo, const char *trans, const int *n, const int *k, + const double *alpha, const double *a, const int *lda, const double *beta, + const double *c, const int *ldc, int len_uplo, int len_trans); + +/* LAPACK */ + +extern void dgbtrf_f77(const int *m, const int *n, const int *kl, const int *ku, + double *ab, int *ldab, int *ipiv, int *info); + +extern void dgbtrs_f77(const char *trans, const int *n, const int *kl, const int *ku, const int *nrhs, + double *ab, const int *ldab, int *ipiv, double *b, const int *ldb, + int *info, int len_trans); + + +extern void dgeqp3_f77(const int *m, const int *n, double *a, const int *lda, int *jpvt, double *tau, + double *work, const int *lwork, int *info); + +extern void dgeqrf_f77(const int *m, const int *n, double *a, const int *lda, double *tau, double *work, + const int *lwork, int *info); + +extern void dgetrf_f77(const int *m, const int *n, double *a, int *lda, int *ipiv, int *info); + +extern void dgetrs_f77(const char *trans, const int *n, const int *nrhs, double *a, const int *lda, + int *ipiv, double *b, const int *ldb, int *info, int len_trans); + + +extern void dormqr_f77(const char *side, const char *trans, const int *m, const int *n, const int *k, + double *a, const int *lda, double *tau, double *c, const int *ldc, + double *work, const int *lwork, int *info, int len_side, int len_trans); + +extern void dpotrf_f77(const char *uplo, const int *n, double *a, int *lda, int *info, int len_uplo); + +extern void dpotrs_f77(const char *uplo, const int *n, const int *nrhs, double *a, const int *lda, + double *b, const int *ldb, int * info, int len_uplo); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/sundials_math.h b/odemex/Parser/CVode/cv_src/include/sundials_math.h new file mode 100644 index 0000000..99de085 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials_math.h @@ -0,0 +1,139 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for a simple C-language math library. The + * routines listed here work with the type realtype as defined in + * the header file sundials_types.h. + * ----------------------------------------------------------------- + */ + +#ifndef _SUNDIALSMATH_H +#define _SUNDIALSMATH_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Macros : MIN and MAX + * ----------------------------------------------------------------- + * MIN(A,B) returns the minimum of A and B + * + * MAX(A,B) returns the maximum of A and B + * + * SQR(A) returns A^2 + * ----------------------------------------------------------------- + */ + +#ifndef MIN +#define MIN(A, B) ((A) < (B) ? (A) : (B)) +#endif + +#ifndef MAX +#define MAX(A, B) ((A) > (B) ? (A) : (B)) +#endif + +#ifndef SQR +#define SQR(A) ((A)*(A)) +#endif + +#ifndef ABS +#define ABS RAbs +#endif + +#ifndef SQRT +#define SQRT RSqrt +#endif + +#ifndef EXP +#define EXP RExp +#endif + +/* + * ----------------------------------------------------------------- + * Function : RPowerI + * ----------------------------------------------------------------- + * Usage : int exponent; + * realtype base, ans; + * ans = RPowerI(base,exponent); + * ----------------------------------------------------------------- + * RPowerI returns the value of base^exponent, where base is of type + * realtype and exponent is of type int. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT realtype RPowerI(realtype base, int exponent); + +/* + * ----------------------------------------------------------------- + * Function : RPowerR + * ----------------------------------------------------------------- + * Usage : realtype base, exponent, ans; + * ans = RPowerR(base,exponent); + * ----------------------------------------------------------------- + * RPowerR returns the value of base^exponent, where both base and + * exponent are of type realtype. If base < ZERO, then RPowerR + * returns ZERO. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT realtype RPowerR(realtype base, realtype exponent); + +/* + * ----------------------------------------------------------------- + * Function : RSqrt + * ----------------------------------------------------------------- + * Usage : realtype sqrt_x; + * sqrt_x = RSqrt(x); + * ----------------------------------------------------------------- + * RSqrt(x) returns the square root of x. If x < ZERO, then RSqrt + * returns ZERO. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT realtype RSqrt(realtype x); + +/* + * ----------------------------------------------------------------- + * Function : RAbs (a.k.a. ABS) + * ----------------------------------------------------------------- + * Usage : realtype abs_x; + * abs_x = RAbs(x); + * ----------------------------------------------------------------- + * RAbs(x) returns the absolute value of x. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT realtype RAbs(realtype x); + +/* + * ----------------------------------------------------------------- + * Function : RExp (a.k.a. EXP) + * ----------------------------------------------------------------- + * Usage : realtype exp_x; + * exp_x = RExp(x); + * ----------------------------------------------------------------- + * RExp(x) returns e^x (base-e exponential function). + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT realtype RExp(realtype x); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/sundials_nvector.h b/odemex/Parser/CVode/cv_src/include/sundials_nvector.h new file mode 100644 index 0000000..6142b32 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials_nvector.h @@ -0,0 +1,373 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for a generic NVECTOR package. + * It defines the N_Vector structure (_generic_N_Vector) which + * contains the following fields: + * - an implementation-dependent 'content' field which contains + * the description and actual data of the vector + * - an 'ops' filed which contains a structure listing operations + * acting on such vectors + * + * Part I of this file contains type declarations for the + * _generic_N_Vector and _generic_N_Vector_Ops structures, as well + * as references to pointers to such structures (N_Vector). + * + * Part II of this file contains the prototypes for the vector + * functions which operate on N_Vector. + * + * At a minimum, a particular implementation of an NVECTOR must + * do the following: + * - specify the 'content' field of N_Vector, + * - implement the operations on those N_Vectors, + * - provide a constructor routine for new vectors + * + * Additionally, an NVECTOR implementation may provide the following: + * - macros to access the underlying N_Vector data + * - a constructor for an array of N_Vectors + * - a constructor for an empty N_Vector (i.e., a new N_Vector with + * a NULL data pointer). + * - a routine to print the content of an N_Vector + * ----------------------------------------------------------------- + */ + +#ifndef _NVECTOR_H +#define _NVECTOR_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Generic definition of N_Vector + * ----------------------------------------------------------------- + */ + +/* Forward reference for pointer to N_Vector_Ops object */ +typedef struct _generic_N_Vector_Ops *N_Vector_Ops; + +/* Forward reference for pointer to N_Vector object */ +typedef struct _generic_N_Vector *N_Vector; + +/* Define array of N_Vectors */ +typedef N_Vector *N_Vector_S; + +/* Structure containing function pointers to vector operations */ +struct _generic_N_Vector_Ops { + N_Vector (*nvclone)(N_Vector); + N_Vector (*nvcloneempty)(N_Vector); + void (*nvdestroy)(N_Vector); + void (*nvspace)(N_Vector, long int *, long int *); + realtype* (*nvgetarraypointer)(N_Vector); + void (*nvsetarraypointer)(realtype *, N_Vector); + void (*nvlinearsum)(realtype, N_Vector, realtype, N_Vector, N_Vector); + void (*nvconst)(realtype, N_Vector); + void (*nvprod)(N_Vector, N_Vector, N_Vector); + void (*nvdiv)(N_Vector, N_Vector, N_Vector); + void (*nvscale)(realtype, N_Vector, N_Vector); + void (*nvabs)(N_Vector, N_Vector); + void (*nvinv)(N_Vector, N_Vector); + void (*nvaddconst)(N_Vector, realtype, N_Vector); + realtype (*nvdotprod)(N_Vector, N_Vector); + realtype (*nvmaxnorm)(N_Vector); + realtype (*nvwrmsnorm)(N_Vector, N_Vector); + realtype (*nvwrmsnormmask)(N_Vector, N_Vector, N_Vector); + realtype (*nvmin)(N_Vector); + realtype (*nvwl2norm)(N_Vector, N_Vector); + realtype (*nvl1norm)(N_Vector); + void (*nvcompare)(realtype, N_Vector, N_Vector); + booleantype (*nvinvtest)(N_Vector, N_Vector); + booleantype (*nvconstrmask)(N_Vector, N_Vector, N_Vector); + realtype (*nvminquotient)(N_Vector, N_Vector); +}; + +/* + * ----------------------------------------------------------------- + * A vector is a structure with an implementation-dependent + * 'content' field, and a pointer to a structure of vector + * operations corresponding to that implementation. + * ----------------------------------------------------------------- + */ + +struct _generic_N_Vector { + void *content; + struct _generic_N_Vector_Ops *ops; +}; + +/* + * ----------------------------------------------------------------- + * Functions exported by NVECTOR module + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * N_VClone + * Creates a new vector of the same type as an existing vector. + * It does not copy the vector, but rather allocates storage for + * the new vector. + * + * N_VCloneEmpty + * Creates a new vector of the same type as an existing vector, + * but does not allocate storage. + * + * N_VDestroy + * Destroys a vector created with N_VClone. + * + * N_VSpace + * Returns space requirements for one N_Vector (type 'realtype' in + * lrw and type 'long int' in liw). + * + * N_VGetArrayPointer + * Returns a pointer to the data component of the given N_Vector. + * NOTE: This function assumes that the internal data is stored + * as a contiguous 'realtype' array. This routine is only used in + * the solver-specific interfaces to the dense and banded linear + * solvers, as well as the interfaces to the banded preconditioners + * distributed with SUNDIALS. + * + * N_VSetArrayPointer + * Overwrites the data field in the given N_Vector with a user-supplied + * array of type 'realtype'. + * NOTE: This function assumes that the internal data is stored + * as a contiguous 'realtype' array. This routine is only used in + * the interfaces to the dense linear solver. + * + * N_VLinearSum + * Performs the operation z = a*x + b*y + * + * N_VConst + * Performs the operation z[i] = c for i = 0, 1, ..., N-1 + * + * N_VProd + * Performs the operation z[i] = x[i]*y[i] for i = 0, 1, ..., N-1 + * + * N_VDiv + * Performs the operation z[i] = x[i]/y[i] for i = 0, 1, ..., N-1 + * + * N_VScale + * Performs the operation z = c*x + * + * N_VAbs + * Performs the operation z[i] = |x[i]| for i = 0, 1, ..., N-1 + * + * N_VInv + * Performs the operation z[i] = 1/x[i] for i = 0, 1, ..., N-1 + * This routine does not check for division by 0. It should be + * called only with an N_Vector x which is guaranteed to have + * all non-zero components. + * + * N_VAddConst + * Performs the operation z[i] = x[i] + b for i = 0, 1, ..., N-1 + * + * N_VDotProd + * Returns the dot product of two vectors: + * sum (i = 0 to N-1) {x[i]*y[i]} + * + * N_VMaxNorm + * Returns the maximum norm of x: + * max (i = 0 to N-1) ABS(x[i]) + * + * N_VWrmsNorm + * Returns the weighted root mean square norm of x with weight + * vector w: + * sqrt [(sum (i = 0 to N-1) {(x[i]*w[i])^2})/N] + * + * N_VWrmsNormMask + * Returns the weighted root mean square norm of x with weight + * vector w, masked by the elements of id: + * sqrt [(sum (i = 0 to N-1) {(x[i]*w[i]*msk[i])^2})/N] + * where msk[i] = 1.0 if id[i] > 0 and + * msk[i] = 0.0 if id[i] < 0 + * + * N_VMin + * Returns the smallest element of x: + * min (i = 0 to N-1) x[i] + * + * N_VWL2Norm + * Returns the weighted Euclidean L2 norm of x with weight + * vector w: + * sqrt [(sum (i = 0 to N-1) {(x[i]*w[i])^2})] + * + * N_VL1Norm + * Returns the L1 norm of x: + * sum (i = 0 to N-1) {ABS(x[i])} + * + * N_VCompare + * Performs the operation + * z[i] = 1.0 if ABS(x[i]) >= c i = 0, 1, ..., N-1 + * 0.0 otherwise + * + * N_VInvTest + * Performs the operation z[i] = 1/x[i] with a test for + * x[i] == 0.0 before inverting x[i]. + * This routine returns TRUE if all components of x are non-zero + * (successful inversion) and returns FALSE otherwise. + * + * N_VConstrMask + * Performs the operation : + * m[i] = 1.0 if constraint test fails for x[i] + * m[i] = 0.0 if constraint test passes for x[i] + * where the constraint tests are as follows: + * If c[i] = +2.0, then x[i] must be > 0.0. + * If c[i] = +1.0, then x[i] must be >= 0.0. + * If c[i] = -1.0, then x[i] must be <= 0.0. + * If c[i] = -2.0, then x[i] must be < 0.0. + * This routine returns a boolean FALSE if any element failed + * the constraint test, TRUE if all passed. It also sets a + * mask vector m, with elements equal to 1.0 where the + * corresponding constraint test failed, and equal to 0.0 + * where the constraint test passed. + * This routine is specialized in that it is used only for + * constraint checking. + * + * N_VMinQuotient + * Performs the operation : + * minq = min ( num[i]/denom[i]) over all i such that + * denom[i] != 0. + * This routine returns the minimum of the quotients obtained + * by term-wise dividing num[i] by denom[i]. A zero element + * in denom will be skipped. If no such quotients are found, + * then the large value BIG_REAL is returned. + * + * ----------------------------------------------------------------- + * + * The following table lists the vector functions used by + * different modules in SUNDIALS. The symbols in the table + * have the following meaning: + * S - called by the solver; + * D - called by the dense linear solver module + * B - called by the band linear solver module + * Di - called by the diagonal linear solver module + * I - called by the iterative linear solver module + * BP - called by the band preconditioner module + * BBDP - called by the band-block diagonal preconditioner module + * F - called by the Fortran-to-C interface + * + * ------------------------------------------------ + * MODULES + * NVECTOR ------------------------------------------------ + * FUNCTIONS CVODE/CVODES IDA KINSOL + * ----------------------------------------------------------------- + * N_VClone S Di I S I BBDP S I BBDP + * ----------------------------------------------------------------- + * N_VCloneEmpty F F F + * ----------------------------------------------------------------- + * N_VDestroy S Di I S I BBDP S I BBDP + * ----------------------------------------------------------------- + * N_VSpace S S S + * ----------------------------------------------------------------- + * N_VGetArrayPointer D B BP BBDP F D B BBDP BBDP F + * ----------------------------------------------------------------- + * N_VSetArrayPointer D F D F + * ----------------------------------------------------------------- + * N_VLinearSum S D Di I S D I S I + * ----------------------------------------------------------------- + * N_VConst S I S I I + * ----------------------------------------------------------------- + * N_VProd S Di I S I S I + * ----------------------------------------------------------------- + * N_VDiv S Di I S I S I + * ----------------------------------------------------------------- + * N_VScale S D B Di I BP BBDP S D B I BBDP S I BBDP + * ----------------------------------------------------------------- + * N_VAbs S S S + * ----------------------------------------------------------------- + * N_VInv S Di S S + * ----------------------------------------------------------------- + * N_VAddConst S Di S + * ----------------------------------------------------------------- + * N_VDotProd I I I + * ----------------------------------------------------------------- + * N_VMaxNorm S S S + * ----------------------------------------------------------------- + * N_VWrmsNorm S D B I BP BBDP S + * ----------------------------------------------------------------- + * N_VWrmsNormMask S + * ----------------------------------------------------------------- + * N_VMin S S S + * ----------------------------------------------------------------- + * N_VWL2Norm S I + * ----------------------------------------------------------------- + * N_VL1Norm I + * ----------------------------------------------------------------- + * N_VCompare Di S + * ----------------------------------------------------------------- + * N_VInvTest Di + * ----------------------------------------------------------------- + * N_VConstrMask S S + * ----------------------------------------------------------------- + * N_VMinQuotient S S + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VClone(N_Vector w); +SUNDIALS_EXPORT N_Vector N_VCloneEmpty(N_Vector w); +SUNDIALS_EXPORT void N_VDestroy(N_Vector v); +SUNDIALS_EXPORT void N_VSpace(N_Vector v, long int *lrw, long int *liw); +SUNDIALS_EXPORT realtype *N_VGetArrayPointer(N_Vector v); +SUNDIALS_EXPORT void N_VSetArrayPointer(realtype *v_data, N_Vector v); +SUNDIALS_EXPORT void N_VLinearSum(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VConst(realtype c, N_Vector z); +SUNDIALS_EXPORT void N_VProd(N_Vector x, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VDiv(N_Vector x, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VScale(realtype c, N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VAbs(N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VInv(N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VAddConst(N_Vector x, realtype b, N_Vector z); +SUNDIALS_EXPORT realtype N_VDotProd(N_Vector x, N_Vector y); +SUNDIALS_EXPORT realtype N_VMaxNorm(N_Vector x); +SUNDIALS_EXPORT realtype N_VWrmsNorm(N_Vector x, N_Vector w); +SUNDIALS_EXPORT realtype N_VWrmsNormMask(N_Vector x, N_Vector w, N_Vector id); +SUNDIALS_EXPORT realtype N_VMin(N_Vector x); +SUNDIALS_EXPORT realtype N_VWL2Norm(N_Vector x, N_Vector w); +SUNDIALS_EXPORT realtype N_VL1Norm(N_Vector x); +SUNDIALS_EXPORT void N_VCompare(realtype c, N_Vector x, N_Vector z); +SUNDIALS_EXPORT booleantype N_VInvTest(N_Vector x, N_Vector z); +SUNDIALS_EXPORT booleantype N_VConstrMask(N_Vector c, N_Vector x, N_Vector m); +SUNDIALS_EXPORT realtype N_VMinQuotient(N_Vector num, N_Vector denom); + +/* + * ----------------------------------------------------------------- + * Additional functions exported by NVECTOR module + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * N_VCloneEmptyVectorArray + * Creates (by cloning 'w') an array of 'count' empty N_Vectors + * + * N_VCloneVectorArray + * Creates (by cloning 'w') an array of 'count' N_Vectors + * + * N_VDestroyVectorArray + * Frees memory for an array of 'count' N_Vectors that was + * created by a call to N_VCloneVectorArray + * + * These functions are used by the SPGMR iterative linear solver + * module and by the CVODES and IDAS solvers. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector *N_VCloneEmptyVectorArray(int count, N_Vector w); +SUNDIALS_EXPORT N_Vector *N_VCloneVectorArray(int count, N_Vector w); +SUNDIALS_EXPORT void N_VDestroyVectorArray(N_Vector *vs, int count); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/sundials_spbcgs.h b/odemex/Parser/CVode/cv_src/include/sundials_spbcgs.h new file mode 100644 index 0000000..d569d1d --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials_spbcgs.h @@ -0,0 +1,199 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Peter Brown and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2004, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the implementation of the scaled, + * preconditioned Bi-CGSTAB (SPBCG) iterative linear solver. + * ----------------------------------------------------------------- + */ + +#ifndef _SPBCG_H +#define _SPBCG_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Types: struct SpbcgMemRec and struct *SpbcgMem + * ----------------------------------------------------------------- + * A variable declaration of type struct *SpbcgMem denotes a pointer + * to a data structure of type struct SpbcgMemRec. The SpbcgMemRec + * structure contains numerous fields that must be accessed by the + * SPBCG linear solver module. + * + * l_max maximum Krylov subspace dimension that SpbcgSolve will + * be permitted to use + * + * r vector (type N_Vector) which holds the scaled, preconditioned + * linear system residual + * + * r_star vector (type N_Vector) which holds the initial scaled, + * preconditioned linear system residual + * + * p, q, u and Ap vectors (type N_Vector) used for workspace by + * the SPBCG algorithm + * + * vtemp scratch vector (type N_Vector) used as temporary vector + * storage + * ----------------------------------------------------------------- + */ + +typedef struct { + + int l_max; + + N_Vector r_star; + N_Vector r; + N_Vector p; + N_Vector q; + N_Vector u; + N_Vector Ap; + N_Vector vtemp; + +} SpbcgMemRec, *SpbcgMem; + +/* + * ----------------------------------------------------------------- + * Function : SpbcgMalloc + * ----------------------------------------------------------------- + * SpbcgMalloc allocates additional memory needed by the SPBCG + * linear solver module. + * + * l_max maximum Krylov subspace dimension that SpbcgSolve will + * be permitted to use + * + * vec_tmpl implementation-specific template vector (type N_Vector) + * (created using either N_VNew_Serial or N_VNew_Parallel) + * + * If successful, SpbcgMalloc returns a non-NULL memory pointer. If + * an error occurs, then a NULL pointer is returned. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT SpbcgMem SpbcgMalloc(int l_max, N_Vector vec_tmpl); + +/* + * ----------------------------------------------------------------- + * Function : SpbcgSolve + * ----------------------------------------------------------------- + * SpbcgSolve solves the linear system Ax = b by means of a scaled + * preconditioned Bi-CGSTAB (SPBCG) iterative method. + * + * mem pointer to an internal memory block allocated during a + * prior call to SpbcgMalloc + * + * A_data pointer to a data structure containing information + * about the coefficient matrix A (passed to user-supplied + * function referenced by atimes (function pointer)) + * + * x vector (type N_Vector) containing initial guess x_0 upon + * entry, but which upon return contains an approximate solution + * of the linear system Ax = b (solution only valid if return + * value is either SPBCG_SUCCESS or SPBCG_RES_REDUCED) + * + * b vector (type N_Vector) set to the right-hand side vector b + * of the linear system (undisturbed by function) + * + * pretype variable (type int) indicating the type of + * preconditioning to be used (see sundials_iterative.h) + * + * delta tolerance on the L2 norm of the scaled, preconditioned + * residual (if return value == SPBCG_SUCCESS, then + * ||sb*P1_inv*(b-Ax)||_L2 <= delta) + * + * P_data pointer to a data structure containing preconditioner + * information (passed to user-supplied function referenced + * by psolve (function pointer)) + * + * sx vector (type N_Vector) containing positive scaling factors + * for x (pass sx == NULL if scaling NOT required) + * + * sb vector (type N_Vector) containing positive scaling factors + * for b (pass sb == NULL if scaling NOT required) + * + * atimes user-supplied routine responsible for computing the + * matrix-vector product Ax (see sundials_iterative.h) + * + * psolve user-supplied routine responsible for solving the + * preconditioned linear system Pz = r (ignored if + * pretype == PREC_NONE) (see sundials_iterative.h) + * + * res_norm pointer (type realtype*) to the L2 norm of the + * scaled, preconditioned residual (if return value + * is either SPBCG_SUCCESS or SPBCG_RES_REDUCED, then + * *res_norm = ||sb*P1_inv*(b-Ax)||_L2, where x is + * the computed approximate solution, sb is the diagonal + * scaling matrix for the right-hand side b, and P1_inv + * is the inverse of the left-preconditioner matrix) + * + * nli pointer (type int*) to the total number of linear + * iterations performed + * + * nps pointer (type int*) to the total number of calls made + * to the psolve routine + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int SpbcgSolve(SpbcgMem mem, void *A_data, N_Vector x, N_Vector b, + int pretype, realtype delta, void *P_data, N_Vector sx, + N_Vector sb, ATimesFn atimes, PSolveFn psolve, + realtype *res_norm, int *nli, int *nps); + +/* Return values for SpbcgSolve */ + +#define SPBCG_SUCCESS 0 /* SPBCG algorithm converged */ +#define SPBCG_RES_REDUCED 1 /* SPBCG did NOT converge, but the + residual was reduced */ +#define SPBCG_CONV_FAIL 2 /* SPBCG algorithm failed to converge */ +#define SPBCG_PSOLVE_FAIL_REC 3 /* psolve failed recoverably */ +#define SPBCG_ATIMES_FAIL_REC 4 /* atimes failed recoverably */ +#define SPBCG_PSET_FAIL_REC 5 /* pset faild recoverably */ + +#define SPBCG_MEM_NULL -1 /* mem argument is NULL */ +#define SPBCG_ATIMES_FAIL_UNREC -2 /* atimes returned failure flag */ +#define SPBCG_PSOLVE_FAIL_UNREC -3 /* psolve failed unrecoverably */ +#define SPBCG_PSET_FAIL_UNREC -4 /* pset failed unrecoverably */ + +/* + * ----------------------------------------------------------------- + * Function : SpbcgFree + * ----------------------------------------------------------------- + * SpbcgFree frees the memory allocated by a call to SpbcgMalloc. + * It is illegal to use the pointer mem after a call to SpbcgFree. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void SpbcgFree(SpbcgMem mem); + +/* + * ----------------------------------------------------------------- + * Macro : SPBCG_VTEMP + * ----------------------------------------------------------------- + * This macro provides access to the vector r in the + * memory block of the SPBCG module. The argument mem is the + * memory pointer returned by SpbcgMalloc, of type SpbcgMem, + * and the macro value is of type N_Vector. + * + * Note: Only used by IDA (r contains P_inverse F if nli_inc == 0). + * ----------------------------------------------------------------- + */ + +#define SPBCG_VTEMP(mem) (mem->r) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/sundials_spgmr.h b/odemex/Parser/CVode/cv_src/include/sundials_spgmr.h new file mode 100644 index 0000000..c557acd --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials_spgmr.h @@ -0,0 +1,296 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the implementation of SPGMR Krylov + * iterative linear solver. The SPGMR algorithm is based on the + * Scaled Preconditioned GMRES (Generalized Minimal Residual) + * method. + * + * The SPGMR algorithm solves a linear system A x = b. + * Preconditioning is allowed on the left, right, or both. + * Scaling is allowed on both sides, and restarts are also allowed. + * We denote the preconditioner and scaling matrices as follows: + * P1 = left preconditioner + * P2 = right preconditioner + * S1 = diagonal matrix of scale factors for P1-inverse b + * S2 = diagonal matrix of scale factors for P2 x + * The matrices A, P1, and P2 are not required explicitly; only + * routines that provide A, P1-inverse, and P2-inverse as + * operators are required. + * + * In this notation, SPGMR applies the underlying GMRES method to + * the equivalent transformed system + * Abar xbar = bbar , where + * Abar = S1 (P1-inverse) A (P2-inverse) (S2-inverse) , + * bbar = S1 (P1-inverse) b , and xbar = S2 P2 x . + * + * The scaling matrices must be chosen so that vectors S1 + * P1-inverse b and S2 P2 x have dimensionless components. + * If preconditioning is done on the left only (P2 = I), by a + * matrix P, then S2 must be a scaling for x, while S1 is a + * scaling for P-inverse b, and so may also be taken as a scaling + * for x. Similarly, if preconditioning is done on the right only + * (P1 = I, P2 = P), then S1 must be a scaling for b, while S2 is + * a scaling for P x, and may also be taken as a scaling for b. + * + * The stopping test for the SPGMR iterations is on the L2 norm of + * the scaled preconditioned residual: + * || bbar - Abar xbar ||_2 < delta + * with an input test constant delta. + * + * The usage of this SPGMR solver involves supplying two routines + * and making three calls. The user-supplied routines are + * atimes (A_data, x, y) to compute y = A x, given x, + * and + * psolve (P_data, x, y, lr) + * to solve P1 x = y or P2 x = y for x, given y. + * The three user calls are: + * mem = SpgmrMalloc(lmax, vec_tmpl); + * to initialize memory, + * flag = SpgmrSolve(mem,A_data,x,b,..., + * P_data,s1,s2,atimes,psolve,...); + * to solve the system, and + * SpgmrFree(mem); + * to free the memory created by SpgmrMalloc. + * Complete details for specifying atimes and psolve and for the + * usage calls are given in the paragraphs below and in iterative.h. + * ----------------------------------------------------------------- + */ + +#ifndef _SPGMR_H +#define _SPGMR_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Types: SpgmrMemRec, SpgmrMem + * ----------------------------------------------------------------- + * SpgmrMem is a pointer to an SpgmrMemRec which contains + * the memory needed by SpgmrSolve. The SpgmrMalloc routine + * returns a pointer of type SpgmrMem which should then be passed + * in subsequent calls to SpgmrSolve. The SpgmrFree routine frees + * the memory allocated by SpgmrMalloc. + * + * l_max is the maximum Krylov dimension that SpgmrSolve will be + * permitted to use. + * + * V is the array of Krylov basis vectors v_1, ..., v_(l_max+1), + * stored in V[0], ..., V[l_max], where l_max is the second + * parameter to SpgmrMalloc. Each v_i is a vector of type + * N_Vector. + * + * Hes is the (l_max+1) x l_max Hessenberg matrix. It is stored + * row-wise so that the (i,j)th element is given by Hes[i][j]. + * + * givens is a length 2*l_max array which represents the + * Givens rotation matrices that arise in the algorithm. The + * Givens rotation matrices F_0, F_1, ..., F_j, where F_i is + * + * 1 + * 1 + * c_i -s_i <--- row i + * s_i c_i + * 1 + * 1 + * + * are represented in the givens vector as + * givens[0]=c_0, givens[1]=s_0, givens[2]=c_1, givens[3]=s_1, + * ..., givens[2j]=c_j, givens[2j+1]=s_j. + * + * xcor is a vector (type N_Vector) which holds the scaled, + * preconditioned correction to the initial guess. + * + * yg is a length (l_max+1) array of realtype used to hold "short" + * vectors (e.g. y and g). + * + * vtemp is a vector (type N_Vector) used as temporary vector + * storage during calculations. + * ----------------------------------------------------------------- + */ + +typedef struct _SpgmrMemRec { + + int l_max; + + N_Vector *V; + realtype **Hes; + realtype *givens; + N_Vector xcor; + realtype *yg; + N_Vector vtemp; + +} SpgmrMemRec, *SpgmrMem; + +/* + * ----------------------------------------------------------------- + * Function : SpgmrMalloc + * ----------------------------------------------------------------- + * SpgmrMalloc allocates the memory used by SpgmrSolve. It + * returns a pointer of type SpgmrMem which the user of the + * SPGMR package should pass to SpgmrSolve. The parameter l_max + * is the maximum Krylov dimension that SpgmrSolve will be + * permitted to use. The parameter vec_tmpl is a pointer to an + * N_Vector used as a template to create new vectors by duplication. + * This routine returns NULL if there is a memory request failure. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT SpgmrMem SpgmrMalloc(int l_max, N_Vector vec_tmpl); + +/* + * ----------------------------------------------------------------- + * Function : SpgmrSolve + * ----------------------------------------------------------------- + * SpgmrSolve solves the linear system Ax = b using the SPGMR + * method. The return values are given by the symbolic constants + * below. The first SpgmrSolve parameter is a pointer to memory + * allocated by a prior call to SpgmrMalloc. + * + * mem is the pointer returned by SpgmrMalloc to the structure + * containing the memory needed by SpgmrSolve. + * + * A_data is a pointer to information about the coefficient + * matrix A. This pointer is passed to the user-supplied function + * atimes. + * + * x is the initial guess x_0 upon entry and the solution + * N_Vector upon exit with return value SPGMR_SUCCESS or + * SPGMR_RES_REDUCED. For all other return values, the output x + * is undefined. + * + * b is the right hand side N_Vector. It is undisturbed by this + * function. + * + * pretype is the type of preconditioning to be used. Its + * legal possible values are enumerated in iterativ.h. These + * values are PREC_NONE=0, PREC_LEFT=1, PREC_RIGHT=2, and + * PREC_BOTH=3. + * + * gstype is the type of Gram-Schmidt orthogonalization to be + * used. Its legal values are enumerated in iterativ.h. These + * values are MODIFIED_GS=0 and CLASSICAL_GS=1. + * + * delta is the tolerance on the L2 norm of the scaled, + * preconditioned residual. On return with value SPGMR_SUCCESS, + * this residual satisfies || s1 P1_inv (b - Ax) ||_2 <= delta. + * + * max_restarts is the maximum number of times the algorithm is + * allowed to restart. + * + * P_data is a pointer to preconditioner information. This + * pointer is passed to the user-supplied function psolve. + * + * s1 is an N_Vector of positive scale factors for P1-inv b, where + * P1 is the left preconditioner. (Not tested for positivity.) + * Pass NULL if no scaling on P1-inv b is required. + * + * s2 is an N_Vector of positive scale factors for P2 x, where + * P2 is the right preconditioner. (Not tested for positivity.) + * Pass NULL if no scaling on P2 x is required. + * + * atimes is the user-supplied function which performs the + * operation of multiplying A by a given vector. Its description + * is given in iterative.h. + * + * psolve is the user-supplied function which solves a + * preconditioner system Pz = r, where P is P1 or P2. Its full + * description is given in iterativ.h. The psolve function will + * not be called if pretype is NONE; in that case, the user + * should pass NULL for psolve. + * + * res_norm is a pointer to the L2 norm of the scaled, + * preconditioned residual. On return with value SPGMR_SUCCESS or + * SPGMR_RES_REDUCED, (*res_norm) contains the value + * || s1 P1_inv (b - Ax) ||_2 for the computed solution x. + * For all other return values, (*res_norm) is undefined. The + * caller is responsible for allocating the memory (*res_norm) + * to be filled in by SpgmrSolve. + * + * nli is a pointer to the number of linear iterations done in + * the execution of SpgmrSolve. The caller is responsible for + * allocating the memory (*nli) to be filled in by SpgmrSolve. + * + * nps is a pointer to the number of calls made to psolve during + * the execution of SpgmrSolve. The caller is responsible for + * allocating the memory (*nps) to be filled in by SpgmrSolve. + * + * Note: Repeated calls can be made to SpgmrSolve with varying + * input arguments. If, however, the problem size N or the + * maximum Krylov dimension l_max changes, then a call to + * SpgmrMalloc must be made to obtain new memory for SpgmrSolve + * to use. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int SpgmrSolve(SpgmrMem mem, void *A_data, N_Vector x, N_Vector b, + int pretype, int gstype, realtype delta, + int max_restarts, void *P_data, N_Vector s1, + N_Vector s2, ATimesFn atimes, PSolveFn psolve, + realtype *res_norm, int *nli, int *nps); + + +/* Return values for SpgmrSolve */ + +#define SPGMR_SUCCESS 0 /* Converged */ +#define SPGMR_RES_REDUCED 1 /* Did not converge, but reduced + norm of residual */ +#define SPGMR_CONV_FAIL 2 /* Failed to converge */ +#define SPGMR_QRFACT_FAIL 3 /* QRfact found singular matrix */ +#define SPGMR_PSOLVE_FAIL_REC 4 /* psolve failed recoverably */ +#define SPGMR_ATIMES_FAIL_REC 5 /* atimes failed recoverably */ +#define SPGMR_PSET_FAIL_REC 6 /* pset faild recoverably */ + +#define SPGMR_MEM_NULL -1 /* mem argument is NULL */ +#define SPGMR_ATIMES_FAIL_UNREC -2 /* atimes returned failure flag */ +#define SPGMR_PSOLVE_FAIL_UNREC -3 /* psolve failed unrecoverably */ +#define SPGMR_GS_FAIL -4 /* Gram-Schmidt routine faiuled */ +#define SPGMR_QRSOL_FAIL -5 /* QRsol found singular R */ +#define SPGMR_PSET_FAIL_UNREC -6 /* pset failed unrecoverably */ + +/* + * ----------------------------------------------------------------- + * Function : SpgmrFree + * ----------------------------------------------------------------- + * SpgmrMalloc frees the memory allocated by SpgmrMalloc. It is + * illegal to use the pointer mem after a call to SpgmrFree. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void SpgmrFree(SpgmrMem mem); + +/* + * ----------------------------------------------------------------- + * Macro: SPGMR_VTEMP + * ----------------------------------------------------------------- + * This macro provides access to the work vector vtemp in the + * memory block of the SPGMR module. The argument mem is the + * memory pointer returned by SpgmrMalloc, of type SpgmrMem, + * and the macro value is of type N_Vector. + * On a return from SpgmrSolve with *nli = 0, this vector + * contains the scaled preconditioned initial residual, + * s1 * P1_inverse * (b - A x_0). + * ----------------------------------------------------------------- + */ + +#define SPGMR_VTEMP(mem) (mem->vtemp) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/sundials_sptfqmr.h b/odemex/Parser/CVode/cv_src/include/sundials_sptfqmr.h new file mode 100644 index 0000000..2ba5c37 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials_sptfqmr.h @@ -0,0 +1,254 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the implementation of the scaled + * preconditioned Transpose-Free Quasi-Minimal Residual (SPTFQMR) + * linear solver. + * + * The SPTFQMR algorithm solves a linear system of the form Ax = b. + * Preconditioning is allowed on the left (PREC_LEFT), right + * (PREC_RIGHT), or both (PREC_BOTH). Scaling is allowed on both + * sides. We denote the preconditioner and scaling matrices as + * follows: + * P1 = left preconditioner + * P2 = right preconditioner + * S1 = diagonal matrix of scale factors for P1-inverse b + * S2 = diagonal matrix of scale factors for P2 x + * The matrices A, P1, and P2 are not required explicitly; only + * routines that provide A, P1-inverse, and P2-inverse as operators + * are required. + * + * In this notation, SPTFQMR applies the underlying TFQMR method to + * the equivalent transformed system: + * Abar xbar = bbar, where + * Abar = S1 (P1-inverse) A (P2-inverse) (S2-inverse), + * bbar = S1 (P1-inverse) b, and + * xbar = S2 P2 x. + * + * The scaling matrices must be chosen so that vectors + * S1 P1-inverse b and S2 P2 x have dimensionless components. If + * preconditioning is done on the left only (P2 = I), by a matrix P, + * then S2 must be a scaling for x, while S1 is a scaling for + * P-inverse b, and so may also be taken as a scaling for x. + * Similarly, if preconditioning is done on the right only (P1 = I, + * P2 = P), then S1 must be a scaling for b, while S2 is a scaling + * for P x, and may also be taken as a scaling for b. + * + * The stopping test for the SPTFQMR iterations is on the L2-norm of + * the scaled preconditioned residual: + * || bbar - Abar xbar ||_2 < delta + * with an input test constant delta. + * + * The usage of this SPTFQMR solver involves supplying two routines + * and making three calls. The user-supplied routines are: + * atimes(A_data, x, y) to compute y = A x, given x, + * and + * psolve(P_data, x, y, lr) to solve P1 x = y or P2 x = y for x, + * given y. + * The three user calls are: + * mem = SptfqmrMalloc(lmax, vec_tmpl); + * to initialize memory + * flag = SptfqmrSolve(mem, A_data, x, b, pretype, delta, P_data, + * sx, sb, atimes, psolve, res_norm, nli, nps); + * to solve the system, and + * SptfqmrFree(mem); + * to free the memory allocated by SptfqmrMalloc(). + * Complete details for specifying atimes() and psolve() and for the + * usage calls are given in the paragraphs below and in the header + * file sundials_iterative.h. + * ----------------------------------------------------------------- + */ + +#ifndef _SPTFQMR_H +#define _SPTFQMR_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Types: struct SptfqmrMemRec and struct *SptfqmrMem + * ----------------------------------------------------------------- + * A variable declaration of type struct *SptfqmrMem denotes a pointer + * to a data structure of type struct SptfqmrMemRec. The SptfqmrMemRec + * structure contains numerous fields that must be accessed by the + * SPTFQMR linear solver module. + * + * l_max maximum Krylov subspace dimension that SptfqmrSolve will + * be permitted to use + * + * r_star vector (type N_Vector) which holds the initial scaled, + * preconditioned linear system residual + * + * q/d/v/p/u/r vectors (type N_Vector) used for workspace by + * the SPTFQMR algorithm + * + * vtemp1/vtemp2/vtemp3 scratch vectors (type N_Vector) used as + * temporary storage + * ----------------------------------------------------------------- + */ + +typedef struct { + + int l_max; + + N_Vector r_star; + N_Vector q; + N_Vector d; + N_Vector v; + N_Vector p; + N_Vector *r; + N_Vector u; + N_Vector vtemp1; + N_Vector vtemp2; + N_Vector vtemp3; + +} SptfqmrMemRec, *SptfqmrMem; + +/* + * ----------------------------------------------------------------- + * Function : SptfqmrMalloc + * ----------------------------------------------------------------- + * SptfqmrMalloc allocates additional memory needed by the SPTFQMR + * linear solver module. + * + * l_max maximum Krylov subspace dimension that SptfqmrSolve will + * be permitted to use + * + * vec_tmpl implementation-specific template vector (type N_Vector) + * (created using either N_VNew_Serial or N_VNew_Parallel) + * + * If successful, SptfqmrMalloc returns a non-NULL memory pointer. If + * an error occurs, then a NULL pointer is returned. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT SptfqmrMem SptfqmrMalloc(int l_max, N_Vector vec_tmpl); + +/* + * ----------------------------------------------------------------- + * Function : SptfqmrSolve + * ----------------------------------------------------------------- + * SptfqmrSolve solves the linear system Ax = b by means of a scaled + * preconditioned Transpose-Free Quasi-Minimal Residual (SPTFQMR) + * method. + * + * mem pointer to an internal memory block allocated during a + * prior call to SptfqmrMalloc + * + * A_data pointer to a data structure containing information + * about the coefficient matrix A (passed to user-supplied + * function referenced by atimes (function pointer)) + * + * x vector (type N_Vector) containing initial guess x_0 upon + * entry, but which upon return contains an approximate solution + * of the linear system Ax = b (solution only valid if return + * value is either SPTFQMR_SUCCESS or SPTFQMR_RES_REDUCED) + * + * b vector (type N_Vector) set to the right-hand side vector b + * of the linear system (undisturbed by function) + * + * pretype variable (type int) indicating the type of + * preconditioning to be used (see sundials_iterative.h) + * + * delta tolerance on the L2 norm of the scaled, preconditioned + * residual (if return value == SPTFQMR_SUCCESS, then + * ||sb*P1_inv*(b-Ax)||_L2 <= delta) + * + * P_data pointer to a data structure containing preconditioner + * information (passed to user-supplied function referenced + * by psolve (function pointer)) + * + * sx vector (type N_Vector) containing positive scaling factors + * for x (pass sx == NULL if scaling NOT required) + * + * sb vector (type N_Vector) containing positive scaling factors + * for b (pass sb == NULL if scaling NOT required) + * + * atimes user-supplied routine responsible for computing the + * matrix-vector product Ax (see sundials_iterative.h) + * + * psolve user-supplied routine responsible for solving the + * preconditioned linear system Pz = r (ignored if + * pretype == PREC_NONE) (see sundials_iterative.h) + * + * res_norm pointer (type realtype*) to the L2 norm of the + * scaled, preconditioned residual (if return value + * is either SPTFQMR_SUCCESS or SPTFQMR_RES_REDUCED, then + * *res_norm = ||sb*P1_inv*(b-Ax)||_L2, where x is + * the computed approximate solution, sb is the diagonal + * scaling matrix for the right-hand side b, and P1_inv + * is the inverse of the left-preconditioner matrix) + * + * nli pointer (type int*) to the total number of linear + * iterations performed + * + * nps pointer (type int*) to the total number of calls made + * to the psolve routine + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int SptfqmrSolve(SptfqmrMem mem, void *A_data, N_Vector x, N_Vector b, + int pretype, realtype delta, void *P_data, N_Vector sx, + N_Vector sb, ATimesFn atimes, PSolveFn psolve, + realtype *res_norm, int *nli, int *nps); + +/* Return values for SptfqmrSolve */ + +#define SPTFQMR_SUCCESS 0 /* SPTFQMR algorithm converged */ +#define SPTFQMR_RES_REDUCED 1 /* SPTFQMR did NOT converge, but the + residual was reduced */ +#define SPTFQMR_CONV_FAIL 2 /* SPTFQMR algorithm failed to converge */ +#define SPTFQMR_PSOLVE_FAIL_REC 3 /* psolve failed recoverably */ +#define SPTFQMR_ATIMES_FAIL_REC 4 /* atimes failed recoverably */ +#define SPTFQMR_PSET_FAIL_REC 5 /* pset faild recoverably */ + +#define SPTFQMR_MEM_NULL -1 /* mem argument is NULL */ +#define SPTFQMR_ATIMES_FAIL_UNREC -2 /* atimes returned failure flag */ +#define SPTFQMR_PSOLVE_FAIL_UNREC -3 /* psolve failed unrecoverably */ +#define SPTFQMR_PSET_FAIL_UNREC -4 /* pset failed unrecoverably */ + +/* + * ----------------------------------------------------------------- + * Function : SptfqmrFree + * ----------------------------------------------------------------- + * SptfqmrFree frees the memory allocated by a call to SptfqmrMalloc. + * It is illegal to use the pointer mem after a call to SptfqmrFree. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void SptfqmrFree(SptfqmrMem mem); + +/* + * ----------------------------------------------------------------- + * Macro : SPTFQMR_VTEMP + * ----------------------------------------------------------------- + * This macro provides access to the work vector vtemp1 in the + * memory block of the SPTFQMR module. The argument mem is the + * memory pointer returned by SptfqmrMalloc, of type SptfqmrMem, + * and the macro value is of type N_Vector. + * + * Note: Only used by IDA (vtemp1 contains P_inverse F if + * nli_inc == 0). + * ----------------------------------------------------------------- + */ + +#define SPTFQMR_VTEMP(mem) (mem->vtemp1) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/include/sundials_types.h b/odemex/Parser/CVode/cv_src/include/sundials_types.h new file mode 100644 index 0000000..953f6e0 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/include/sundials_types.h @@ -0,0 +1,122 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott Cohen, Alan Hindmarsh, Radu Serban, and + * Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + *------------------------------------------------------------------ + * This header file exports two types: realtype and booleantype, + * as well as the constants TRUE and FALSE. + * + * Users should include the header file sundials_types.h in every + * program file and use the exported name realtype instead of + * float, double or long double. + * + * The constants SUNDIALS_SINGLE_PRECISION, SUNDIALS_DOUBLE_PRECISION + * and SUNDIALS_LONG_DOUBLE_PRECISION indicate the underlying data + * type of realtype. It is set at the configuration stage. + * + * The legal types for realtype are float, double and long double. + * + * The macro RCONST gives the user a convenient way to define + * real-valued constants. To use the constant 1.0, for example, + * the user should write the following: + * + * #define ONE RCONST(1.0) + * + * If realtype is defined as a double, then RCONST(1.0) expands + * to 1.0. If realtype is defined as a float, then RCONST(1.0) + * expands to 1.0F. If realtype is defined as a long double, + * then RCONST(1.0) expands to 1.0L. There is never a need to + * explicitly cast 1.0 to (realtype). + *------------------------------------------------------------------ + */ + +#ifndef _SUNDIALSTYPES_H +#define _SUNDIALSTYPES_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#ifndef _SUNDIALS_CONFIG_H +#define _SUNDIALS_CONFIG_H +#include +#endif + +#include + +/* + *------------------------------------------------------------------ + * Type realtype + * Macro RCONST + * Constants BIG_REAL, SMALL_REAL, and UNIT_ROUNDOFF + *------------------------------------------------------------------ + */ + +#if defined(SUNDIALS_SINGLE_PRECISION) + +typedef float realtype; +# define RCONST(x) x##F +# define BIG_REAL FLT_MAX +# define SMALL_REAL FLT_MIN +# define UNIT_ROUNDOFF FLT_EPSILON + +#elif defined(SUNDIALS_DOUBLE_PRECISION) + +typedef double realtype; +# define RCONST(x) x +# define BIG_REAL DBL_MAX +# define SMALL_REAL DBL_MIN +# define UNIT_ROUNDOFF DBL_EPSILON + +#elif defined(SUNDIALS_EXTENDED_PRECISION) + +typedef long double realtype; +# define RCONST(x) x##L +# define BIG_REAL LDBL_MAX +# define SMALL_REAL LDBL_MIN +# define UNIT_ROUNDOFF LDBL_EPSILON + +#endif + +/* + *------------------------------------------------------------------ + * Type : booleantype + *------------------------------------------------------------------ + * Constants : FALSE and TRUE + *------------------------------------------------------------------ + * ANSI C does not have a built-in boolean data type. Below is the + * definition for a new type called booleantype. The advantage of + * using the name booleantype (instead of int) is an increase in + * code readability. It also allows the programmer to make a + * distinction between int and boolean data. Variables of type + * booleantype are intended to have only the two values FALSE and + * TRUE which are defined below to be equal to 0 and 1, + * respectively. + *------------------------------------------------------------------ + */ + +#ifndef booleantype +#define booleantype int +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/src/cvodes/CMakeLists.txt b/odemex/Parser/CVode/cv_src/src/cvodes/CMakeLists.txt new file mode 100644 index 0000000..d1724b7 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/cvodes/CMakeLists.txt @@ -0,0 +1,131 @@ +# --------------------------------------------------------------- +# $Revision: 1.4 $ +# $Date: 2009/02/17 02:58:47 $ +# --------------------------------------------------------------- +# Programmer: Radu Serban @ LLNL +# --------------------------------------------------------------- +# Copyright (c) 2007, The Regents of the University of California. +# Produced at the Lawrence Livermore National Laboratory. +# All rights reserved. +# For details, see the LICENSE file. +# --------------------------------------------------------------- +# CMakeLists.txt file for the CVODES library + +INSTALL(CODE "MESSAGE(\"\nInstall CVODES\n\")") + +# Add variable cvodes_SOURCES with the sources for the CVODES library +SET(cvodes_SOURCES + cvodes.c + cvodea.c + cvodes_io.c + cvodea_io.c + cvodes_direct.c + cvodes_band.c + cvodes_dense.c + cvodes_diag.c + cvodes_spils.c + cvodes_spbcgs.c + cvodes_spgmr.c + cvodes_sptfqmr.c + cvodes_bandpre.c + cvodes_bbdpre.c + ) + +# Add variable shared_SOURCES with the common SUNDIALS sources which will +# also be included in the CVODES library +SET(shared_SOURCES + sundials_nvector.c + sundials_math.c + sundials_direct.c + sundials_band.c + sundials_dense.c + sundials_iterative.c + sundials_spbcgs.c + sundials_spgmr.c + sundials_sptfqmr.c + ) + +# Add prefix with complete path to the common SUNDIALS sources +ADD_PREFIX(${sundials_SOURCE_DIR}/src/sundials/ shared_SOURCES) + +# Add variable cvodes_HEADERS with the exported CVODES header files +SET(cvodes_HEADERS + cvodes_band.h + cvodes_bandpre.h + cvodes_bbdpre.h + cvodes_dense.h + cvodes_diag.h + cvodes_direct.h + cvodes.h + cvodes_spbcgs.h + cvodes_spgmr.h + cvodes_spils.h + cvodes_sptfqmr.h + ) + +# Add prefix with complete path to the CVODES header files +ADD_PREFIX(${sundials_SOURCE_DIR}/include/cvodes/ cvodes_HEADERS) + +# If Blas/Lapack support was enabled, set-up additional file lists +IF(LAPACK_FOUND) + SET(cvodes_BL_SOURCES cvodes_lapack.c) + SET(cvodes_BL_HEADERS cvodes_lapack.h) + ADD_PREFIX(${sundials_SOURCE_DIR}/include/cvodes/ cvodes_BL_HEADERS) +ELSE(LAPACK_FOUND) + SET(cvodes_BL_SOURCES "") + SET(cvodes_BL_HEADERS "") +ENDIF(LAPACK_FOUND) + + +# Add source directories to include directories for access to +# implementation only header files. +INCLUDE_DIRECTORIES(.) +INCLUDE_DIRECTORIES(../sundials) + +# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY +ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY) + +# Build the static library +IF(BUILD_STATIC_LIBS) + + # Add the build target for the static CVODES library + ADD_LIBRARY(sundials_cvodes_static STATIC + ${cvodes_SOURCES} ${cvodes_BL_SOURCES} ${shared_SOURCES}) + + # Set the library name and make sure it is not deleted + SET_TARGET_PROPERTIES(sundials_cvodes_static + PROPERTIES OUTPUT_NAME sundials_cvodes CLEAN_DIRECT_OUTPUT 1) + + # Install the CVODES library + INSTALL(TARGETS sundials_cvodes_static DESTINATION lib) + +ENDIF(BUILD_STATIC_LIBS) + +# Build the shared library +IF(BUILD_SHARED_LIBS) + + # Add the build target for the CVODES library + ADD_LIBRARY(sundials_cvodes_shared SHARED + ${cvodes_SOURCES} ${cvodes_BL_SOURCES} ${shared_SOURCES}) + + # Set the library name and make sure it is not deleted + SET_TARGET_PROPERTIES(sundials_cvodes_shared + PROPERTIES OUTPUT_NAME sundials_cvodes CLEAN_DIRECT_OUTPUT 1) + + # Set VERSION and SOVERSION for shared libraries + SET_TARGET_PROPERTIES(sundials_cvodes_shared + PROPERTIES VERSION ${cvodeslib_VERSION} SOVERSION ${cvodeslib_SOVERSION}) + + # Install the CVODES library + INSTALL(TARGETS sundials_cvodes_shared DESTINATION lib) + +ENDIF(BUILD_SHARED_LIBS) + +# Install the CVODES header files +INSTALL(FILES ${cvodes_HEADERS} ${cvodes_BL_HEADERS} DESTINATION include/cvodes) + +# Install the CVODES implementation header file +INSTALL(FILES cvodes_impl.h DESTINATION include/cvodes) + +# +MESSAGE(STATUS "Added CVODES module") diff --git a/odemex/Parser/CVode/cv_src/src/cvodes/LICENSE b/odemex/Parser/CVode/cv_src/src/cvodes/LICENSE new file mode 100644 index 0000000..dd9a383 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/cvodes/LICENSE @@ -0,0 +1,59 @@ +Copyright (c) 2002, The Regents of the University of California. +Produced at the Lawrence Livermore National Laboratory +Written by A.C. Hindmarsh and R. Serban. +UCRL-CODE-155950 +All rights reserved. + +This file is part of CVODES v2.1.0. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the disclaimer below. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the disclaimer (as noted below) +in the documentation and/or other materials provided with the +distribution. + +3. Neither the name of the UC/LLNL nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +REGENTS OF THE UNIVERSITY OF CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Additional BSD Notice +--------------------- +1. This notice is required to be provided under our contract with +the U.S. Department of Energy (DOE). This work was produced at the +University of California, Lawrence Livermore National Laboratory +under Contract No. W-7405-ENG-48 with the DOE. + +2. Neither the United States Government nor the University of +California nor any of their employees, makes any warranty, express +or implied, or assumes any liability or responsibility for the +accuracy, completeness, or usefulness of any information, apparatus, +product, or process disclosed, or represents that its use would not +infringe privately-owned rights. + +3. Also, reference herein to any specific commercial products, +process, or services by trade name, trademark, manufacturer or +otherwise does not necessarily constitute or imply its endorsement, +recommendation, or favoring by the United States Government or the +University of California. The views and opinions of authors expressed +herein do not necessarily state or reflect those of the United States +Government or the University of California, and shall not be used for +advertising or product endorsement purposes. diff --git a/odemex/Parser/CVode/cv_src/src/cvodes/Makefile.in b/odemex/Parser/CVode/cv_src/src/cvodes/Makefile.in new file mode 100644 index 0000000..9cf23cb --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/cvodes/Makefile.in @@ -0,0 +1,180 @@ +# ----------------------------------------------------------------- +# $Revision: 1.12 $ +# $Date: 2009/03/25 23:10:50 $ +# ----------------------------------------------------------------- +# Programmer(s): Radu Serban and Aaron Collier @ LLNL +# ----------------------------------------------------------------- +# Copyright (c) 2005, The Regents of the University of California. +# Produced at the Lawrence Livermore National Laboratory. +# All rights reserved. +# For details, see the LICENSE file. +# ----------------------------------------------------------------- +# Makefile for CVODES module +# +# @configure_input@ +# ----------------------------------------------------------------- + +SHELL = @SHELL@ + +@SET_MAKE@ + +srcdir = @srcdir@ +builddir = @builddir@ +abs_builddir = @abs_builddir@ +top_builddir = @top_builddir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +includedir = @includedir@ +libdir = @libdir@ + +INSTALL = @INSTALL@ +INSTALL_LIB = @INSTALL_PROGRAM@ +INSTALL_HEADER = @INSTALL_DATA@ + +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ + +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CC = @CC@ +CFLAGS = @CFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ + +LAPACK_ENABLED = @LAPACK_ENABLED@ + +top_srcdir = $(srcdir)/../.. + +INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include + +LIB_REVISION = 2:0:0 + +CVODES_LIB = libsundials_cvodes.la + +CVODES_SRC_FILES = cvodes.c cvodes_io.c cvodea.c cvodea_io.c cvodes_direct.c cvodes_band.c cvodes_dense.c cvodes_diag.c cvodes_spils.c cvodes_spbcgs.c cvodes_spgmr.c cvodes_sptfqmr.c cvodes_bandpre.c cvodes_bbdpre.c +CVODES_BL_SRC_FILES = cvodes_lapack.c + +CVODES_OBJ_FILES = $(CVODES_SRC_FILES:.c=.o) +CVODES_BL_OBJ_FILES = $(CVODES_BL_SRC_FILES:.c=.o) + +CVODES_LIB_FILES = $(CVODES_SRC_FILES:.c=.lo) +CVODES_BL_LIB_FILES = $(CVODES_BL_SRC_FILES:.c=.lo) + +SHARED_LIB_FILES = $(top_builddir)/src/sundials/sundials_band.lo \ + $(top_builddir)/src/sundials/sundials_dense.lo \ + $(top_builddir)/src/sundials/sundials_direct.lo \ + $(top_builddir)/src/sundials/sundials_iterative.lo \ + $(top_builddir)/src/sundials/sundials_spgmr.lo \ + $(top_builddir)/src/sundials/sundials_spbcgs.lo \ + $(top_builddir)/src/sundials/sundials_sptfqmr.lo \ + $(top_builddir)/src/sundials/sundials_math.lo \ + $(top_builddir)/src/sundials/sundials_nvector.lo + +mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs +rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs + +# ---------------------------------------------------------------------------------------------------------------------- + +all: $(CVODES_LIB) + +$(CVODES_LIB): shared $(CVODES_LIB_FILES) + @if test "X${LAPACK_ENABLED}" = "Xyes"; then \ + make lib_with_bl; \ + else \ + make lib_without_bl; \ + fi + +lib_without_bl: shared $(CVODES_LIB_FILES) + $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(CVODES_LIB) $(CVODES_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -version-info $(LIB_REVISION) + +lib_with_bl: shared $(CVODES_LIB_FILES) $(CVODES_BL_LIB_FILES) + $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(CVODES_LIB) $(CVODES_LIB_FILES) $(CVODES_BL_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -version-info $(LIB_REVISION) + +install: $(CVODES_LIB) + $(mkinstalldirs) $(includedir)/cvodes + $(mkinstalldirs) $(libdir) + $(LIBTOOL) --mode=install $(INSTALL_LIB) $(CVODES_LIB) $(libdir) + $(INSTALL_HEADER) $(top_srcdir)/include/cvodes/cvodes.h $(includedir)/cvodes/ + $(INSTALL_HEADER) $(top_srcdir)/include/cvodes/cvodes_direct.h $(includedir)/cvodes/ + $(INSTALL_HEADER) $(top_srcdir)/include/cvodes/cvodes_dense.h $(includedir)/cvodes/ + $(INSTALL_HEADER) $(top_srcdir)/include/cvodes/cvodes_band.h $(includedir)/cvodes/ + $(INSTALL_HEADER) $(top_srcdir)/include/cvodes/cvodes_diag.h $(includedir)/cvodes/ + $(INSTALL_HEADER) $(top_srcdir)/include/cvodes/cvodes_spils.h $(includedir)/cvodes/ + $(INSTALL_HEADER) $(top_srcdir)/include/cvodes/cvodes_spbcgs.h $(includedir)/cvodes/ + $(INSTALL_HEADER) $(top_srcdir)/include/cvodes/cvodes_spgmr.h $(includedir)/cvodes/ + $(INSTALL_HEADER) $(top_srcdir)/include/cvodes/cvodes_sptfqmr.h $(includedir)/cvodes/ + $(INSTALL_HEADER) $(top_srcdir)/include/cvodes/cvodes_bandpre.h $(includedir)/cvodes/ + $(INSTALL_HEADER) $(top_srcdir)/include/cvodes/cvodes_bbdpre.h $(includedir)/cvodes/ + $(INSTALL_HEADER) $(top_srcdir)/src/cvodes/cvodes_impl.h $(includedir)/cvodes/ + @if test "X${LAPACK_ENABLED}" = "Xyes"; then \ + $(INSTALL_HEADER) $(top_srcdir)/include/cvodes/cvodes_lapack.h $(includedir)/cvodes/ ; \ + fi + +uninstall: + $(LIBTOOL) --mode=uninstall rm -f $(libdir)/$(CVODES_LIB) + rm -f $(includedir)/cvodes/cvodes.h + rm -f $(includedir)/cvodes/cvodes_direct.h + rm -f $(includedir)/cvodes/cvodes_dense.h + rm -f $(includedir)/cvodes/cvodes_band.h + rm -f $(includedir)/cvodes/cvodes_diag.h + rm -f $(includedir)/cvodes/cvodes_lapack.h + rm -f $(includedir)/cvodes/cvodes_spils.h + rm -f $(includedir)/cvodes/cvodes_spbcgs.h + rm -f $(includedir)/cvodes/cvodes_spgmr.h + rm -f $(includedir)/cvodes/cvodes_sptfqmr.h + rm -f $(includedir)/cvodes/cvodes_bandpre.h + rm -f $(includedir)/cvodes/cvodes_bbdpre.h + rm -f $(includedir)/cvodes/cvodes_impl.h + $(rminstalldirs) ${includedir}/cvodes + +shared: + @cd ${top_builddir}/src/sundials ; \ + ${MAKE} ; \ + cd ${abs_builddir} + +clean: + $(LIBTOOL) --mode=clean rm -f $(CVODES_LIB) + rm -f $(CVODES_LIB_FILES) + rm -f $(CVODES_BL_LIB_FILES) + rm -f $(CVODES_OBJ_FILES) + rm -f $(CVODES_BL_OBJ_FILES) + +distclean: clean + rm -f Makefile + +cvodes.lo: $(srcdir)/cvodes.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodes.c +cvodes_io.lo: $(srcdir)/cvodes_io.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodes_io.c +cvodea.lo: $(srcdir)/cvodea.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodea.c +cvodea_io.lo: $(srcdir)/cvodea_io.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodea_io.c +cvodes_direct.lo: $(srcdir)/cvodes_direct.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodes_direct.c +cvodes_dense.lo: $(srcdir)/cvodes_dense.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodes_dense.c +cvodes_band.lo: $(srcdir)/cvodes_band.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodes_band.c +cvodes_diag.lo: $(srcdir)/cvodes_diag.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodes_diag.c +cvodes_lapack.lo: $(srcdir)/cvodes_lapack.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodes_lapack.c +cvodes_spils.lo: $(srcdir)/cvodes_spils.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodes_spils.c +cvodes_spbcgs.lo: $(srcdir)/cvodes_spils.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodes_spbcgs.c +cvodes_spgmr.lo: $(srcdir)/cvodes_spgmr.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodes_spgmr.c +cvodes_sptfqmr.lo: $(srcdir)/cvodes_sptfqmr.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodes_sptfqmr.c +cvodes_bandpre.lo: $(srcdir)/cvodes_bandpre.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodes_bandpre.c +cvodes_bbdpre.lo: $(srcdir)/cvodes_bbdpre.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/cvodes_bbdpre.c + + +libtool: $(top_builddir)/$(LIBTOOL_DEPS) + @cd ${top_builddir} ; \ + ${SHELL} ./config.status --recheck ; \ + cd ${abs_builddir} diff --git a/odemex/Parser/CVode/cv_src/src/cvodes/README b/odemex/Parser/CVode/cv_src/src/cvodes/README new file mode 100644 index 0000000..cfd3885 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/cvodes/README @@ -0,0 +1,431 @@ + CVODES + Release 2.6.0, January 2008 + Alan C. Hindmarsh and Radu Serban + Center for Applied Scientific Computing, LLNL + +CVODES is a solver for stiff and nonstiff ODE systems (initial value +problem) given in explicit form y' = f(t,y,p) with sensitivity analysis +capabilities (both forward and adjoint modes). +It is written in ANSI standard C. + +CVODES can be used both on serial and parallel (MPI) computers. The +main difference is in the NVECTOR module of vector kernels. The desired +version is obtained when compiling the example files by linking the +appropriate library of NVECTOR kernels. In the parallel version, +communication between processors is done with the MPI (Message Passage +Interface) system. + +When used with the serial NVECTOR module, CVODES provides both direct (dense +and band) and preconditioned Krylov (iterative) linear solvers. Three different +iterative solvers are available: scaled preconditioned GMRES (SPGMR), scaled +preconditioned BiCGStab (SPBCG), and scaled preconditioned TFQMR (SPTFQMR). +When CVODES is used with the parallel NVECTOR module, only the Krylov linear solvers +are available. (An approximate diagonal Jacobian option is available with both +versions.) For the serial version, there is a banded preconditioner module +called CVBANDPRE available for use with the Krylov solvers, while for the parallel +version there is a preconditioner module called CVBBDPRE which provides a +band-block-diagonal preconditioner. + +CVODES is part of a software family called SUNDIALS: SUite of Nonlinear and +DIfferential/ALgebraic equation Solvers [4]. This suite consists of CVODE, +CVODES, IDA, IDAS, and KINSOL. The directory structure of the package supplied +reflects this family relationship. + +The notes below provide the location of documentation, directions for the +installation of the CVODES package, and relevant references. Following that +is a brief history of revisions to the package. + + +A. Documentation +---------------- + +/sundials/doc/cvodes/ contains PDF files for the CVODES User Guide [1] (cvs_guide.pdf) +and the CVODES Examples [2] (cvs_examples.pdf) documents. + + +B. Installation +--------------- + +For basic installation instructions see /sundials/INSTALL_NOTES. +For complete installation instructions see the "CVODES Installation Procedure" +chapter in the CVODES User Guide. + + +C. References +------------- + +[1] A. C. Hindmarsh and R. Serban, "User Documentation for CVODES v2.6.0," + LLNL technical report UCRL-SM-208111, November 2004. + +[2] A. C. Hindmarsh and R. Serban, "Example Programs for CVODES v2.6.0," + LLNL technical report UCRL-SM-208115, November 2004. + +[3] R. Serban and A. C. Hindmarsh, "CVODES: the Sensitivity-Enabled ODE + solver in SUNDIALS," Proceedings of IDETC/CIE 2005, Sept. 2005, + Long Beach, CA. + +[4] A. C. Hindmarsh, P. N. Brown, K. E. Grant, S. L. Lee, R. Serban, + D. E. Shumaker, and C. S. Woodward, "SUNDIALS, Suite of Nonlinear and + Differential/Algebraic Equation Solvers," ACM Trans. Math. Softw., + 31(3), pp. 363-396, 2005. + +D. Releases +----------- + +v. 2.6.0 - Jan. 2008 +v. 2.5.0 - Nov. 2006 +v. 2.4.0 - Mar. 2006 +v. 2.3.0 - May. 2005 +v. 2.2.0 - Apr. 2005 +v. 2.1.2 - Mar. 2005 +v. 2.1.1 - Jan. 2005 +v. 2.1.0 - Dec. 2004 +v. 1.0 - Jul. 2002 (first SUNDIALS release) + + +E. Revision History +------------------- + +v. 2.5.0 (Nov. 2006) ---> v. 2.6.0 (Jan. 2008) +--------------------------------------------------------- + +- New features + - added a new linear solver module based on Blas + Lapack for + both dense and banded matrices. + - added optional input to specify which direction of zero-crossing + is to be monitored while performing root-finding. The root information + array iroots (returned by CVodeGetRootInfo) also encodes the + direction of zero-crossing. + - added support for performing FSA of quadrature variables (see functions + CVode**QuadSens**). + - in the adjoint module, added support for integrating forward sensitivities + of states and quadrature variables during the forward integration + phase (e.g. for computing 2nd order sensitivity information using + the "forward over adjoint" method). + - in the adjoint module, added support for propagating backwards in time + multiple adjoint systems, each initialized at posibly different times. + - added option for reinitializing the adjoint module in order to + solve a new adjoint problem (with same number of steps between + check points and the same interpolation type). + +- Bug fixes + - in the rootfinding algorithm, fixed a bug resulting in unnecessary + evaluations of the root functions after reinitialization of the + solver right after a return at a root. + - in the initial step size calculation, restrict h based on tstop. + +- Changes to user interface + - renamed all **Malloc functions to **Init + - tolerances are now specified through separate functions instead of + the initialization functions CVodeInit (former CVodeMalloc) and + CVodeReInit. Depending on the tolerance type, one of 3 functions + must be called before the first call to CVode. + - tolerances for quadratures, sensitivities, and quadrature sensitivities + are specified in a manner similar to that for state variables, with the + exception that toelrances for quadratures and quadrature sensitivities + are required only if the corresponding variables are included in the + error test. + - removed function inputs from argument lists of all re-initialization + functions. + - all user-supplied functions now receive the same pointer to user data + (instead of having different ones for the system evaluation, Jacobian + information functions, etc.) + - removed CV_NORMAL_TSTOP and CV_ONE_STEP_TSTOP named constants for the + itask argument to CVode/CVodeF. A tstop value is now both set and activated + through CVodeSetStopTime. Once tstop is reached it is also deactivated. + A new value can be then spcified by calling again CVodeSetStopTime. + - common functionality for all direct linear solvers (dense, band, and + the new Lapack solver) has been collected into the DLS (Direct Linear + Solver) module, similar to the SPILS module for the iterative linear + solvers. All optional input and output functions for these linear + solver now have the prefix 'CVDls'. In addition, in order to include + the new Lapack-based linear solver, all dimensions for these linear + solvers (problem sizes, bandwidths, etc) are now of type 'int' + (instead of 'long int'). + - the initialization functions for the two preconditioner modules, + CVBANDPRE and CVBBDPRE were renamed ***Init (from ***Alloc) and they + do not return a pointer to preconditioner memory anymore. Instead, + all preconditioner module-related functions are now called with + the main solver memory pointer as their first argument. When using + one of these two modules, there is no need to use special functions + to attach one of the SPILS linear solvers (instead use one of + CVSpgmr, CVSpbcg, or CVSptfqmr). Moreover, there is no need to call + a memory deallocation function for the preconditioner module. + - CVodeSensMalloc was replaced by CVodeSensInit and CvodeSensInit1. + The sensitivity RHS function is now passed as an argument to these + initialization functions. The former takes as argument fS a function + of type CVSensRhsFn, while the latter takes as argument fS1 of type + CVSensRhs1Fn. Removed the functions CVodeSetSensRhsFn and CVodeSetSensRhs1Fn. + - changed the API for all functions in the adjoint module related to + initialization, set-up, and solution of backward problems. A backward problem + is always identified by its index (of type int) returned by the CvodeCreateB + function. + - the extraction functions CVodeGetQuad, CVodeGetSens, and CVodeGetSens1 + now return the values of quadrature and sensitivity variables, respectively, + at the same time as that at which CVode returned the solution (for dense + output of quadrature or sensitivity variables, the user can only use + CVodeGetQuadDky, CVodeGetSensDky, or CVodeGetSensDky1). Similar functions are + available for the new quadrature sensitivity feature. + +v. 2.4.0 (Mar. 2006) ---> v. 2.5.0 (Nov. 2006) +--------------------------------------------------------- + +- Bug fixes + - fixed wrong logic in final stopping tests: now we check if + tout was reached before checking if tstop was reached. + - added a roundoff factor when testing whether tn was just returned + (in root finding) to prevent an unnecessary return. + - fixed bug in CVodeB in searching for the current check point + (i.e. the check point for which interpolation data is available) + - fixed bug in CVodeF to ensure that in NORMAL mode no extra + step is taken (which sometimes resulted in an error from the + interpolated output function). + - changed address variable type in CVadjCheckPointRec structure from + 'unsigned int' to 'void *' to avoid address truncation/mangling on + 64-bit platforms (see CVS_P1). + +- Changes related to the build system + - reorganized source tree: header files in ${srcdir}/include/cvodes, + source files in ${srcdir}/src/cvodes,examples in ${srcdir}/examples/cvodes + - exported header files are installed unde ${includedir}/cvodes + +- Changes to user interface + - all included header files use relative paths from ${includedir} + - changed the API for specifying the DQ method used to approximate + the sensitivity equations: renamed CVodeSetSensRho to CVodeSetSensDQMethod. + The user passes two values: DQtype (CV_CENTERED or CV_FORWARD) and + DQrhomax (the cut-off value for switching between simultaneous and + separate approximations of the two terms in the sensi. eqs.) + +v. 2.3.0 (May. 2005) ---> v. 2.4.0 (Mar. 2006) +--------------------------------------------------------- + +- New features + - added CVSPBCG interface module to allow CVODES to interface with the + shared SPBCG (scaled preconditioned Bi-CGSTAB) linear solver module. + - added CVSPTFQMR interface module to allow CVODES to interface with + the shared SPTFQMR (scaled preconditioned TFQMR) linear solver module. + - added support for SPBCG and SPTFQMR to the CVBBDPRE and CVBANDPRE + preconditioner modules. + - added support for interpreting failures in user-supplied functions. + - added a new variable-degree polynomial interpolation method as an + an alternative to the current cubic Hermite interpolation for the + adjoint module. + +- Changes to user interface + - changed argument of CVodeFree, CVBandPrecFree, CVBBDPrecFree, and + CVadjFree to be the address of the respective memory block pointer, + so that its NULL value is propagated back to the calling function. + - added CVSPBCG module which defines appropriate CVSpbcg* functions to + allow CVODES to interface with the shared SPBCG linear solver module. + - added CVBBDSpbcg function to CVBBDPRE module and CVBPSpbcg function to + CVBANDPRE module to support SPBCG linear solver module. + - added CVBBDSptfqmr function to CVBBDPRE module and CVBPSptfqmr function to + CVBANDPRE module to support SPTFQMR linear solver module. + - changed function type names (not the actual definition) to accomodate + all the Scaled Preconditioned Iterative Linear Solvers now available: + CVSpgmrJactimesVecFn -> CVSpilsJacTimesVecFn + CVSpgmrPrecSetupFn -> CVSpilsPrecSetupFn + CVSpgmrPrecSolveFn -> CVSpilsPrecSolveFn + - changed function types so that all user-supplied functions return + an integer flag (not all of them currently used). + - changed some names for CVBBDPRE and CVBANDPRE function outputs + - added option for user-supplied error handler function. + - added a argument to CVadjMalloc to specify the type of interpolation + (possible values are CV_HERMITE for cubic Hermite and CV_POLYNOMIAL + for variable-order polynomial interpolation) + - renamed all exported header files (except for cvodes.h and cvodea.h all + header files have the prefix 'cvodes_') + - changed naming scheme for CVODES examples + +- Changes related to the build system + - the main CVODES header files (cvodes.h and cvodea.h) are still exported to + the install include directory. However, all other CVODES header files are + exported into a 'cvodes' subdirectory of the install include directory. + - the CVODES library now contains all shared object files (there is no separate + libsundials_shared library anymore) + +v. 2.2.0 (Apr. 2005) ---> v. 2.3.0 (May. 2005) +---------------------------------------------- + +- Bug fixes + - in the adjoint module, fixed bug in storing interpolation data at + a point corresponding to a check point (improperly scaled y'). + +- Changes to user interface + - removed CVadjGetcheckPointsList from the list of user-callable functions. + +v. 2.1.2 (Mar. 2005) ---> v. 2.2.0 (Apr. 2005) +---------------------------------------------- + +- New features + - added option for user-provided error weight computation function for + the solution vector (of type CVEwtFn specified through CVodeSetEwtFn). + +- Changes to user interface + - CVODES now stores tolerances through values rather than references + (to resolve potential scoping issues). + - CVODES now passes information back to the user through values rather + than references (error weights, estimated local errors, root info, + STAGGERED1 statistics, etc.) + - CVodeMalloc, CVodeReInit, CVodeSetTolerances: added option itol=CV_WF + to indicate user-supplied function for computing the error weights; + reltol is now declared as realtype. Note that it is now illegal to call + CVodeSetTolerances before CVodeMalloc. It is now legal to deallocate + the absolute tolerance N_Vector right after its use. + - Several optional input functions were combined into a single one + (CVodeRootInit and CvodeSetGdata, CVDenseSetJacFn and CVDenseSetJacData, + CVBandSetJacFn and CVBandSetJacData, CVSpgmrSetPrecSolveFn and + CVSpgmrSetPrecSetFn and CVSpgmrSetPrecData, CVSpgmrSetJacTimesVecFn and + CVSpgmrSetJacData). + - Removed CVodeSetQuadtolerances. CVodeSetQuadErrCon now sets both the + error control flag and the tolerances for quadratures. + - CVodeSetQuadErrCon, CVodeSetSensTolerances: the relative tolerance + must now be passed as a realtype. It is now illegal to call + CVodeSetQuadErrCon before CVodeQuadMalloc or to call CVodeSetSensTolerances + before CVodeSensMalloc. + - CvodeSensMalloc: removed p and plist from argument list. + - CVodeSensParams replaces CVodeSensPbar and sets p, pbar, and plist. NULL + can be passed for any of them if it will not be needed given the current + set of options. The array pbar must now contain Ns non-zero realtype + values giving order of magnitude for the parameters with respect to which + sensitivities will be computed. The array plist can now only have positive + entries. + - CVodeGetErrorWeights, CVodeGetQuadErrorWeights: the user is now responsible + for allocating space for the N_Vector in which error weights will be copied. + - CVodeGetEstLocalErrors: the user is now responsible for allocating space + for the N_Vector in which estimated local errors will be copied. + - CVodeGetRootInfo: the user is now responsible for allocating space + for the int array in which root information will be copied. + - CVodeGetNumStgrSensNonlinSolvIters, CVodeGetNumStgrSensNonlinSolvConvFails: + the user is now responsible for allocating space for the long int arrays + in which STAGGERED1 statistics will be copied. + - CVodeMallocB, CVodeReInitB, CVodeSetQuadErrConB: the relative tolerance + for the backward integration must now be passed as a realtype. It is now + illegal to call CVodeSetQuadErrConB before CVQuadMallocB. + - Passing a value of 0 for the maximum step size, the minimum step + size, or for maxsteps results in the solver using the corresponding + default value (infinity, 0, 500, respectively) + - User-callable functions in the adjoint module were modified similarly + to their corresponding counterparts for forward simulation. + + +v. 2.1.1 (Jan. 2005) ---> v. 2.1.2 (Mar. 2005) +---------------------------------------------- + +- Bug fixes + - fixed bug in CVode function: Initial setting of tretlast = *tret = tn removed + (correcting erroneous behavior at first call to CVRcheck3). + - removed redundant setting of tretlast = *tret = tn at CLOSE_ROOTS return from CVode. + - fixed bug in CVCompleteStep related to quadrature and sensitivity variables + (leading to wrong values at a BDF order increase) + - in CVUpperBoundH0, fixed a potential, although not harmful, use of + uninitialized memory + - changed implicit type conversion to explicit in check_flag() routine in + examples to avoid C++ compiler errors + +- Changes to documentation + - added section with numerical values of all input and output solver constants + - added more detailed notes on the type of absolute tolerances + - added more details on ownership of memory for the array returned by CVodeGetRootInfo + - corrected/added descriptions of error returns. + - added description of --with-mpi-flags option + +- Changes related to the build system + - fixed autoconf-related bug to allow configuration with the PGI Fortran compiler + - modified to use customized detection of the Fortran name mangling scheme + (autoconf's AC_F77_WRAPPERS routine is problematic on some platforms) + - added --with-mpi-flags as a configure option to allow user to specify + MPI-specific flags + - updated Makefiles for Fortran examples to avoid C++ compiler errors (now use + CC and MPICC to link) + + +v. 2.1.0 (Dec. 2004) ---> v. 2.1.1 (Jan. 2005) +---------------------------------------------- + +- New features + - added function CVodeSensToggle to allow activation/deactivation of + sensitivity calculations without memory allocation/deallocation. + +- Bug fixes + - fixed bug in CVCompleteStep related to quadrature and sensitivity variables + (leading to wrong values at a BDF order increase). + - in CVUpperBoundH0, fixed a potential, although not harmful, use of + uninitialized memory. + - fixed logic in testing for negative values of user-supplied absolute tolerances + for sensitivity variables. + +- Changes related to the build system + - changed order of compiler directives in header files to avoid compilation + errors when using a C++ compiler. + +v. 1.0 (Jul. 2002) ---> v. 2.1.0 (Dec. 2004) +-------------------------------------------- + +- New features + - added quadrature integration capabilities. + - added root finding capabilities. + - added option for different user data structures for ODE r.h.s. + and sensitivity r.h.s. + - in adjoint module, added interface to CVBBDPRE for the backward + phase. + - in adjoint module, added option for using CVDIAG during backward + phase. + - in adjoint module, added option for ONE_STEP integration during + backward phase. + - in adjoint module, added option to reinitialize the backward + integration phase (and perform a new backward integration using + the same check points). + - in adjoint module, relaxed assumption that t_final > t_0 (now + accepts t_final < t_0). + +- Bug fixes + - fixed bug in adjustment of sensitivity Nordsieck history array on an + order decrease (when using BDF). + - in adjoint module, fixed a potential use of memory before being set. + - in adjoint module, fixed a bug related to data saved at check points. + This addresses the case in which an order increase is deemed necessary + at the very first step after a check-point. + +- Changes related to the NVECTOR module + (see also the file sundials/shared/README) + - removed machEnv, redefined table of vector operations (now contained + in the N_Vector structure itself). + - all CVODES functions create new N_Vector variables through cloning, using + an N_Vector passed by the user as a template. + +- Changes to type names and CVODES constants + - removed type 'integertype'; instead use int or long int, as appropriate. + - restructured the list of return values from the various CVODES functions. + - changed all CVODES constants (inputs and return values) to have the + prefix 'CV_' (e.g. CV_SUCCESS). + - renamed various function types to have the prefix 'CV' (e.g. CVRhsFn). + +- Changes to optional input/ouput + - added CVodeSet* and CVodeGet* functions for optional inputs/outputs, + replacing the arrays iopt and ropt. + - added new optional inputs (e.g. maximum number of Newton iterations, + maximum number of convergence failures, etc). + - the value of the last return flag from any function within a linear + solver module can be obtained as an optional output (e.g. CVDenseGetLastFlag). + +- Changes to user-callable functions + - renamed header files to have prefix 'cv' instead of 'cvs' (e.g. cvdense.h + replaces cvsdense.h). + - added new function CVodeCreate which initializes the CVODES solver + object and returns a pointer to the CVODES memory block. + - removed N (problem size) from all functions except the initialization + functions for the direct linear solvers (CVDense and CVBand). + - shortened argument lists of most CVODES functions (the arguments that + were dropped can now be specified through CVodeSet* functions). + - removed reinitialization functions for band/dense/SPGMR linear + solvers (same functionality can be obtained using CV*Set* functions). + - in CVBBDPRE, added a new function, CVBBDSpgmr to initialize the + SPGMR linear solver with the BBD preconditioner. + - function names changed in CVBANDPRE and CVBBDPRE for uniformity. + +- Changes to user-supplied functions + - removed N (probem dimension) from argument lists. + - shortened argument lists for user dense/band/SPGMR Jacobian routines. + - in CVSPGMR, shortened argument lists for user preconditioner functions. diff --git a/odemex/Parser/CVode/cv_src/src/cvodes/cvodea.c b/odemex/Parser/CVode/cv_src/src/cvodes/cvodea.c new file mode 100644 index 0000000..46a4358 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/cvodes/cvodea.c @@ -0,0 +1,2967 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.23 $ + * $Date: 2007/11/26 16:19:59 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the CVODEA adjoint integrator. + * ----------------------------------------------------------------- + */ + +/* + * ================================================================= + * IMPORTED HEADER FILES + * ================================================================= + */ + +#include +#include + +#include "cvodes_impl.h" + +#include +#include + +/* + * ================================================================= + * MACRO DEFINITIONS + * ================================================================= + */ + +#define loop for(;;) + +/* + * ================================================================= + * CVODEA PRIVATE CONSTANTS + * ================================================================= + */ + +#define ZERO RCONST(0.0) /* real 0.0 */ +#define ONE RCONST(1.0) /* real 1.0 */ +#define TWO RCONST(2.0) /* real 2.0 */ +#define HUNDRED RCONST(100.0) /* real 100.0 */ +#define FUZZ_FACTOR RCONST(1000000.0) /* fuzz factor for IMget */ + +/* + * ================================================================= + * PRIVATE FUNCTION PROTOTYPES + * ================================================================= + */ + +static CkpntMem CVAckpntInit(CVodeMem cv_mem); +static CkpntMem CVAckpntNew(CVodeMem cv_mem); +static void CVAckpntDelete(CkpntMem *ck_memPtr); + +static void CVAbckpbDelete(CVodeBMem *cvB_memPtr); + +static int CVAdataStore(CVodeMem cv_mem, CkpntMem ck_mem); +static int CVAckpntGet(CVodeMem cv_mem, CkpntMem ck_mem); + +static int CVAfindIndex(CVodeMem cv_mem, realtype t, + long int *indx, booleantype *newpoint); + +static booleantype CVAhermiteMalloc(CVodeMem cv_mem); +static void CVAhermiteFree(CVodeMem cv_mem); +static int CVAhermiteGetY(CVodeMem cv_mem, realtype t, N_Vector y, N_Vector *yS); +static int CVAhermiteStorePnt(CVodeMem cv_mem, DtpntMem d); + +static booleantype CVApolynomialMalloc(CVodeMem cv_mem); +static void CVApolynomialFree(CVodeMem cv_mem); +static int CVApolynomialGetY(CVodeMem cv_mem, realtype t, N_Vector y, N_Vector *yS); +static int CVApolynomialStorePnt(CVodeMem cv_mem, DtpntMem d); + +/* Wrappers */ + +static int CVArhs(realtype t, N_Vector yB, + N_Vector yBdot, void *cvode_mem); + +static int CVArhsQ(realtype t, N_Vector yB, + N_Vector qBdot, void *cvode_mem); + +/* + * ================================================================= + * EXPORTED FUNCTIONS IMPLEMENTATION + * ================================================================= + */ + +/* + * CVodeAdjInit + * + * This routine initializes ASA and allocates space for the adjoint + * memory structure. + */ + +int CVodeAdjInit(void *cvode_mem, long int steps, int interp) +{ + CVadjMem ca_mem; + CVodeMem cv_mem; + long int i, ii; + + /* --------------- + * Check arguments + * --------------- */ + + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeAdjInit", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem)cvode_mem; + + if (steps <= 0) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeAdjInit", MSGCV_BAD_STEPS); + return(CV_ILL_INPUT); + } + + if ( (interp != CV_HERMITE) && (interp != CV_POLYNOMIAL) ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeAdjInit", MSGCV_BAD_INTERP); + return(CV_ILL_INPUT); + } + + /* ---------------------------- + * Allocate CVODEA memory block + * ---------------------------- */ + + ca_mem = NULL; + ca_mem = (CVadjMem) malloc(sizeof(struct CVadjMemRec)); + if (ca_mem == NULL) { + cvProcessError(cv_mem, CV_MEM_FAIL, "CVODEA", "CVodeAdjInit", MSGCV_MEM_FAIL); + return(CV_MEM_FAIL); + } + + /* Attach ca_mem to CVodeMem structure */ + + cv_mem->cv_adj_mem = ca_mem; + + /* ------------------------------ + * Initialization of check points + * ------------------------------ */ + + /* Set Check Points linked list to NULL */ + ca_mem->ck_mem = NULL; + + /* Initialize nckpnts to ZERO */ + ca_mem->ca_nckpnts = 0; + + /* No interpolation data is available */ + ca_mem->ca_ckpntData = NULL; + + /* ------------------------------------ + * Initialization of interpolation data + * ------------------------------------ */ + + /* Interpolation type */ + + ca_mem->ca_IMtype = interp; + + /* Number of steps between check points */ + + ca_mem->ca_nsteps = steps; + + /* Allocate space for the array of Data Point structures */ + + ca_mem->dt_mem = NULL; + ca_mem->dt_mem = (DtpntMem *) malloc((steps+1)*sizeof(struct DtpntMemRec *)); + if (ca_mem->dt_mem == NULL) { + free(ca_mem); ca_mem = NULL; + cvProcessError(cv_mem, CV_MEM_FAIL, "CVODEA", "CVodeAdjInit", MSGCV_MEM_FAIL); + return(CV_MEM_FAIL); + } + + for (i=0; i<=steps; i++) { + ca_mem->dt_mem[i] = NULL; + ca_mem->dt_mem[i] = (DtpntMem) malloc(sizeof(struct DtpntMemRec)); + if (ca_mem->dt_mem[i] == NULL) { + for(ii=0; iidt_mem[ii]); ca_mem->dt_mem[ii] = NULL;} + free(ca_mem->dt_mem); ca_mem->dt_mem = NULL; + free(ca_mem); ca_mem = NULL; + cvProcessError(cv_mem, CV_MEM_FAIL, "CVODEA", "CVodeAdjInit", MSGCV_MEM_FAIL); + return(CV_MEM_FAIL); + } + } + + /* Attach functions for the appropriate interpolation module */ + + switch(interp) { + + case CV_HERMITE: + + ca_mem->ca_IMmalloc = CVAhermiteMalloc; + ca_mem->ca_IMfree = CVAhermiteFree; + ca_mem->ca_IMget = CVAhermiteGetY; + ca_mem->ca_IMstore = CVAhermiteStorePnt; + + break; + + case CV_POLYNOMIAL: + + ca_mem->ca_IMmalloc = CVApolynomialMalloc; + ca_mem->ca_IMfree = CVApolynomialFree; + ca_mem->ca_IMget = CVApolynomialGetY; + ca_mem->ca_IMstore = CVApolynomialStorePnt; + + break; + + } + + /* The interpolation module has not been initialized yet */ + + ca_mem->ca_IMmallocDone = FALSE; + + /* By default we will store but not interpolate sensitivities + * - IMstoreSensi will be set in CVodeF to FALSE if FSA is not enabled + * or if the user can force this through CVodeSetAdjNoSensi + * - IMinterpSensi will be set in CVodeB to TRUE if IMstoreSensi is + * TRUE and if at least one backward problem requires sensitivities */ + + ca_mem->ca_IMstoreSensi = TRUE; + ca_mem->ca_IMinterpSensi = FALSE; + + /* ------------------------------------ + * Initialize list of backward problems + * ------------------------------------ */ + + ca_mem->cvB_mem = NULL; + ca_mem->ca_bckpbCrt = NULL; + ca_mem->ca_nbckpbs = 0; + + /* -------------------------------- + * CVodeF and CVodeB not called yet + * -------------------------------- */ + + ca_mem->ca_firstCVodeFcall = TRUE; + ca_mem->ca_tstopCVodeFcall = FALSE; + + ca_mem->ca_firstCVodeBcall = TRUE; + + /* --------------------------------------------- + * ASA initialized and allocated + * --------------------------------------------- */ + + cv_mem->cv_adj = TRUE; + cv_mem->cv_adjMallocDone = TRUE; + + return(CV_SUCCESS); +} + +/* CVodeAdjReInit + * + * This routine reinitializes the CVODEA memory structure assuming that the + * the number of steps between check points and the type of interpolation + * remain unchanged. + * The list of check points (and associated memory) is deleted. + * The list of backward problems is kept (however, new backward problems can + * be added to this list by calling CVodeCreateB). + * The CVODES memory for the forward and backward problems can be reinitialized + * separately by calling CVodeReInit and CVodeReInitB, respectively. + * NOTE: if a completely new list of backward problems is also needed, then + * simply free the adjoint memory (by calling CVodeAdjFree) and reinitialize + * ASA with CVodeAdjInit. + */ + +int CVodeAdjReInit(void *cvode_mem) +{ + CVadjMem ca_mem; + CVodeMem cv_mem; + + /* Check cvode_mem */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeAdjReInit", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeAdjReInit", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + + ca_mem = cv_mem->cv_adj_mem; + + /* Free current list of Check Points */ + + while (ca_mem->ck_mem != NULL) CVAckpntDelete(&(ca_mem->ck_mem)); + + /* Initialization of check points */ + + ca_mem->ck_mem = NULL; + ca_mem->ca_nckpnts = 0; + ca_mem->ca_ckpntData = NULL; + + /* CVodeF and CVodeB not called yet */ + + ca_mem->ca_firstCVodeFcall = TRUE; + ca_mem->ca_tstopCVodeFcall = FALSE; + ca_mem->ca_firstCVodeBcall = TRUE; + + return(CV_SUCCESS); +} + +/* + * CVodeAdjFree + * + * This routine frees the memory allocated by CVodeAdjInit. + */ + +void CVodeAdjFree(void *cvode_mem) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + long int i; + + if (cvode_mem == NULL) return; + cv_mem = (CVodeMem) cvode_mem; + + if (cv_mem->cv_adjMallocDone) { + + ca_mem = cv_mem->cv_adj_mem; + + /* Delete check points one by one */ + while (ca_mem->ck_mem != NULL) CVAckpntDelete(&(ca_mem->ck_mem)); + + /* Free vectors at all data points */ + if (ca_mem->ca_IMmallocDone) { + ca_mem->ca_IMfree(cv_mem); + } + for(i=0; i<=ca_mem->ca_nsteps; i++) { + free(ca_mem->dt_mem[i]); + ca_mem->dt_mem[i] = NULL; + } + free(ca_mem->dt_mem); + ca_mem->dt_mem = NULL; + + /* Delete backward problems one by one */ + while (ca_mem->cvB_mem != NULL) CVAbckpbDelete(&(ca_mem->cvB_mem)); + + /* Free CVODEA memory */ + free(ca_mem); + cv_mem->cv_adj_mem = NULL; + + } + +} + +/* + * ----------------------------------------------------------------- + * Readibility Constants + * ----------------------------------------------------------------- + */ + +#define tinitial (ca_mem->ca_tinitial) +#define tfinal (ca_mem->ca_tfinal) +#define nckpnts (ca_mem->ca_nckpnts) +#define nsteps (ca_mem->ca_nsteps) +#define nbckpbs (ca_mem->ca_nbckpbs) +#define ckpntData (ca_mem->ca_ckpntData) +#define np (ca_mem->ca_np) +#define ytmp (ca_mem->ca_ytmp) +#define yStmp (ca_mem->ca_yStmp) +#define Y (ca_mem->ca_Y) +#define YS (ca_mem->ca_YS) +#define T (ca_mem->ca_T) + +#define IMmalloc (ca_mem->ca_IMmalloc) +#define IMfree (ca_mem->ca_IMfree) +#define IMget (ca_mem->ca_IMget) +#define IMstore (ca_mem->ca_IMstore) +#define IMmallocDone (ca_mem->ca_IMmallocDone) +#define IMstoreSensi (ca_mem->ca_IMstoreSensi) +#define IMinterpSensi (ca_mem->ca_IMinterpSensi) +#define IMnewData (ca_mem->ca_IMnewData) + +#define uround (cv_mem->cv_uround) +#define zn (cv_mem->cv_zn) +#define nst (cv_mem->cv_nst) +#define q (cv_mem->cv_q) +#define qu (cv_mem->cv_qu) +#define qprime (cv_mem->cv_qprime) +#define qwait (cv_mem->cv_qwait) +#define L (cv_mem->cv_L) +#define gammap (cv_mem->cv_gammap) +#define h (cv_mem->cv_h) +#define hprime (cv_mem->cv_hprime) +#define hscale (cv_mem->cv_hscale) +#define eta (cv_mem->cv_eta) +#define etamax (cv_mem->cv_etamax) +#define tn (cv_mem->cv_tn) +#define tretlast (cv_mem->cv_tretlast) +#define tau (cv_mem->cv_tau) +#define tq (cv_mem->cv_tq) +#define l (cv_mem->cv_l) +#define saved_tq5 (cv_mem->cv_saved_tq5) +#define forceSetup (cv_mem->cv_forceSetup) +#define f (cv_mem->cv_f) +#define lmm (cv_mem->cv_lmm) +#define iter (cv_mem->cv_iter) +#define reltol (cv_mem->cv_reltol) +#define user_data (cv_mem->cv_user_data) +#define errfp (cv_mem->cv_errfp) +#define h0u (cv_mem->cv_h0u) +#define tempv (cv_mem->cv_tempv) + +#define quadr (cv_mem->cv_quadr) +#define errconQ (cv_mem->cv_errconQ) +#define znQ (cv_mem->cv_znQ) +#define tempvQ (cv_mem->cv_tempvQ) + +#define sensi (cv_mem->cv_sensi) +#define Ns (cv_mem->cv_Ns) +#define errconS (cv_mem->cv_errconS) +#define znS (cv_mem->cv_znS) + +#define quadr_sensi (cv_mem->cv_quadr_sensi) +#define errconQS (cv_mem->cv_errconQS) +#define znQS (cv_mem->cv_znQS) + +#define t0_ (ck_mem->ck_t0) +#define t1_ (ck_mem->ck_t1) +#define zn_ (ck_mem->ck_zn) +#define znQ_ (ck_mem->ck_znQ) +#define znS_ (ck_mem->ck_znS) +#define znQS_ (ck_mem->ck_znQS) +#define quadr_ (ck_mem->ck_quadr) +#define sensi_ (ck_mem->ck_sensi) +#define quadr_sensi_ (ck_mem->ck_quadr_sensi) +#define Ns_ (ck_mem->ck_Ns) +#define zqm_ (ck_mem->ck_zqm) +#define nst_ (ck_mem->ck_nst) +#define tretlast_ (ck_mem->ck_tretlast) +#define q_ (ck_mem->ck_q) +#define qprime_ (ck_mem->ck_qprime) +#define qwait_ (ck_mem->ck_qwait) +#define L_ (ck_mem->ck_L) +#define gammap_ (ck_mem->ck_gammap) +#define h_ (ck_mem->ck_h) +#define hprime_ (ck_mem->ck_hprime) +#define hscale_ (ck_mem->ck_hscale) +#define eta_ (ck_mem->ck_eta) +#define etamax_ (ck_mem->ck_etamax) +#define tau_ (ck_mem->ck_tau) +#define tq_ (ck_mem->ck_tq) +#define l_ (ck_mem->ck_l) +#define saved_tq5_ (ck_mem->ck_saved_tq5) +#define next_ (ck_mem->ck_next) + + +/* + * CVodeF + * + * This routine integrates to tout and returns solution into yout. + * In the same time, it stores check point data every 'steps' steps. + * + * CVodeF can be called repeatedly by the user. + * + * ncheckPtr points to the number of check points stored so far. + */ + +int CVodeF(void *cvode_mem, realtype tout, N_Vector yout, + realtype *tret, int itask, int *ncheckPtr) +{ + CVadjMem ca_mem; + CVodeMem cv_mem; + CkpntMem tmp; + DtpntMem *dt_mem; + int flag, i; + booleantype iret, allocOK; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeF", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeF", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + + ca_mem = cv_mem->cv_adj_mem; + + /* Check for yout != NULL */ + if (yout == NULL) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeF", MSGCV_YOUT_NULL); + return(CV_ILL_INPUT); + } + + /* Check for tret != NULL */ + if (tret == NULL) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeF", MSGCV_TRET_NULL); + return(CV_ILL_INPUT); + } + + /* Check for valid itask */ + if ( (itask != CV_NORMAL) && (itask != CV_ONE_STEP) ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeF", MSGCV_BAD_ITASK); + return(CV_ILL_INPUT); + } + + /* All error checking done */ + + dt_mem = ca_mem->dt_mem; + + /* If tstop is enabled, store some info */ + if (cv_mem->cv_tstopset) { + ca_mem->ca_tstopCVodeFcall = TRUE; + ca_mem->ca_tstopCVodeF = cv_mem->cv_tstop; + } + + /* We will call CVode in CV_ONE_STEP mode, regardless + * of what itask is, so flag if we need to return */ + if (itask == CV_ONE_STEP) iret = TRUE; + else iret = FALSE; + + /* On the first step: + * - set tinitial + * - initialize list of check points + * - if needed, initialize the interpolation module + * - load dt_mem[0] + * On subsequent steps, test if taking a new step is necessary. + */ + if ( ca_mem->ca_firstCVodeFcall ) { + + tinitial = tn; + + ca_mem->ck_mem = CVAckpntInit(cv_mem); + if (ca_mem->ck_mem == NULL) { + cvProcessError(cv_mem, CV_MEM_FAIL, "CVODEA", "CVodeF", MSGCV_MEM_FAIL); + return(CV_MEM_FAIL); + } + + if ( !IMmallocDone ) { + + /* Do we need to store sensitivities? */ + if (!sensi) IMstoreSensi = FALSE; + + /* Allocate space for interpolation data */ + allocOK = IMmalloc(cv_mem); + if (!allocOK) { + cvProcessError(cv_mem, CV_MEM_FAIL, "CVODEA", "CVodeF", MSGCV_MEM_FAIL); + return(CV_MEM_FAIL); + } + + /* Rename zn and, if needed, znS for use in interpolation */ + for (i=0;it = ca_mem->ck_mem->ck_t0; + IMstore(cv_mem, dt_mem[0]); + + ca_mem->ca_firstCVodeFcall = FALSE; + + } else if ( (tn - tout)*h >= ZERO ) { + + /* If tout was passed, return interpolated solution. + No changes to ck_mem or dt_mem are needed. */ + *tret = tout; + flag = CVodeGetDky(cv_mem, tout, 0, yout); + *ncheckPtr = nckpnts; + IMnewData = TRUE; + ckpntData = ca_mem->ck_mem; + np = nst % nsteps + 1; + + return(flag); + + } + + /* Integrate to tout (in CV_ONE_STEP mode) while loading check points */ + loop { + + /* Perform one step of the integration */ + + flag = CVode(cv_mem, tout, yout, tret, CV_ONE_STEP); + if (flag < 0) break; + + /* Test if a new check point is needed */ + + if ( nst % nsteps == 0 ) { + + ca_mem->ck_mem->ck_t1 = *tret; + + /* Create a new check point, load it, and append it to the list */ + tmp = CVAckpntNew(cv_mem); + if (tmp == NULL) { + cvProcessError(cv_mem, CV_MEM_FAIL, "CVODEA", "CVodeF", MSGCV_MEM_FAIL); + flag = CV_MEM_FAIL; + break; + } + tmp->ck_next = ca_mem->ck_mem; + ca_mem->ck_mem = tmp; + nckpnts++; + forceSetup = TRUE; + + /* Reset i=0 and load dt_mem[0] */ + dt_mem[0]->t = ca_mem->ck_mem->ck_t0; + IMstore(cv_mem, dt_mem[0]); + + } else { + + /* Load next point in dt_mem */ + dt_mem[nst%nsteps]->t = *tret; + IMstore(cv_mem, dt_mem[nst%nsteps]); + + } + + /* Set t1 field of the current ckeck point structure + for the case in which there will be no future + check points */ + ca_mem->ck_mem->ck_t1 = *tret; + + /* tfinal is now set to *tret */ + tfinal = *tret; + + /* Return if in CV_ONE_STEP mode */ + if (iret) break; + + /* Return if tout reached */ + if ( (*tret - tout)*h >= ZERO ) { + *tret = tout; + CVodeGetDky(cv_mem, tout, 0, yout); + /* Reset tretlast in cv_mem so that CVodeGetQuad and CVodeGetSens + * evaluate quadratures and/or sensitivities at the proper time */ + cv_mem->cv_tretlast = tout; + break; + } + + } /* end of loop() */ + + /* Get ncheck from ca_mem */ + *ncheckPtr = nckpnts; + + /* Data is available for the last interval */ + IMnewData = TRUE; + ckpntData = ca_mem->ck_mem; + np = nst % nsteps + 1; + + return(flag); +} + + + +/* + * ================================================================= + * FUNCTIONS FOR BACKWARD PROBLEMS + * ================================================================= + */ + + +int CVodeCreateB(void *cvode_mem, int lmmB, int iterB, int *which) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem new_cvB_mem; + void *cvodeB_mem; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeCreateB", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeCreateB", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Allocate space for new CVodeBMem object */ + + new_cvB_mem = NULL; + new_cvB_mem = (CVodeBMem) malloc(sizeof(struct CVodeBMemRec)); + if (new_cvB_mem == NULL) { + cvProcessError(cv_mem, CV_MEM_FAIL, "CVODEA", "CVodeCreateB", MSGCV_MEM_FAIL); + return(CV_MEM_FAIL); + } + + /* Create and set a new CVODES object for the backward problem */ + + cvodeB_mem = CVodeCreate(lmmB, iterB); + if (cvodeB_mem == NULL) { + cvProcessError(cv_mem, CV_MEM_FAIL, "CVODEA", "CVodeCreateB", MSGCV_MEM_FAIL); + return(CV_MEM_FAIL); + } + + CVodeSetUserData(cvodeB_mem, cvode_mem); + + CVodeSetMaxHnilWarns(cvodeB_mem, -1); + + CVodeSetErrHandlerFn(cvodeB_mem, cv_mem->cv_ehfun, cv_mem->cv_eh_data); + CVodeSetErrFile(cvodeB_mem, cv_mem->cv_errfp); + + /* Set/initialize fields in the new CVodeBMem object, new_cvB_mem */ + + new_cvB_mem->cv_index = nbckpbs; + + new_cvB_mem->cv_mem = (CVodeMem) cvodeB_mem; + + new_cvB_mem->cv_f = NULL; + new_cvB_mem->cv_fs = NULL; + + new_cvB_mem->cv_fQ = NULL; + new_cvB_mem->cv_fQs = NULL; + + new_cvB_mem->cv_user_data = NULL; + + new_cvB_mem->cv_lmem = NULL; + new_cvB_mem->cv_lfree = NULL; + new_cvB_mem->cv_pmem = NULL; + new_cvB_mem->cv_pfree = NULL; + + new_cvB_mem->cv_y = NULL; + + new_cvB_mem->cv_f_withSensi = FALSE; + new_cvB_mem->cv_fQ_withSensi = FALSE; + + /* Attach the new object to the linked list cvB_mem */ + + new_cvB_mem->cv_next = ca_mem->cvB_mem; + ca_mem->cvB_mem = new_cvB_mem; + + /* Return the index of the newly created CVodeBMem object. + * This must be passed to CVodeInitB and to other ***B + * functions to set optional inputs for this backward problem */ + + *which = nbckpbs; + + nbckpbs++; + + return(CV_SUCCESS); +} + +int CVodeInitB(void *cvode_mem, int which, + CVRhsFnB fB, + realtype tB0, N_Vector yB0) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeInitB", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeInitB", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check the value of which */ + + if ( which >= nbckpbs ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeInitB", MSGCV_BAD_WHICH); + return(CV_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + /* Allocate and set the CVODES object */ + + flag = CVodeInit(cvodeB_mem, CVArhs, tB0, yB0); + + if (flag != CV_SUCCESS) return(flag); + + /* Copy fB function in cvB_mem */ + + cvB_mem->cv_f_withSensi = FALSE; + cvB_mem->cv_f = fB; + + /* Allocate space and initialize the y Nvector in cvB_mem */ + + cvB_mem->cv_t0 = tB0; + cvB_mem->cv_y = N_VClone(yB0); + N_VScale(ONE, yB0, cvB_mem->cv_y); + + return(CV_SUCCESS); +} + +int CVodeInitBS(void *cvode_mem, int which, + CVRhsFnBS fBs, + realtype tB0, N_Vector yB0) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeInitBS", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeInitBS", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check the value of which */ + + if ( which >= nbckpbs ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeInitBS", MSGCV_BAD_WHICH); + return(CV_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + /* Allocate and set the CVODES object */ + + flag = CVodeInit(cvodeB_mem, CVArhs, tB0, yB0); + + if (flag != CV_SUCCESS) return(flag); + + /* Copy fBs function in cvB_mem */ + + cvB_mem->cv_f_withSensi = TRUE; + cvB_mem->cv_fs = fBs; + + /* Allocate space and initialize the y Nvector in cvB_mem */ + + cvB_mem->cv_t0 = tB0; + cvB_mem->cv_y = N_VClone(yB0); + N_VScale(ONE, yB0, cvB_mem->cv_y); + + return(CV_SUCCESS); +} + + +int CVodeReInitB(void *cvode_mem, int which, + realtype tB0, N_Vector yB0) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeReInitB", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeReInitB", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check the value of which */ + if ( which >= nbckpbs ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeReInitB", MSGCV_BAD_WHICH); + return(CV_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + /* Reinitialize CVODES object */ + + flag = CVodeReInit(cvodeB_mem, tB0, yB0); + + return(flag); +} + + +int CVodeSStolerancesB(void *cvode_mem, int which, realtype reltolB, realtype abstolB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeSStolerancesB", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeSStolerancesB", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check the value of which */ + + if ( which >= nbckpbs ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSStolerancesB", MSGCV_BAD_WHICH); + return(CV_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + /* Set tolerances */ + + flag = CVodeSStolerances(cvodeB_mem, reltolB, abstolB); + + return(flag); +} + + +int CVodeSVtolerancesB(void *cvode_mem, int which, realtype reltolB, N_Vector abstolB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeSVtolerancesB", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeSVtolerancesB", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check the value of which */ + + if ( which >= nbckpbs ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSVtolerancesB", MSGCV_BAD_WHICH); + return(CV_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + /* Set tolerances */ + + flag = CVodeSVtolerances(cvodeB_mem, reltolB, abstolB); + + return(flag); +} + + +int CVodeQuadInitB(void *cvode_mem, int which, + CVQuadRhsFnB fQB, N_Vector yQB0) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeQuadInitB", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeQuadInitB", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= nbckpbs ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeQuadInitB", MSGCV_BAD_WHICH); + return(CV_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + flag = CVodeQuadInit(cvodeB_mem, CVArhsQ, yQB0); + if (flag != CV_SUCCESS) return(flag); + + cvB_mem->cv_fQ_withSensi = FALSE; + cvB_mem->cv_fQ = fQB; + + return(CV_SUCCESS); +} + +int CVodeQuadInitBS(void *cvode_mem, int which, + CVQuadRhsFnBS fQBs, N_Vector yQB0) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeQuadInitBS", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeQuadInitBS", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= nbckpbs ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeQuadInitBS", MSGCV_BAD_WHICH); + return(CV_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + flag = CVodeQuadInit(cvodeB_mem, CVArhsQ, yQB0); + if (flag != CV_SUCCESS) return(flag); + + cvB_mem->cv_fQ_withSensi = TRUE; + cvB_mem->cv_fQs = fQBs; + + return(CV_SUCCESS); +} + +int CVodeQuadReInitB(void *cvode_mem, int which, N_Vector yQB0) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeQuadReInitB", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeQuadReInitB", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check the value of which */ + if ( which >= nbckpbs ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeQuadReInitB", MSGCV_BAD_WHICH); + return(CV_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + flag = CVodeQuadReInit(cvodeB_mem, yQB0); + if (flag != CV_SUCCESS) return(flag); + + return(CV_SUCCESS); +} + +int CVodeQuadSStolerancesB(void *cvode_mem, int which, realtype reltolQB, realtype abstolQB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeQuadSStolerancesB", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeQuadSStolerancesB", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= nbckpbs ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeQuadSStolerancesB", MSGCV_BAD_WHICH); + return(CV_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + flag = CVodeQuadSStolerances(cvodeB_mem, reltolQB, abstolQB); + + return(flag); +} + +int CVodeQuadSVtolerancesB(void *cvode_mem, int which, realtype reltolQB, N_Vector abstolQB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeQuadSStolerancesB", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeQuadSStolerancesB", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= nbckpbs ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeQuadSStolerancesB", MSGCV_BAD_WHICH); + return(CV_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + flag = CVodeQuadSVtolerances(cvodeB_mem, reltolQB, abstolQB); + + return(flag); +} + +/* + * CVodeB + * + * This routine performs the backward integration towards tBout + * of all backward problems that were defined. + * When necessary, it performs a forward integration between two + * consecutive check points to update interpolation data. + * itask can be CV_NORMAL or CV_ONE_STEP only. + * + * On a successful return, CVodeB returns either CV_SUCCESS + * (in ONE_STEP mode or if tBout was reached in NORMAL mode) + * unless the return time happens to be a checkpoint, in which + * case it returns CV_TSTOP_RETURN) + * + * NOTE that CVodeB DOES NOT return the solution for the backward + * problem(s). Use CVodeGetB to extract the solution at tBret + * for any given backward problem. + */ + +int CVodeB(void *cvode_mem, realtype tBout, int itaskB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem, tmp_cvB_mem; + CkpntMem ck_mem; + int sign, flag; + realtype tBret, tBn, hB, troundoff; + booleantype gotCheckpoint, isActive, reachedTBout; + + /* Check if cvode_mem exists */ + + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeB", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeB", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check if any backward problem has been defined */ + + if ( nbckpbs == 0 ) { + cvProcessError(cv_mem, CV_NO_BCK, "CVODEA", "CVodeB", MSGCV_NO_BCK); + return(CV_NO_BCK); + } + cvB_mem = ca_mem->cvB_mem; + + /* Check whether CVodeF has been called */ + + if ( ca_mem->ca_firstCVodeFcall ) { + cvProcessError(cv_mem, CV_NO_FWD, "CVODEA", "CVodeB", MSGCV_NO_FWD); + return(CV_NO_FWD); + } + sign = (tfinal - tinitial > ZERO) ? 1 : -1; + + /* If this is the first call, loop over all backward problems and + * - check that tB0 is valid + * - check whether we need to interpolate forward sensitivities + */ + + if ( ca_mem->ca_firstCVodeBcall ) { + + tmp_cvB_mem = cvB_mem; + + while(tmp_cvB_mem != NULL) { + + tBn = tmp_cvB_mem->cv_mem->cv_tn; + if ( (sign*(tBn-tinitial) < ZERO) || (sign*(tfinal-tBn) < ZERO) ) { + cvProcessError(cv_mem, CV_BAD_TB0, "CVODEA", "CVodeB", MSGCV_BAD_TB0, tmp_cvB_mem->cv_index); + return(CV_BAD_TB0); + } + + if ( tmp_cvB_mem->cv_f_withSensi || tmp_cvB_mem->cv_fQ_withSensi ) IMinterpSensi = TRUE; + + tmp_cvB_mem = tmp_cvB_mem->cv_next; + + } + + if ( IMinterpSensi && !IMstoreSensi) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeB", MSGCV_BAD_SENSI); + return(CV_ILL_INPUT); + } + + ca_mem->ca_firstCVodeBcall = FALSE; + } + + /* Check if itaskB is legal */ + + if ( (itaskB != CV_NORMAL) && (itaskB != CV_ONE_STEP) ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeB", MSGCV_BAD_ITASKB); + return(CV_ILL_INPUT); + } + + /* Check if tBout is legal */ + + if ( (sign*(tBout-tinitial) < ZERO) || (sign*(tfinal-tBout) < ZERO) ) { + if ( ABS(tBout-tinitial) < HUNDRED*uround ) { + tBout = tinitial; + } else { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeB", MSGCV_BAD_TBOUT); + return(CV_ILL_INPUT); + } + } + + /* Loop through the check points and stop as soon as a backward + * problem has its tn value larger than the current check point's + * t0_ value (taking into account the direction of integration) */ + + ck_mem = ca_mem->ck_mem; + + gotCheckpoint = FALSE; + + loop { + + tmp_cvB_mem = cvB_mem; + while(tmp_cvB_mem != NULL) { + tBn = tmp_cvB_mem->cv_mem->cv_tn; + hB = tmp_cvB_mem->cv_mem->cv_hu; + troundoff = HUNDRED*uround*(ABS(tBn) + ABS(hB)); + if ( sign * (tBn-t0_) > troundoff ) { + gotCheckpoint = TRUE; + break; + } + tmp_cvB_mem = tmp_cvB_mem->cv_next; + } + + if (gotCheckpoint) break; + + if (next_ == NULL) break; + + ck_mem = next_; + } + + /* Loop while propagating backward problems */ + + loop { + + /* Store interpolation data if not available. + This is the 2nd forward integration pass */ + + if (ck_mem != ckpntData) { + + flag = CVAdataStore(cv_mem, ck_mem); + if (flag != CV_SUCCESS) break; + + } + + /* Loop through all backward problems and, if needed, + * propagate their solution towards tBout */ + + tmp_cvB_mem = cvB_mem; + while (tmp_cvB_mem != NULL) { + + /* Decide if current backward problem is "active" */ + + isActive = TRUE; + + tBn = tmp_cvB_mem->cv_mem->cv_tn; + hB = tmp_cvB_mem->cv_mem->cv_hu; + troundoff = HUNDRED*uround*(ABS(tBn) + ABS(hB)); + + if ( sign * (tBn - t0_) < troundoff ) isActive = FALSE; + if ( sign * (tBn - tBout) < troundoff ) isActive = FALSE; + + if ( isActive ) { + + /* Store the address of current backward problem memory + * in ca_mem to be used in the wrapper functions */ + ca_mem->ca_bckpbCrt = tmp_cvB_mem; + + /* Integrate current backward problem */ + CVodeSetStopTime(tmp_cvB_mem->cv_mem, t0_); + flag = CVode(tmp_cvB_mem->cv_mem, tBout, tmp_cvB_mem->cv_y, &tBret, itaskB); + + /* If an error occured, exit while loop */ + if (flag < 0) break; + + /* Set the time at which we will report solution and/or quadratures */ + tmp_cvB_mem->cv_tout = tBret; + + } else { + + flag = CV_SUCCESS; + tmp_cvB_mem->cv_tout = tBn; + + } + + /* Move to next backward problem */ + + tmp_cvB_mem = tmp_cvB_mem->cv_next; + } + + /* If an error occured, return now */ + + if (flag <0) { + cvProcessError(cv_mem, flag, "CVODEA", "CVodeB", MSGCV_BACK_ERROR, tmp_cvB_mem->cv_index); + return(flag); + } + + /* If in CV_ONE_STEP mode, return now (flag=CV_SUCCESS or flag=CV_TSTOP_RETURN) */ + + if (itaskB == CV_ONE_STEP) break; + + /* If all backward problems have succesfully reached tBout, return now */ + + reachedTBout = TRUE; + + tmp_cvB_mem = cvB_mem; + while(tmp_cvB_mem != NULL) { + if ( sign*(tmp_cvB_mem->cv_tout - tBout) > 0 ) { + reachedTBout = FALSE; + break; + } + tmp_cvB_mem = tmp_cvB_mem->cv_next; + } + + if ( reachedTBout ) break; + + /* Move check point in linked list to next one */ + + ck_mem = next_; + + } + + return(flag); +} + + + +int CVodeGetB(void *cvode_mem, int which, realtype *tret, N_Vector yB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeGetB", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeGetB", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + + ca_mem = cv_mem->cv_adj_mem; + + /* Check the value of which */ + if ( which >= nbckpbs ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeGetB", MSGCV_BAD_WHICH); + return(CV_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + N_VScale(ONE, cvB_mem->cv_y, yB); + *tret = cvB_mem->cv_tout; + + return(CV_SUCCESS); +} + + +/* + * CVodeGetQuadB + */ + +int CVodeGetQuadB(void *cvode_mem, int which, realtype *tret, N_Vector qB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + long int nstB; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeGetQuadB", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeGetQuadB", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + + ca_mem = cv_mem->cv_adj_mem; + + /* Check the value of which */ + if ( which >= nbckpbs ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeGetQuadB", MSGCV_BAD_WHICH); + return(CV_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + /* If the integration for this backward problem has not started yet, + * simply return the current value of qB (i.e. the final conditions) */ + + flag = CVodeGetNumSteps(cvodeB_mem, &nstB); + + if (nstB == 0) { + N_VScale(ONE, cvB_mem->cv_mem->cv_znQ[0], qB); + *tret = cvB_mem->cv_tout; + } else { + flag = CVodeGetQuad(cvodeB_mem, tret, qB); + } + + return(flag); +} + + +/* + * ================================================================= + * PRIVATE FUNCTIONS FOR CHECK POINTS + * ================================================================= + */ + +/* + * CVAckpntInit + * + * This routine initializes the check point linked list with + * information from the initial time. + */ + +static CkpntMem CVAckpntInit(CVodeMem cv_mem) +{ + CkpntMem ck_mem; + int is; + + /* Allocate space for ckdata */ + ck_mem = NULL; + ck_mem = (CkpntMem) malloc(sizeof(struct CkpntMemRec)); + if (ck_mem == NULL) return(NULL); + + zn_[0] = N_VClone(tempv); + if (zn_[0] == NULL) { + free(ck_mem); ck_mem = NULL; + return(NULL); + } + + zn_[1] = N_VClone(tempv); + if (zn_[1] == NULL) { + N_VDestroy(zn_[0]); + free(ck_mem); ck_mem = NULL; + return(NULL); + } + + /* zn_[qmax] was not allocated */ + zqm_ = 0; + + /* Load ckdata from cv_mem */ + N_VScale(ONE, zn[0], zn_[0]); + t0_ = tn; + nst_ = 0; + q_ = 1; + h_ = 0.0; + + /* Do we need to carry quadratures */ + quadr_ = quadr && errconQ; + + if (quadr_) { + + znQ_[0] = N_VClone(tempvQ); + if (znQ_[0] == NULL) { + N_VDestroy(zn_[0]); + N_VDestroy(zn_[1]); + free(ck_mem); ck_mem = NULL; + return(NULL); + } + + N_VScale(ONE, znQ[0], znQ_[0]); + + } + + /* Do we need to carry sensitivities? */ + sensi_ = sensi; + + if (sensi_) { + + Ns_ = Ns; + + znS_[0] = N_VCloneVectorArray(Ns, tempv); + if (znS_[0] == NULL) { + N_VDestroy(zn_[0]); + N_VDestroy(zn_[1]); + if (quadr_) N_VDestroy(znQ_[0]); + free(ck_mem); ck_mem = NULL; + return(NULL); + } + + for (is=0; isck_next = NULL; + + /* Test if we need to allocate space for the last zn. + * NOTE: zn(qmax) may be needed for a hot restart, if an order + * increase is deemed necessary at the first step after a check point */ + qmax = cv_mem->cv_qmax; + zqm_ = (q < qmax) ? qmax : 0; + + for (j=0; j<=q; j++) { + zn_[j] = N_VClone(tempv); + if (zn_[j] == NULL) { + for (jj=0; jjck_next; + + /* free N_Vectors in tmp */ + for (j=0;j<=tmp->ck_q;j++) N_VDestroy(tmp->ck_zn[j]); + if (tmp->ck_zqm != 0) N_VDestroy(tmp->ck_zn[tmp->ck_zqm]); + + /* free N_Vectors for quadratures in tmp + * Note that at the check point at t_initial, only znQ_[0] + * was allocated */ + if (tmp->ck_quadr) { + + if (tmp->ck_next != NULL) { + for (j=0;j<=tmp->ck_q;j++) N_VDestroy(tmp->ck_znQ[j]); + if (tmp->ck_zqm != 0) N_VDestroy(tmp->ck_znQ[tmp->ck_zqm]); + } else { + N_VDestroy(tmp->ck_znQ[0]); + } + + } + + /* free N_Vectors for sensitivities in tmp + * Note that at the check point at t_initial, only znS_[0] + * was allocated */ + if (tmp->ck_sensi) { + + if (tmp->ck_next != NULL) { + for (j=0;j<=tmp->ck_q;j++) N_VDestroyVectorArray(tmp->ck_znS[j], tmp->ck_Ns); + if (tmp->ck_zqm != 0) N_VDestroyVectorArray(tmp->ck_znS[tmp->ck_zqm], tmp->ck_Ns); + } else { + N_VDestroyVectorArray(tmp->ck_znS[0], tmp->ck_Ns); + } + + } + + /* free N_Vectors for quadrature sensitivities in tmp + * Note that at the check point at t_initial, only znQS_[0] + * was allocated */ + if (tmp->ck_quadr_sensi) { + + if (tmp->ck_next != NULL) { + for (j=0;j<=tmp->ck_q;j++) N_VDestroyVectorArray(tmp->ck_znQS[j], tmp->ck_Ns); + if (tmp->ck_zqm != 0) N_VDestroyVectorArray(tmp->ck_znQS[tmp->ck_zqm], tmp->ck_Ns); + } else { + N_VDestroyVectorArray(tmp->ck_znQS[0], tmp->ck_Ns); + } + + } + + free(tmp); tmp = NULL; + +} + +/* + * ================================================================= + * PRIVATE FUNCTIONS FOR BACKWARD PROBLEMS + * ================================================================= + */ + +static void CVAbckpbDelete(CVodeBMem *cvB_memPtr) +{ + CVodeBMem tmp; + void *cvode_mem; + + if (*cvB_memPtr != NULL) { + + /* Save head of the list */ + tmp = *cvB_memPtr; + + /* Move head of the list */ + *cvB_memPtr = (*cvB_memPtr)->cv_next; + + /* Free CVODES memory in tmp */ + cvode_mem = (void *)(tmp->cv_mem); + CVodeFree(&cvode_mem); + + /* Free linear solver memory */ + if (tmp->cv_lfree != NULL) tmp->cv_lfree(tmp); + + /* Free preconditioner memory */ + if (tmp->cv_pfree != NULL) tmp->cv_pfree(tmp); + + /* Free workspace Nvector */ + N_VDestroy(tmp->cv_y); + + free(tmp); tmp = NULL; + + } + +} + +/* + * ================================================================= + * PRIVATE FUNCTIONS FOR INTERPOLATION + * ================================================================= + */ + +/* + * CVAdataStore + * + * This routine integrates the forward model starting at the check + * point ck_mem and stores y and yprime at all intermediate steps. + * + * Return values: + * CV_SUCCESS + * CV_REIFWD_FAIL + * CV_FWD_FAIL + */ + +static int CVAdataStore(CVodeMem cv_mem, CkpntMem ck_mem) +{ + CVadjMem ca_mem; + DtpntMem *dt_mem; + realtype t; + long int i; + int flag; + + ca_mem = cv_mem->cv_adj_mem; + dt_mem = ca_mem->dt_mem; + + /* Initialize cv_mem with data from ck_mem */ + flag = CVAckpntGet(cv_mem, ck_mem); + if (flag != CV_SUCCESS) + return(CV_REIFWD_FAIL); + + /* Set first structure in dt_mem[0] */ + dt_mem[0]->t = t0_; + IMstore(cv_mem, dt_mem[0]); + + /* Decide whether TSTOP must be activated */ + if (ca_mem->ca_tstopCVodeFcall) { + CVodeSetStopTime(cv_mem, ca_mem->ca_tstopCVodeF); + } + + /* Run CVode to set following structures in dt_mem[i] */ + i = 1; + do { + + flag = CVode(cv_mem, t1_, ytmp, &t, CV_ONE_STEP); + if (flag < 0) return(CV_FWD_FAIL); + + dt_mem[i]->t = t; + IMstore(cv_mem, dt_mem[i]); + i++; + + } while (tcv_ism, znS_[0]); + if (flag != CV_SUCCESS) return(flag); + } + + if (quadr_sensi_) { + flag = CVodeQuadSensReInit(cv_mem, znQS_[0]); + if (flag != CV_SUCCESS) return(flag); + } + + } else { + + qmax = cv_mem->cv_qmax; + + /* Copy parameters from check point data structure */ + + nst = nst_; + tretlast = tretlast_; + q = q_; + qprime = qprime_; + qwait = qwait_; + L = L_; + gammap = gammap_; + h = h_; + hprime = hprime_; + hscale = hscale_; + eta = eta_; + etamax = etamax_; + tn = t0_; + saved_tq5 = saved_tq5_; + + /* Copy the arrays from check point data structure */ + + for (j=0; j<=q; j++) N_VScale(ONE, zn_[j], zn[j]); + if ( q < qmax ) N_VScale(ONE, zn_[qmax], zn[qmax]); + + if (quadr_) { + for (j=0; j<=q; j++) N_VScale(ONE, znQ_[j], znQ[j]); + if ( q < qmax ) N_VScale(ONE, znQ_[qmax], znQ[qmax]); + } + + if (sensi_) { + for (is=0; iscv_adj_mem; + dt_mem = ca_mem->dt_mem; + + *newpoint = FALSE; + + /* Find the direction of integration */ + sign = (tfinal - tinitial > ZERO) ? 1 : -1; + + /* If this is the first time we use new data */ + if (IMnewData) { + ilast = np-1; + *newpoint = TRUE; + IMnewData = FALSE; + } + + /* Search for indx starting from ilast */ + to_left = ( sign*(t - dt_mem[ilast-1]->t) < ZERO); + to_right = ( sign*(t - dt_mem[ilast]->t) > ZERO); + + if ( to_left ) { + /* look for a new indx to the left */ + + *newpoint = TRUE; + + *indx = ilast; + loop { + if ( *indx == 0 ) break; + if ( sign*(t - dt_mem[*indx-1]->t) <= ZERO ) (*indx)--; + else break; + } + + if ( *indx == 0 ) + ilast = 1; + else + ilast = *indx; + + if ( *indx == 0 ) { + /* t is beyond leftmost limit. Is it too far? */ + if ( ABS(t - dt_mem[0]->t) > FUZZ_FACTOR * uround ) { + return(CV_GETY_BADT); + } + } + + } else if ( to_right ) { + /* look for a new indx to the right */ + + *newpoint = TRUE; + + *indx = ilast; + loop { + if ( sign*(t - dt_mem[*indx]->t) > ZERO) (*indx)++; + else break; + } + + ilast = *indx; + + + } else { + /* ilast is still OK */ + + *indx = ilast; + + } + + return(CV_SUCCESS); + + +} + +/* + * CVodeGetAdjY + * + * This routine returns the interpolated forward solution at time t. + * The user must allocate space for y. + */ + +int CVodeGetAdjY(void *cvode_mem, realtype t, N_Vector y) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + int flag; + + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeGetAdjY", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + ca_mem = cv_mem->cv_adj_mem; + + flag = IMget(cv_mem, t, y, NULL); + + return(flag); +} + +/* + * ----------------------------------------------------------------- + * Functions specific to cubic Hermite interpolation + * ----------------------------------------------------------------- + */ + +/* + * CVAhermiteMalloc + * + * This routine allocates memory for storing information at all + * intermediate points between two consecutive check points. + * This data is then used to interpolate the forward solution + * at any other time. + */ + +static booleantype CVAhermiteMalloc(CVodeMem cv_mem) +{ + CVadjMem ca_mem; + DtpntMem *dt_mem; + HermiteDataMem content; + long int i, ii=0; + booleantype allocOK; + + allocOK = TRUE; + + ca_mem = cv_mem->cv_adj_mem; + + /* Allocate space for the vectors ytmp and yStmp */ + + ytmp = N_VClone(tempv); + if (ytmp == NULL) { + return(FALSE); + } + + if (IMstoreSensi) { + yStmp = N_VCloneVectorArray(Ns, tempv); + if (yStmp == NULL) { + N_VDestroy(ytmp); + return(FALSE); + } + } + + /* Allocate space for the content field of the dt structures */ + + dt_mem = ca_mem->dt_mem; + + for (i=0; i<=nsteps; i++) { + + content = NULL; + content = (HermiteDataMem) malloc(sizeof(struct HermiteDataMemRec)); + if (content == NULL) { + ii = i; + allocOK = FALSE; + break; + } + + content->y = N_VClone(tempv); + if (content->y == NULL) { + free(content); content = NULL; + ii = i; + allocOK = FALSE; + break; + } + + content->yd = N_VClone(tempv); + if (content->yd == NULL) { + N_VDestroy(content->y); + free(content); content = NULL; + ii = i; + allocOK = FALSE; + break; + } + + if (IMstoreSensi) { + + content->yS = N_VCloneVectorArray(Ns, tempv); + if (content->yS == NULL) { + N_VDestroy(content->y); + N_VDestroy(content->yd); + free(content); content = NULL; + ii = i; + allocOK = FALSE; + break; + } + + content->ySd = N_VCloneVectorArray(Ns, tempv); + if (content->ySd == NULL) { + N_VDestroy(content->y); + N_VDestroy(content->yd); + N_VDestroyVectorArray(content->yS, Ns); + free(content); content = NULL; + ii = i; + allocOK = FALSE; + break; + } + + } + + dt_mem[i]->content = content; + + } + + /* If an error occurred, deallocate and return */ + + if (!allocOK) { + + N_VDestroy(ytmp); + + if (IMstoreSensi) { + N_VDestroyVectorArray(yStmp, Ns); + } + + for (i=0; icontent); + N_VDestroy(content->y); + N_VDestroy(content->yd); + if (IMstoreSensi) { + N_VDestroyVectorArray(content->yS, Ns); + N_VDestroyVectorArray(content->ySd, Ns); + } + free(dt_mem[i]->content); dt_mem[i]->content = NULL; + } + + } + + return(allocOK); +} + +/* + * CVAhermiteFree + * + * This routine frees the memory allocated for data storage. + */ + +static void CVAhermiteFree(CVodeMem cv_mem) +{ + CVadjMem ca_mem; + DtpntMem *dt_mem; + HermiteDataMem content; + long int i; + + ca_mem = cv_mem->cv_adj_mem; + + N_VDestroy(ytmp); + + if (IMstoreSensi) { + N_VDestroyVectorArray(yStmp, Ns); + } + + dt_mem = ca_mem->dt_mem; + + for (i=0; i<=nsteps; i++) { + content = (HermiteDataMem) (dt_mem[i]->content); + N_VDestroy(content->y); + N_VDestroy(content->yd); + if (IMstoreSensi) { + N_VDestroyVectorArray(content->yS, Ns); + N_VDestroyVectorArray(content->ySd, Ns); + } + free(dt_mem[i]->content); dt_mem[i]->content = NULL; + } +} + +/* + * CVAhermiteStorePnt ( -> IMstore ) + * + * This routine stores a new point (y,yd) in the structure d for use + * in the cubic Hermite interpolation. + * Note that the time is already stored. + */ + +static int CVAhermiteStorePnt(CVodeMem cv_mem, DtpntMem d) +{ + CVadjMem ca_mem; + HermiteDataMem content; + int is, retval; + + ca_mem = cv_mem->cv_adj_mem; + + content = (HermiteDataMem) d->content; + + /* Load solution */ + + N_VScale(ONE, zn[0], content->y); + + if (IMstoreSensi) { + for (is=0; isyS[is]); + } + + /* Load derivative */ + + if (nst == 0) { + + retval = f(tn, content->y, content->yd, user_data); + + if (IMstoreSensi) { + retval = cvSensRhsWrapper(cv_mem, tn, content->y, content->yd, + content->yS, content->ySd, + cv_mem->cv_tempv, cv_mem->cv_ftemp); + } + + } else { + + N_VScale(ONE/h, zn[1], content->yd); + + if (IMstoreSensi) { + for (is=0; isySd[is]); + } + + } + + return(0); +} + +/* + * CVAhermiteGetY ( -> IMget ) + * + * This routine uses cubic piece-wise Hermite interpolation for + * the forward solution vector. + * It is typically called by the wrapper routines before calling + * user provided routines (fB, djacB, bjacB, jtimesB, psolB) but + * can be directly called by the user through CVodeGetAdjY + */ + +static int CVAhermiteGetY(CVodeMem cv_mem, realtype t, + N_Vector y, N_Vector *yS) +{ + CVadjMem ca_mem; + DtpntMem *dt_mem; + HermiteDataMem content0, content1; + + realtype t0, t1, delta; + realtype factor1, factor2, factor3; + + N_Vector y0, yd0, y1, yd1; + N_Vector *yS0, *ySd0, *yS1, *ySd1; + + int flag, is, NS; + long int indx; + booleantype newpoint; + + + ca_mem = cv_mem->cv_adj_mem; + dt_mem = ca_mem->dt_mem; + + /* Local value of Ns */ + + NS = IMinterpSensi ? Ns : 0; + + /* Get the index in dt_mem */ + + flag = CVAfindIndex(cv_mem, t, &indx, &newpoint); + if (flag != CV_SUCCESS) return(flag); + + /* If we are beyond the left limit but close enough, + then return y at the left limit. */ + + if (indx == 0) { + content0 = (HermiteDataMem) (dt_mem[0]->content); + N_VScale(ONE, content0->y, y); + for (is=0; isyS[is], yS[is]); + return(CV_SUCCESS); + } + + /* Extract stuff from the appropriate data points */ + + t0 = dt_mem[indx-1]->t; + t1 = dt_mem[indx]->t; + delta = t1 - t0; + + content0 = (HermiteDataMem) (dt_mem[indx-1]->content); + y0 = content0->y; + yd0 = content0->yd; + if (IMinterpSensi) { + yS0 = content0->yS; + ySd0 = content0->ySd; + } + + if (newpoint) { + + /* Recompute Y0 and Y1 */ + + content1 = (HermiteDataMem) (dt_mem[indx]->content); + + y1 = content1->y; + yd1 = content1->yd; + + N_VLinearSum(ONE, y1, -ONE, y0, Y[0]); + N_VLinearSum(ONE, yd1, ONE, yd0, Y[1]); + N_VLinearSum(delta, Y[1], -TWO, Y[0], Y[1]); + N_VLinearSum(ONE, Y[0], -delta, yd0, Y[0]); + + + yS1 = content1->yS; + ySd1 = content1->ySd; + + for (is=0; iscv_adj_mem; + + /* Allocate space for the vectors ytmp and yStmp */ + + ytmp = N_VClone(tempv); + if (ytmp == NULL) { + return(FALSE); + } + + if (IMstoreSensi) { + yStmp = N_VCloneVectorArray(Ns, tempv); + if (yStmp == NULL) { + N_VDestroy(ytmp); + return(FALSE); + } + } + + /* Allocate space for the content field of the dt structures */ + + dt_mem = ca_mem->dt_mem; + + for (i=0; i<=nsteps; i++) { + + content = NULL; + content = (PolynomialDataMem) malloc(sizeof(struct PolynomialDataMemRec)); + if (content == NULL) { + ii = i; + allocOK = FALSE; + break; + } + + content->y = N_VClone(tempv); + if (content->y == NULL) { + free(content); content = NULL; + ii = i; + allocOK = FALSE; + break; + } + + if (IMstoreSensi) { + + content->yS = N_VCloneVectorArray(Ns, tempv); + if (content->yS == NULL) { + N_VDestroy(content->y); + free(content); content = NULL; + ii = i; + allocOK = FALSE; + break; + } + + } + + dt_mem[i]->content = content; + + } + + /* If an error occurred, deallocate and return */ + + if (!allocOK) { + + N_VDestroy(ytmp); + + if (IMstoreSensi) { + N_VDestroyVectorArray(yStmp, Ns); + } + + for (i=0; icontent); + N_VDestroy(content->y); + if (IMstoreSensi) { + N_VDestroyVectorArray(content->yS, Ns); + } + free(dt_mem[i]->content); dt_mem[i]->content = NULL; + } + + } + + return(allocOK); + +} + +/* + * CVApolynomialFree + * + * This routine frees the memeory allocated for data storage. + */ + +static void CVApolynomialFree(CVodeMem cv_mem) +{ + CVadjMem ca_mem; + DtpntMem *dt_mem; + PolynomialDataMem content; + long int i; + + ca_mem = cv_mem->cv_adj_mem; + + N_VDestroy(ytmp); + + if (IMstoreSensi) { + N_VDestroyVectorArray(yStmp, Ns); + } + + dt_mem = ca_mem->dt_mem; + + for (i=0; i<=nsteps; i++) { + content = (PolynomialDataMem) (dt_mem[i]->content); + N_VDestroy(content->y); + if (IMstoreSensi) { + N_VDestroyVectorArray(content->yS, Ns); + } + free(dt_mem[i]->content); dt_mem[i]->content = NULL; + } +} + +/* + * CVApolynomialStorePnt ( -> IMstore ) + * + * This routine stores a new point y in the structure d for use + * in the Polynomial interpolation. + * Note that the time is already stored. + */ + +static int CVApolynomialStorePnt(CVodeMem cv_mem, DtpntMem d) +{ + CVadjMem ca_mem; + PolynomialDataMem content; + int is; + + ca_mem = cv_mem->cv_adj_mem; + + content = (PolynomialDataMem) d->content; + + N_VScale(ONE, zn[0], content->y); + + if (IMstoreSensi) { + for (is=0; isyS[is]); + } + + content->order = qu; + + return(0); +} + +/* + * CVApolynomialGetY ( -> IMget ) + * + * This routine uses polynomial interpolation for the forward solution vector. + * It is typically called by the wrapper routines before calling + * user provided routines (fB, djacB, bjacB, jtimesB, psolB)) but + * can be directly called by the user through CVodeGetAdjY. + */ + +static int CVApolynomialGetY(CVodeMem cv_mem, realtype t, + N_Vector y, N_Vector *yS) +{ + CVadjMem ca_mem; + DtpntMem *dt_mem; + PolynomialDataMem content; + + int flag, dir, order, i, j, is, NS; + long int indx, base; + booleantype newpoint; + realtype dt, factor; + + ca_mem = cv_mem->cv_adj_mem; + dt_mem = ca_mem->dt_mem; + + /* Local value of Ns */ + + NS = IMinterpSensi ? Ns : 0; + + /* Get the index in dt_mem */ + + flag = CVAfindIndex(cv_mem, t, &indx, &newpoint); + if (flag != CV_SUCCESS) return(flag); + + /* If we are beyond the left limit but close enough, + then return y at the left limit. */ + + if (indx == 0) { + content = (PolynomialDataMem) (dt_mem[0]->content); + N_VScale(ONE, content->y, y); + for (is=0; isyS[is], yS[is]); + return(CV_SUCCESS); + } + + /* Scaling factor */ + + dt = ABS(dt_mem[indx]->t - dt_mem[indx-1]->t); + + /* Find the direction of the forward integration */ + + dir = (tfinal - tinitial > ZERO) ? 1 : -1; + + /* Establish the base point depending on the integration direction. + Modify the base if there are not enough points for the current order */ + + if (dir == 1) { + base = indx; + content = (PolynomialDataMem) (dt_mem[base]->content); + order = content->order; + if(indx < order) base += order-indx; + } else { + base = indx-1; + content = (PolynomialDataMem) (dt_mem[base]->content); + order = content->order; + if (np-indx > order) base -= indx+order-np; + } + + /* Recompute Y (divided differences for Newton polynomial) if needed */ + + if (newpoint) { + + /* Store 0-th order DD */ + if (dir == 1) { + for(j=0;j<=order;j++) { + T[j] = dt_mem[base-j]->t; + content = (PolynomialDataMem) (dt_mem[base-j]->content); + N_VScale(ONE, content->y, Y[j]); + for (is=0; isyS[is], YS[j][is]); + } + } else { + for(j=0;j<=order;j++) { + T[j] = dt_mem[base-1+j]->t; + content = (PolynomialDataMem) (dt_mem[base-1+j]->content); + N_VScale(ONE, content->y, Y[j]); + for (is=0; isyS[is], YS[j][is]); + } + } + + /* Compute higher-order DD */ + for(i=1;i<=order;i++) { + for(j=order;j>=i;j--) { + factor = dt/(T[j]-T[j-i]); + N_VLinearSum(factor, Y[j], -factor, Y[j-1], Y[j]); + for (is=0; is=0; i--) { + factor = (t-T[i])/dt; + N_VLinearSum(factor, y, ONE, Y[i], y); + for (is=0; iscv_adj_mem; + + cvB_mem = ca_mem->ca_bckpbCrt; + + /* Get forward solution from interpolation */ + + if (IMinterpSensi) + flag = IMget(cv_mem, t, ytmp, yStmp); + else + flag = IMget(cv_mem, t, ytmp, NULL); + + if (flag != CV_SUCCESS) { + cvProcessError(cv_mem, -1, "CVODEA", "CVArhs", MSGCV_BAD_TINTERP, t); + return(-1); + } + + /* Call the user's RHS function */ + + if (cvB_mem->cv_f_withSensi) + retval = (cvB_mem->cv_fs)(t, ytmp, yStmp, yB, yBdot, cvB_mem->cv_user_data); + else + retval = (cvB_mem->cv_f)(t, ytmp, yB, yBdot, cvB_mem->cv_user_data); + + return(retval); +} + +/* + * CVArhsQ + * + * This routine interfaces to the CVQuadRhsFnB (or CVQuadRhsFnBS) routine + * provided by the user. + */ + +static int CVArhsQ(realtype t, N_Vector yB, + N_Vector qBdot, void *cvode_mem) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + int flag, retval; + + cv_mem = (CVodeMem) cvode_mem; + + ca_mem = cv_mem->cv_adj_mem; + + cvB_mem = ca_mem->ca_bckpbCrt; + + /* Get forward solution from interpolation */ + + if (IMinterpSensi) + flag = IMget(cv_mem, t, ytmp, yStmp); + else + flag = IMget(cv_mem, t, ytmp, NULL); + + /* Call the user's RHS function */ + + if (cvB_mem->cv_fQ_withSensi) + retval = (cvB_mem->cv_fQs)(t, ytmp, yStmp, yB, qBdot, cvB_mem->cv_user_data); + else + retval = (cvB_mem->cv_fQ)(t, ytmp, yB, qBdot, cvB_mem->cv_user_data); + + return(retval); +} + + + diff --git a/odemex/Parser/CVode/cv_src/src/cvodes/cvodea_io.c b/odemex/Parser/CVode/cv_src/src/cvodes/cvodea_io.c new file mode 100644 index 0000000..6c6927d --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/cvodes/cvodea_io.c @@ -0,0 +1,716 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.9 $ + * $Date: 2007/06/05 20:55:57 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the optional input and output + * functions for the adjoint module in the CVODES solver. + * ----------------------------------------------------------------- + */ + +/* + * ================================================================= + * IMPORTED HEADER FILES + * ================================================================= + */ + +#include +#include + +#include "cvodes_impl.h" +#include + +/* + * ================================================================= + * CVODEA PRIVATE CONSTANTS + * ================================================================= + */ + +#define ONE RCONST(1.0) + +/* + * ================================================================= + * EXPORTED FUNCTIONS IMPLEMENTATION + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Readibility Constants + * ----------------------------------------------------------------- + */ + +#define IMtype (ca_mem->ca_IMtype) +#define ckpntData (ca_mem->ca_ckpntData) +#define nbckpbs (ca_mem->ca_nbckpbs) + +#define t0_ (ck_mem->ck_t0) +#define t1_ (ck_mem->ck_t1) +#define nst_ (ck_mem->ck_nst) +#define q_ (ck_mem->ck_q) +#define h_ (ck_mem->ck_h) +#define next_ (ck_mem->ck_next) + +/* + * ----------------------------------------------------------------- + * Optional input functions for ASA + * ----------------------------------------------------------------- + */ + +int CVodeSetAdjNoSensi(void *cvode_mem) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeSetAdjNoSensi", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeSetAdjNoSensi", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + ca_mem->ca_IMstoreSensi = FALSE; + + return(CV_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * Optional input functions for backward integration + * ----------------------------------------------------------------- + */ + +int CVodeSetIterTypeB(void *cvode_mem, int which, int iterB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeSetIterTypeB", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeSetIterTypeB", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= nbckpbs ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetIterTypeB", MSGCV_BAD_WHICH); + return(CV_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + flag = CVodeSetIterType(cvodeB_mem, iterB); + + return(flag); +} + +int CVodeSetUserDataB(void *cvode_mem, int which, void *user_dataB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeSetUserDataB", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeSetUserDataB", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= nbckpbs ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetUserDataB", MSGCV_BAD_WHICH); + return(CV_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvB_mem->cv_user_data = user_dataB; + + return(CV_SUCCESS); +} + +int CVodeSetMaxOrdB(void *cvode_mem, int which, int maxordB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + int flag; + + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeSetMaxOrdB", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeSetMaxOrdB", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= nbckpbs ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetMaxOrdB", MSGCV_BAD_WHICH); + return(CV_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + flag = CVodeSetMaxOrd(cvodeB_mem, maxordB); + + return(flag); +} + + +int CVodeSetMaxNumStepsB(void *cvode_mem, int which, long int mxstepsB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeSetMaxNumStepsB", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeSetMaxNumStepsB", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= nbckpbs ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetMaxNumStepsB", MSGCV_BAD_WHICH); + return(CV_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + flag = CVodeSetMaxNumSteps(cvodeB_mem, mxstepsB); + + return(flag); +} + +int CVodeSetStabLimDetB(void *cvode_mem, int which, booleantype stldetB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeSetStabLimDetB", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeSetStabLimDetB", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= nbckpbs ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetStabLimDetB", MSGCV_BAD_WHICH); + return(CV_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + flag = CVodeSetStabLimDet(cvodeB_mem, stldetB); + + return(flag); +} + +int CVodeSetInitStepB(void *cvode_mem, int which, realtype hinB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeSetInitStepB", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeSetInitStepB", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= nbckpbs ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetInitStepB", MSGCV_BAD_WHICH); + return(CV_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + flag = CVodeSetInitStep(cvodeB_mem, hinB); + + return(flag); +} + +int CVodeSetMinStepB(void *cvode_mem, int which, realtype hminB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeSetMinStepB", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeSetMinStepB", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= nbckpbs ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetMinStepB", MSGCV_BAD_WHICH); + return(CV_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + flag = CVodeSetMinStep(cvodeB_mem, hminB); + + return(flag); +} + +int CVodeSetMaxStepB(void *cvode_mem, int which, realtype hmaxB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeSetMaxStepB", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeSetMaxStepB", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= nbckpbs ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetMaxStepB", MSGCV_BAD_WHICH); + return(CV_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + flag = CVodeSetMaxStep(cvodeB_mem, hmaxB); + + return(flag); +} + +/* + * CVodeSetQuad*B + * + * Wrappers for the backward phase around the corresponding + * CVODES quadrature optional input functions + */ + +int CVodeSetQuadErrConB(void *cvode_mem, int which, booleantype errconQB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeSetQuadErrConB", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeSetQuadErrConB", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= nbckpbs ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetQuadErrConB", MSGCV_BAD_WHICH); + return(CV_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + flag = CVodeSetQuadErrCon(cvodeB_mem, errconQB); + + return(flag); +} + +/* + * ----------------------------------------------------------------- + * Optional output functions for backward integration + * ----------------------------------------------------------------- + */ + +/* + * CVodeGetAdjCVodeBmem + * + * This function returns a (void *) pointer to the CVODES + * memory allocated for the backward problem. This pointer can + * then be used to call any of the CVodeGet* CVODES routines to + * extract optional output for the backward integration phase. + */ + +void *CVodeGetAdjCVodeBmem(void *cvode_mem, int which) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, 0, "CVODEA", "CVodeGetAdjCVodeBmem", MSGCV_NO_MEM); + return(NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, 0, "CVODEA", "CVodeGetAdjCVodeBmem", MSGCV_NO_ADJ); + return(NULL); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= nbckpbs ) { + cvProcessError(cv_mem, 0, "CVODEA", "CVodeGetAdjCVodeBmem", MSGCV_BAD_WHICH); + return(NULL); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + return(cvodeB_mem); +} + +/* + * CVodeGetAdjCheckPointsInfo + * + * This routine loads an array of nckpnts structures of type CVadjCheckPointRec. + * The user must allocate space for ckpnt. + */ + +int CVodeGetAdjCheckPointsInfo(void *cvode_mem, CVadjCheckPointRec *ckpnt) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CkpntMem ck_mem; + int i; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeGetAdjCheckPointsInfo", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeGetAdjCheckPointsInfo", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + ck_mem = ca_mem->ck_mem; + + i = 0; + + while (ck_mem != NULL) { + + ckpnt[i].my_addr = (void *) ck_mem; + ckpnt[i].next_addr = (void *) next_; + ckpnt[i].t0 = t0_; + ckpnt[i].t1 = t1_; + ckpnt[i].nstep = nst_; + ckpnt[i].order = q_; + ckpnt[i].step = h_; + + ck_mem = next_; + i++; + + } + + return(CV_SUCCESS); + +} + +/* + * CVodeGetAdjDataPointHermite + * + * This routine returns the solution stored in the data structure + * at the 'which' data point. Cubic Hermite interpolation. + */ + +int CVodeGetAdjDataPointHermite(void *cvode_mem, long int which, + realtype *t, N_Vector y, N_Vector yd) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + DtpntMem *dt_mem; + HermiteDataMem content; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeGetAdjDataPointHermite", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeGetAdjDataPointHermite", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + dt_mem = ca_mem->dt_mem; + + if (IMtype != CV_HERMITE) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVadjGetDataPointHermite", MSGCV_WRONG_INTERP); + return(CV_ILL_INPUT); + } + + *t = dt_mem[which]->t; + + content = (HermiteDataMem) (dt_mem[which]->content); + + if (y != NULL) + N_VScale(ONE, content->y, y); + + if (yd != NULL) + N_VScale(ONE, content->yd, yd); + + return(CV_SUCCESS); +} + +/* + * CVodeGetAdjDataPointPolynomial + * + * This routine returns the solution stored in the data structure + * at the 'which' data point. Polynomial interpolation. + */ + +int CVodeGetAdjDataPointPolynomial(void *cvode_mem, long int which, + realtype *t, int *order, N_Vector y) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + DtpntMem *dt_mem; + PolynomialDataMem content; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeGetAdjDataPointPolynomial", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeGetAdjDataPointPolynomial", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + dt_mem = ca_mem->dt_mem; + + if (IMtype != CV_POLYNOMIAL) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVadjGetDataPointPolynomial", MSGCV_WRONG_INTERP); + return(CV_ILL_INPUT); + } + + *t = dt_mem[which]->t; + + content = (PolynomialDataMem) (dt_mem[which]->content); + + if (y != NULL) + N_VScale(ONE, content->y, y); + + *order = content->order; + + return(CV_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * UNDOCUMENTED development user-callable functions + * ----------------------------------------------------------------- + */ + +/* + * CVodeGetAdjCurrentCheckPoint + * + * Returns the address of the 'active' check point. + */ + +int CVodeGetAdjCurrentCheckPoint(void *cvode_mem, void **addr) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODEA", "CVodeGetAdjCurrentCheckPoint", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeGetAdjCurrentCheckPoint", MSGCV_NO_ADJ); + return(CV_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + *addr = (void *) ckpntData; + + return(CV_SUCCESS); +} diff --git a/odemex/Parser/CVode/cv_src/src/cvodes/cvodes.c b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes.c new file mode 100644 index 0000000..dcbe1fc --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes.c @@ -0,0 +1,9026 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.29 $ + * $Date: 2009/05/06 21:49:02 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the main CVODES integrator + * with sensitivity analysis capabilities. + * ----------------------------------------------------------------- + * + * EXPORTED FUNCTIONS + * ------------------ + * + * Creation, allocation and re-initialization functions + * + * CVodeCreate + * + * CVodeInit + * CVodeReInit + * CVodeSStolerances + * CVodeSVtolerances + * CVodeWFtolerances + * + * CVodeQuadInit + * CVodeQuadReInit + * CVodeQuadSStolerances + * CVodeQuadSVtolerances + * + * CVodeSensInit + * CVodeSensInit1 + * CVodeSensReInit + * CVodeSensSStolerances + * CVodeSensSVtolerances + * CVodeSensEEtolerances + * + * CVodeQuadSensInit + * CVodeQuadSensReInit + * + * CVodeSensToggleOff + * + * CVodeRootInit + * + * Main solver function + * CVode + * + * Interpolated output and extraction functions + * CVodeGetDky + * CVodeGetQuad + * CVodeGetQuadDky + * CVodeGetSens + * CVodeGetSens1 + * CVodeGetSensDky + * CVodeGetSensDky1 + * CVodeGetQuadSens + * CVodeGetQuadSens1 + * CVodeGetQuadSensDky + * CVodeGetQuadSensDky1 + * + * Deallocation functions + * CVodeFree + * CVodeQuadFree + * CVodeSensFree + * CVodeQuadSensFree + * + * PRIVATE FUNCTIONS + * ----------------- + * + * cvCheckNvector + * + * Memory allocation/deallocation + * cvAllocVectors + * cvFreeVectors + * cvQuadAllocVectors + * cvQuadFreeVectors + * cvSensAllocVectors + * cvSensFreeVectors + * cvQuadSensAllocVectors + * cvQuadSensFreeVectors + * + * Initial stepsize calculation + * cvHin + * cvUpperBoundH0 + * cvYddNorm + * + * Initial setup + * cvInitialSetup + * cvEwtSet + * cvEwtSetSS + * cvEwtSetSV + * cvQuadEwtSet + * cvQuadEwtSetSS + * cvQuadEwtSetSV + * cvSensEwtSet + * cvSensEwtSetEE + * cvSensEwtSetSS + * cvSensEwtSetSV + * cvQuadSensEwtSet + * cvQuadSensEwtSetEE + * cvQuadSensEwtSetSS + * cvQuadSensEwtSetSV + * + * Main cvStep function + * cvStep + * + * Functions called at beginning of step + * cvAdjustParams + * cvAdjustOrder + * cvAdjustAdams + * cvAdjustBDF + * cvIncreaseBDF + * cvDecreaseBDF + * cvRescale + * cvPredict + * cvSet + * cvSetAdams + * cvAdamsStart + * cvAdamsFinish + * cvAltSum + * cvSetBDF + * cvSetTqBDF + * + * Nonlinear solver functions + * cvNls + * cvNlsFunctional + * cvNlsNewton + * cvNewtonIteration + * cvQuadNls + * cvStgrNls + * cvStgrNlsFunctional + * cvStgrNlsNewton + * cvStgrNewtonIteration + * cvStgr1Nls + * cvStgr1NlsFunctional + * cvStgr1NlsNewton + * cvStgr1NewtonIteration + * cvQuadSensNls + * cvHandleNFlag + * cvRestore + * + * Error Test + * cvDoErrorTest + * + * Functions called after a successful step + * cvCompleteStep + * cvPrepareNextStep + * cvSetEta + * cvComputeEtaqm1 + * cvComputeEtaqp1 + * cvChooseEta + * + * Function to handle failures + * cvHandleFailure + * + * Functions for BDF Stability Limit Detection + * cvBDFStab + * cvSLdet + * + * Functions for rootfinding + * cvRcheck1 + * cvRcheck2 + * cvRcheck3 + * cvRootFind + * + * Functions for combined norms + * cvQuadUpdateNorm + * cvSensNorm + * cvSensUpdateNorm + * cvQuadSensNorm + * cvQuadSensUpdateNorm + * + * Wrappers for sensitivity RHS + * cvSensRhsWrapper + * cvSensRhs1Wrapper + * + * Internal DQ approximations for sensitivity RHS + * cvSensRhsInternalDQ + * cvSensRhs1InternalDQ + * cvQuadSensRhsDQ + * + * Error message handling functions + * cvProcessError + * cvErrHandler + * + * ----------------------------------------------------------------- + */ + +/* + * ================================================================= + * IMPORTED HEADER FILES + * ================================================================= + */ + +#include +#include +#include +#include + +#include "cvodes_impl.h" +#include +#include + +/* + * ================================================================= + * MACRO DEFINITIONS + * ================================================================= + */ + +/* Macro: loop */ +#define loop for(;;) + +/* + * ================================================================= + * CVODES PRIVATE CONSTANTS + * ================================================================= + */ + +#define ZERO RCONST(0.0) +#define TINY RCONST(1.0e-10) +#define TENTH RCONST(0.1) +#define POINT2 RCONST(0.2) +#define FOURTH RCONST(0.25) +#define HALF RCONST(0.5) +#define ONE RCONST(1.0) +#define TWO RCONST(2.0) +#define THREE RCONST(3.0) +#define FOUR RCONST(4.0) +#define FIVE RCONST(5.0) +#define TWELVE RCONST(12.0) +#define HUN RCONST(100.0) + +/* + * ================================================================= + * CVODES ROUTINE-SPECIFIC CONSTANTS + * ================================================================= + */ + +/* + * Control constants for lower-level functions used by cvStep + * ---------------------------------------------------------- + * + * cvHin return values: + * CV_SUCCESS, + * CV_RHSFUNC_FAIL, CV_RPTD_RHSFUNC_ERR, + * CV_QRHSFUNC_FAIL, CV_RPTD_QRHSFUNC_ERR, + * CV_SRHSFUNC_FAIL, CV_RPTD_SRHSFUNC_ERR, + * CV_TOO_CLOSE + * + * cvStep control constants: + * DO_ERROR_TEST + * PREDICT_AGAIN + * + * cvStep return values: + * CV_SUCCESS, + * CV_CONV_FAILURE, CV_ERR_FAILURE, + * CV_LSETUP_FAIL, CV_LSOLVE_FAIL, + * CV_RTFUNC_FAIL, + * CV_RHSFUNC_FAIL, CV_QRHSFUNC_FAIL, CV_SRHSFUNC_FAIL, CV_QSRHSFUNC_FAIL, + * CV_FIRST_RHSFUNC_ERR, CV_FIRST_QRHSFUNC_ERR, CV_FIRST_SRHSFUNC_ERR, CV_FIRST_QSRHSFUNC_ERR, + * CV_UNREC_RHSFUNC_ERR, CV_UNREC_QRHSFUNC_ERR, CV_UNREC_SRHSFUNC_ERR, CV_UNREC_QSRHSFUNC_ERR, + * CV_REPTD_RHSFUNC_ERR, CV_REPTD_QRHSFUNC_ERR, CV_REPTD_SRHSFUNC_ERR, CV_REPTD_QSRHSFUNC_ERR, + * + * cvNls input nflag values: + * FIRST_CALL + * PREV_CONV_FAIL + * PREV_ERR_FAIL + * + * cvNls return values: + * CV_SUCCESS, + * CV_LSETUP_FAIL, CV_LSOLVE_FAIL, + * CV_RHSFUNC_FAIL, CV_SRHSFUNC_FAIL, + * CONV_FAIL, + * RHSFUNC_RECVR, SRHSFUNC_RECVR + * + * cvNewtonIteration return values: + * CV_SUCCESS, + * CV_LSOLVE_FAIL, + * CV_RHSFUNC_FAIL, CV_SRHSFUNC_FAIL, + * CONV_FAIL, TRY_AGAIN + * RHSFUNC_RECVR, SRHSFUNC_RECVR + * + */ + +#define DO_ERROR_TEST +2 +#define PREDICT_AGAIN +3 + +#define CONV_FAIL +4 +#define TRY_AGAIN +5 + +#define FIRST_CALL +6 +#define PREV_CONV_FAIL +7 +#define PREV_ERR_FAIL +8 + +#define RHSFUNC_RECVR +9 + +#define QRHSFUNC_RECVR +11 +#define SRHSFUNC_RECVR +12 +#define QSRHSFUNC_RECVR +13 + +/* + * Control constants for lower-level rootfinding functions + * ------------------------------------------------------- + * + * cvRcheck1 return values: + * CV_SUCCESS, + * CV_RTFUNC_FAIL, + * cvRcheck2 return values: + * CV_SUCCESS, + * CV_RTFUNC_FAIL, + * CLOSERT, + * RTFOUND + * cvRcheck3 return values: + * CV_SUCCESS, + * CV_RTFUNC_FAIL, + * RTFOUND + * cvRootFind return values: + * CV_SUCCESS, + * CV_RTFUNC_FAIL, + * RTFOUND + */ + +#define RTFOUND +1 +#define CLOSERT +3 + +/* + * Control constants for sensitivity DQ + * ------------------------------------ + */ + +#define CENTERED1 +1 +#define CENTERED2 +2 +#define FORWARD1 +3 +#define FORWARD2 +4 + +/* + * Control constants for type of sensitivity RHS + * --------------------------------------------- + */ + +#define CV_ONESENS 1 +#define CV_ALLSENS 2 + +/* + * Control constants for tolerances + * -------------------------------- + */ + +#define CV_NN 0 +#define CV_SS 1 +#define CV_SV 2 +#define CV_WF 3 +#define CV_EE 4 + +/* + * Algorithmic constants + * --------------------- + * + * CVodeGetDky and cvStep + * + * FUZZ_FACTOR fuzz factor used to estimate infinitesimal time intervals + * + * cvHin + * + * HLB_FACTOR factor for upper bound on initial step size + * HUB_FACTOR factor for lower bound on initial step size + * H_BIAS bias factor in selection of intial step size + * MAX_ITERS maximum attempts to compute the initial step size + * + * CVodeCreate + * + * CORTES constant in nonlinear iteration convergence test + * + * cvStep + * + * THRESH if eta < THRESH reject a change in step size or order + * ETAMX1 -+ + * ETAMX2 | + * ETAMX3 |-> bounds for eta (step size change) + * ETAMXF | + * ETAMIN | + * ETACF -+ + * ADDON safety factor in computing eta + * BIAS1 -+ + * BIAS2 |-> bias factors in eta selection + * BIAS3 -+ + * ONEPSM (1+epsilon) used in testing if the step size is below its bound + * + * SMALL_NST nst > SMALL_NST => use ETAMX3 + * MXNCF max no. of convergence failures during one step try + * MXNEF max no. of error test failures during one step try + * MXNEF1 max no. of error test failures before forcing a reduction of order + * SMALL_NEF if an error failure occurs and SMALL_NEF <= nef <= MXNEF1, then + * reset eta = MIN(eta, ETAMXF) + * LONG_WAIT number of steps to wait before considering an order change when + * q==1 and MXNEF1 error test failures have occurred + * + * cvNls + * + * NLS_MAXCOR maximum no. of corrector iterations for the nonlinear solver + * CRDOWN constant used in the estimation of the convergence rate (crate) + * of the iterates for the nonlinear equation + * DGMAX iter == CV_NEWTON, |gamma/gammap-1| > DGMAX => call lsetup + * RDIV declare divergence if ratio del/delp > RDIV + * MSBP max no. of steps between lsetup calls + * + */ + + +#define FUZZ_FACTOR RCONST(100.0) + +#define HLB_FACTOR RCONST(100.0) +#define HUB_FACTOR RCONST(0.1) +#define H_BIAS HALF +#define MAX_ITERS 4 + +#define CORTES RCONST(0.1) + +#define THRESH RCONST(1.5) +#define ETAMX1 RCONST(10000.0) +#define ETAMX2 RCONST(10.0) +#define ETAMX3 RCONST(10.0) +#define ETAMXF RCONST(0.2) +#define ETAMIN RCONST(0.1) +#define ETACF RCONST(0.25) +#define ADDON RCONST(0.000001) +#define BIAS1 RCONST(6.0) +#define BIAS2 RCONST(6.0) +#define BIAS3 RCONST(10.0) +#define ONEPSM RCONST(1.000001) + +#define SMALL_NST 10 +#define MXNCF 10 +#define MXNEF 7 +#define MXNEF1 3 +#define SMALL_NEF 2 +#define LONG_WAIT 10 + +#define NLS_MAXCOR 3 +#define CRDOWN RCONST(0.3) +#define DGMAX RCONST(0.3) + +#define RDIV TWO +#define MSBP 20 + +/* + * ================================================================= + * PRIVATE FUNCTION PROTOTYPES + * ================================================================= + */ + +static booleantype cvCheckNvector(N_Vector tmpl); + +/* Memory allocation/deallocation */ + +static booleantype cvAllocVectors(CVodeMem cv_mem, N_Vector tmpl); +static void cvFreeVectors(CVodeMem cv_mem); + +static booleantype cvQuadAllocVectors(CVodeMem cv_mem, N_Vector tmpl); +static void cvQuadFreeVectors(CVodeMem cv_mem); + +static booleantype cvSensAllocVectors(CVodeMem cv_mem, N_Vector tmpl); +static void cvSensFreeVectors(CVodeMem cv_mem); + +static booleantype cvQuadSensAllocVectors(CVodeMem cv_mem, N_Vector tmpl); +static void cvQuadSensFreeVectors(CVodeMem cv_mem); + +/* Initial stepsize calculation */ + +static int cvHin(CVodeMem cv_mem, realtype tout); +static realtype cvUpperBoundH0(CVodeMem cv_mem, realtype tdist); +static int cvYddNorm(CVodeMem cv_mem, realtype hg, realtype *yddnrm); + +/* Initial setup */ + +static int cvInitialSetup(CVodeMem cv_mem); + +static int cvEwtSetSS(CVodeMem cv_mem, N_Vector ycur, N_Vector weight); +static int cvEwtSetSV(CVodeMem cv_mem, N_Vector ycur, N_Vector weight); + +static int cvQuadEwtSet(CVodeMem cv_mem, N_Vector qcur, N_Vector weightQ); +static int cvQuadEwtSetSS(CVodeMem cv_mem, N_Vector qcur, N_Vector weightQ); +static int cvQuadEwtSetSV(CVodeMem cv_mem, N_Vector qcur, N_Vector weightQ); + +static int cvSensEwtSet(CVodeMem cv_mem, N_Vector *yScur, N_Vector *weightS); +static int cvSensEwtSetEE(CVodeMem cv_mem, N_Vector *yScur, N_Vector *weightS); +static int cvSensEwtSetSS(CVodeMem cv_mem, N_Vector *yScur, N_Vector *weightS); +static int cvSensEwtSetSV(CVodeMem cv_mem, N_Vector *yScur, N_Vector *weightS); + +static int cvQuadSensEwtSet(CVodeMem cv_mem, N_Vector *yQScur, N_Vector *weightQS); +static int cvQuadSensEwtSetEE(CVodeMem cv_mem, N_Vector *yQScur, N_Vector *weightQS); +static int cvQuadSensEwtSetSS(CVodeMem cv_mem, N_Vector *yQScur, N_Vector *weightQS); +static int cvQuadSensEwtSetSV(CVodeMem cv_mem, N_Vector *yQScur, N_Vector *weightQS); + +/* Main cvStep function */ + +static int cvStep(CVodeMem cv_mem); + +/* Function called at beginning of step */ + +static void cvAdjustParams(CVodeMem cv_mem); +static void cvAdjustOrder(CVodeMem cv_mem, int deltaq); +static void cvAdjustAdams(CVodeMem cv_mem, int deltaq); +static void cvAdjustBDF(CVodeMem cv_mem, int deltaq); +static void cvIncreaseBDF(CVodeMem cv_mem); +static void cvDecreaseBDF(CVodeMem cv_mem); +static void cvRescale(CVodeMem cv_mem); +static void cvPredict(CVodeMem cv_mem); +static void cvSet(CVodeMem cv_mem); +static void cvSetAdams(CVodeMem cv_mem); +static realtype cvAdamsStart(CVodeMem cv_mem, realtype m[]); +static void cvAdamsFinish(CVodeMem cv_mem, realtype m[], realtype M[], realtype hsum); +static realtype cvAltSum(int iend, realtype a[], int k); +static void cvSetBDF(CVodeMem cv_mem); +static void cvSetTqBDF(CVodeMem cv_mem, realtype hsum, realtype alpha0, + realtype alpha0_hat, realtype xi_inv, realtype xistar_inv); + +/* Nonlinear solver functions */ + +static int cvNls(CVodeMem cv_mem, int nflag); +static int cvNlsFunctional(CVodeMem cv_mem); +static int cvNlsNewton(CVodeMem cv_mem, int nflag); +static int cvNewtonIteration(CVodeMem cv_mem); + +static int cvQuadNls(CVodeMem cv_mem); + +static int cvStgrNls(CVodeMem cv_mem); +static int cvStgrNlsFunctional(CVodeMem cv_mem); +static int cvStgrNlsNewton(CVodeMem cv_mem); +static int cvStgrNewtonIteration(CVodeMem cv_mem); + +static int cvStgr1Nls(CVodeMem cv_mem, int is); +static int cvStgr1NlsFunctional(CVodeMem cv_mem, int is); +static int cvStgr1NlsNewton(CVodeMem cv_mem, int is); +static int cvStgr1NewtonIteration(CVodeMem cv_mem, int is); + +static int cvQuadSensNls(CVodeMem cv_mem); + +static int cvHandleNFlag(CVodeMem cv_mem, int *nflagPtr, realtype saved_t, + int *ncfPtr, long int *ncfnPtr); + +static void cvRestore(CVodeMem cv_mem, realtype saved_t); + +/* Error Test */ + +static int cvDoErrorTest(CVodeMem cv_mem, int *nflagPtr, realtype saved_t, + realtype acor_nrm, + int *nefPtr, long int *netfPtr, realtype *dsmPtr); + +/* Function called after a successful step */ + +static void cvCompleteStep(CVodeMem cv_mem); +static void cvPrepareNextStep(CVodeMem cv_mem, realtype dsm); +static void cvSetEta(CVodeMem cv_mem); +static realtype cvComputeEtaqm1(CVodeMem cv_mem); +static realtype cvComputeEtaqp1(CVodeMem cv_mem); +static void cvChooseEta(CVodeMem cv_mem); + +/* Function to handle failures */ + +static int cvHandleFailure(CVodeMem cv_mem,int flag); + +/* Functions for BDF Stability Limit Detection */ + +static void cvBDFStab(CVodeMem cv_mem); +static int cvSLdet(CVodeMem cv_mem); + +/* Functions for rootfinding */ + +static int cvRcheck1(CVodeMem cv_mem); +static int cvRcheck2(CVodeMem cv_mem); +static int cvRcheck3(CVodeMem cv_mem); +static int cvRootFind(CVodeMem cv_mem); + +/* Function for combined norms */ + +static realtype cvQuadUpdateNorm(CVodeMem cv_mem, realtype old_nrm, + N_Vector xQ, N_Vector wQ); + +static realtype cvSensNorm(CVodeMem cv_mem, N_Vector *xS, N_Vector *wS); +static realtype cvSensUpdateNorm(CVodeMem cv_mem, realtype old_nrm, + N_Vector *xS, N_Vector *wS); + +static realtype cvQuadSensNorm(CVodeMem cv_mem, N_Vector *xQS, N_Vector *wQS); +static realtype cvQuadSensUpdateNorm(CVodeMem cv_mem, realtype old_nrm, + N_Vector *xQS, N_Vector *wQS); + +/* Internal sensitivity RHS DQ functions */ + +static int cvQuadSensRhsInternalDQ(int Ns, realtype t, + N_Vector y, N_Vector *yS, + N_Vector yQdot, N_Vector *yQSdot, + void *cvode_mem, + N_Vector tmp, N_Vector tmpQ); + +static int cvQuadSensRhs1InternalDQ(CVodeMem cv_mem, int is, realtype t, + N_Vector y, N_Vector yS, + N_Vector yQdot, N_Vector yQSdot, + N_Vector tmp, N_Vector tmpQ); + +/* + * ================================================================= + * EXPORTED FUNCTIONS IMPLEMENTATION + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Creation, allocation and re-initialization functions + * ----------------------------------------------------------------- + */ + +/* + * CVodeCreate + * + * CVodeCreate creates an internal memory block for a problem to + * be solved by CVODES. + * If successful, CVodeCreate returns a pointer to the problem memory. + * This pointer should be passed to CVodeInit. + * If an initialization error occurs, CVodeCreate prints an error + * message to standard err and returns NULL. + */ + +void *CVodeCreate(int lmm, int iter) +{ + int maxord; + CVodeMem cv_mem; + + /* Test inputs */ + + if ((lmm != CV_ADAMS) && (lmm != CV_BDF)) { + cvProcessError(NULL, 0, "CVODES", "CVodeCreate", MSGCV_BAD_LMM); + return(NULL); + } + + if ((iter != CV_FUNCTIONAL) && (iter != CV_NEWTON)) { + cvProcessError(NULL, 0, "CVODES", "CVodeCreate", MSGCV_BAD_ITER); + return(NULL); + } + + cv_mem = NULL; + cv_mem = (CVodeMem) malloc(sizeof(struct CVodeMemRec)); + if (cv_mem == NULL) { + cvProcessError(NULL, 0, "CVODES", "CVodeCreate", MSGCV_CVMEM_FAIL); + return(NULL); + } + + maxord = (lmm == CV_ADAMS) ? ADAMS_Q_MAX : BDF_Q_MAX; + + /* copy input parameters into cv_mem */ + + cv_mem->cv_lmm = lmm; + cv_mem->cv_iter = iter; + + /* Set uround */ + + cv_mem->cv_uround = UNIT_ROUNDOFF; + + /* Set default values for integrator optional inputs */ + + cv_mem->cv_f = NULL; + cv_mem->cv_user_data = NULL; + cv_mem->cv_itol = CV_NN; + cv_mem->cv_user_efun = FALSE; + cv_mem->cv_efun = NULL; + cv_mem->cv_e_data = NULL; + cv_mem->cv_ehfun = cvErrHandler; + cv_mem->cv_eh_data = cv_mem; + cv_mem->cv_errfp = stderr; + cv_mem->cv_qmax = maxord; + cv_mem->cv_mxstep = MXSTEP_DEFAULT; + cv_mem->cv_mxhnil = MXHNIL_DEFAULT; + cv_mem->cv_sldeton = FALSE; + cv_mem->cv_hin = ZERO; + cv_mem->cv_hmin = HMIN_DEFAULT; + cv_mem->cv_hmax_inv = HMAX_INV_DEFAULT; + cv_mem->cv_tstopset = FALSE; + cv_mem->cv_maxcor = NLS_MAXCOR; + cv_mem->cv_maxnef = MXNEF; + cv_mem->cv_maxncf = MXNCF; + cv_mem->cv_nlscoef = CORTES; + + /* Initialize root finding variables */ + + cv_mem->cv_glo = NULL; + cv_mem->cv_ghi = NULL; + cv_mem->cv_grout = NULL; + cv_mem->cv_iroots = NULL; + cv_mem->cv_rootdir = NULL; + cv_mem->cv_gfun = NULL; + cv_mem->cv_nrtfn = 0; + cv_mem->cv_gactive = NULL; + cv_mem->cv_mxgnull = 1; + + /* Set default values for quad. optional inputs */ + + cv_mem->cv_quadr = FALSE; + cv_mem->cv_fQ = NULL; + cv_mem->cv_errconQ = FALSE; + cv_mem->cv_itolQ = CV_NN; + + /* Set default values for sensi. optional inputs */ + + cv_mem->cv_sensi = FALSE; + cv_mem->cv_fS_data = NULL; + cv_mem->cv_fS = cvSensRhsInternalDQ; + cv_mem->cv_fS1 = cvSensRhs1InternalDQ; + cv_mem->cv_fSDQ = TRUE; + cv_mem->cv_ifS = CV_ONESENS; + cv_mem->cv_DQtype = CV_CENTERED; + cv_mem->cv_DQrhomax = ZERO; + cv_mem->cv_p = NULL; + cv_mem->cv_pbar = NULL; + cv_mem->cv_plist = NULL; + cv_mem->cv_errconS = FALSE; + cv_mem->cv_maxcorS = NLS_MAXCOR; + cv_mem->cv_ncfS1 = NULL; + cv_mem->cv_ncfnS1 = NULL; + cv_mem->cv_nniS1 = NULL; + cv_mem->cv_itolS = CV_NN; + + /* Set default values for quad. sensi. optional inputs */ + + cv_mem->cv_quadr_sensi = FALSE; + cv_mem->cv_fQS = NULL; + cv_mem->cv_fQS_data = NULL; + cv_mem->cv_fQSDQ = TRUE; + cv_mem->cv_errconQS = FALSE; + cv_mem->cv_itolQS = CV_NN; + + /* Set default for ASA */ + + cv_mem->cv_adj = FALSE; + cv_mem->cv_adj_mem = NULL; + + /* Set the saved values for qmax_alloc */ + + cv_mem->cv_qmax_alloc = maxord; + cv_mem->cv_qmax_allocQ = maxord; + cv_mem->cv_qmax_allocS = maxord; + + /* Initialize lrw and liw */ + + cv_mem->cv_lrw = 65 + 2*L_MAX + NUM_TESTS; + cv_mem->cv_liw = 52; + + /* No mallocs have been done yet */ + + cv_mem->cv_VabstolMallocDone = FALSE; + cv_mem->cv_MallocDone = FALSE; + + cv_mem->cv_VabstolQMallocDone = FALSE; + cv_mem->cv_QuadMallocDone = FALSE; + + cv_mem->cv_VabstolSMallocDone = FALSE; + cv_mem->cv_SabstolSMallocDone = FALSE; + cv_mem->cv_SensMallocDone = FALSE; + + cv_mem->cv_VabstolQSMallocDone = FALSE; + cv_mem->cv_SabstolQSMallocDone = FALSE; + cv_mem->cv_QuadSensMallocDone = FALSE; + + cv_mem->cv_adjMallocDone = FALSE; + + /* Return pointer to CVODES memory block */ + + return((void *)cv_mem); +} + +/*-----------------------------------------------------------------*/ + +#define iter (cv_mem->cv_iter) +#define lmm (cv_mem->cv_lmm) +#define lrw (cv_mem->cv_lrw) +#define liw (cv_mem->cv_liw) + +/*-----------------------------------------------------------------*/ +/* Added by Joep Vanlier */ + +int CVodeSetMaxTime( void *cvode_mem, double maxTime ) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeInit", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + cv_mem->tMax = maxTime; +} + +/*-----------------------------------------------------------------*/ + +/* + * CVodeInit + * + * CVodeInit allocates and initializes memory for a problem. All + * problem inputs are checked for errors. If any error occurs during + * initialization, it is reported to the file whose file pointer is + * errfp and an error flag is returned. Otherwise, it returns CV_SUCCESS + */ + +int CVodeInit(void *cvode_mem, CVRhsFn f, realtype t0, N_Vector y0) +{ + CVodeMem cv_mem; + booleantype nvectorOK, allocOK; + long int lrw1, liw1; + int i,k; + + /* Check cvode_mem */ + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeInit", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Set max integration time Joep Vanlier */ + + cv_mem->tMax = DBL_MAX; + + /* Check for legal input parameters */ + + if (y0==NULL) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeInit", MSGCV_NULL_Y0); + return(CV_ILL_INPUT); + } + + if (f == NULL) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeInit", MSGCV_NULL_F); + return(CV_ILL_INPUT); + } + + /* Test if all required vector operations are implemented */ + + nvectorOK = cvCheckNvector(y0); + if(!nvectorOK) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeInit", MSGCV_BAD_NVECTOR); + return(CV_ILL_INPUT); + } + + /* Set space requirements for one N_Vector */ + + if (y0->ops->nvspace != NULL) { + N_VSpace(y0, &lrw1, &liw1); + } else { + lrw1 = 0; + liw1 = 0; + } + cv_mem->cv_lrw1 = lrw1; + cv_mem->cv_liw1 = liw1; + + /* Allocate the vectors (using y0 as a template) */ + + allocOK = cvAllocVectors(cv_mem, y0); + if (!allocOK) { + cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeInit", MSGCV_MEM_FAIL); + return(CV_MEM_FAIL); + } + + /* All error checking is complete at this point */ + + /* Copy the input parameters into CVODES state */ + + cv_mem->cv_f = f; + cv_mem->cv_tn = t0; + + /* Set step parameters */ + + cv_mem->cv_q = 1; + cv_mem->cv_L = 2; + cv_mem->cv_qwait = cv_mem->cv_L; + cv_mem->cv_etamax = ETAMX1; + + cv_mem->cv_qu = 0; + cv_mem->cv_hu = ZERO; + cv_mem->cv_tolsf = ONE; + + /* Set the linear solver addresses to NULL. + (We check != NULL later, in CVode, if using CV_NEWTON.) */ + + cv_mem->cv_linit = NULL; + cv_mem->cv_lsetup = NULL; + cv_mem->cv_lsolve = NULL; + cv_mem->cv_lfree = NULL; + cv_mem->cv_lmem = NULL; + + /* Set forceSetup to FALSE */ + + cv_mem->cv_forceSetup = FALSE; + + /* Initialize zn[0] in the history array */ + + N_VScale(ONE, y0, cv_mem->cv_zn[0]); + + /* Initialize all the counters */ + + cv_mem->cv_nst = 0; + cv_mem->cv_nfe = 0; + cv_mem->cv_ncfn = 0; + cv_mem->cv_netf = 0; + cv_mem->cv_nni = 0; + cv_mem->cv_nsetups = 0; + cv_mem->cv_nhnil = 0; + cv_mem->cv_nstlp = 0; + cv_mem->cv_nscon = 0; + cv_mem->cv_nge = 0; + + cv_mem->cv_irfnd = 0; + + /* Initialize other integrator optional outputs */ + + cv_mem->cv_h0u = ZERO; + cv_mem->cv_next_h = ZERO; + cv_mem->cv_next_q = 0; + + /* Initialize Stablilty Limit Detection data */ + /* NOTE: We do this even if stab lim det was not + turned on yet. This way, the user can turn it + on at any time */ + + cv_mem->cv_nor = 0; + for (i = 1; i <= 5; i++) + for (k = 1; k <= 3; k++) + cv_mem->cv_ssdat[i-1][k-1] = ZERO; + + /* Problem has been successfully initialized */ + + cv_mem->cv_MallocDone = TRUE; + + return(CV_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +#define lrw1 (cv_mem->cv_lrw1) +#define liw1 (cv_mem->cv_liw1) + +/*-----------------------------------------------------------------*/ + +/* + * CVodeReInit + * + * CVodeReInit re-initializes CVODES's memory for a problem, assuming + * it has already been allocated in a prior CVodeInit call. + * All problem specification inputs are checked for errors. + * If any error occurs during initialization, it is reported to the + * file whose file pointer is errfp. + * The return value is CV_SUCCESS = 0 if no errors occurred, or + * a negative value otherwise. + */ + +int CVodeReInit(void *cvode_mem, realtype t0, N_Vector y0) +{ + CVodeMem cv_mem; + int i,k; + + /* Check cvode_mem */ + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeReInit", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Check if cvode_mem was allocated */ + + if (cv_mem->cv_MallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_MALLOC, "CVODES", "CVodeReInit", MSGCV_NO_MALLOC); + return(CV_NO_MALLOC); + } + + /* Check for legal input parameters */ + + if (y0 == NULL) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeReInit", MSGCV_NULL_Y0); + return(CV_ILL_INPUT); + } + + /* Copy the input parameters into CVODES state */ + + cv_mem->cv_tn = t0; + + /* Set step parameters */ + + cv_mem->cv_q = 1; + cv_mem->cv_L = 2; + cv_mem->cv_qwait = cv_mem->cv_L; + cv_mem->cv_etamax = ETAMX1; + + cv_mem->cv_qu = 0; + cv_mem->cv_hu = ZERO; + cv_mem->cv_tolsf = ONE; + + /* Set forceSetup to FALSE */ + + cv_mem->cv_forceSetup = FALSE; + + /* Initialize zn[0] in the history array */ + + N_VScale(ONE, y0, cv_mem->cv_zn[0]); + + /* Initialize all the counters */ + + cv_mem->cv_nst = 0; + cv_mem->cv_nfe = 0; + cv_mem->cv_ncfn = 0; + cv_mem->cv_netf = 0; + cv_mem->cv_nni = 0; + cv_mem->cv_nsetups = 0; + cv_mem->cv_nhnil = 0; + cv_mem->cv_nstlp = 0; + cv_mem->cv_nscon = 0; + cv_mem->cv_nge = 0; + + cv_mem->cv_irfnd = 0; + + /* Initialize other integrator optional outputs */ + + cv_mem->cv_h0u = ZERO; + cv_mem->cv_next_h = ZERO; + cv_mem->cv_next_q = 0; + + /* Initialize Stablilty Limit Detection data */ + + cv_mem->cv_nor = 0; + for (i = 1; i <= 5; i++) + for (k = 1; k <= 3; k++) + cv_mem->cv_ssdat[i-1][k-1] = ZERO; + + /* Problem has been successfully re-initialized */ + + return(CV_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +/* + * CVodeSStolerances + * CVodeSVtolerances + * CVodeWFtolerances + * + * These functions specify the integration tolerances. One of them + * MUST be called before the first call to CVode. + * + * CVodeSStolerances specifies scalar relative and absolute tolerances. + * CVodeSVtolerances specifies scalar relative tolerance and a vector + * absolute tolerance (a potentially different absolute tolerance + * for each vector component). + * CVodeWFtolerances specifies a user-provides function (of type CVEwtFn) + * which will be called to set the error weight vector. + */ + +int CVodeSStolerances(void *cvode_mem, realtype reltol, realtype abstol) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSStolerances", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (cv_mem->cv_MallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_MALLOC, "CVODES", "CVodeSStolerances", MSGCV_NO_MALLOC); + return(CV_NO_MALLOC); + } + + /* Check inputs */ + + if (reltol < ZERO) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSStolerances", MSGCV_BAD_RELTOL); + return(CV_ILL_INPUT); + } + + if (abstol < ZERO) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSStolerances", MSGCV_BAD_ABSTOL); + return(CV_ILL_INPUT); + } + + /* Copy tolerances into memory */ + + cv_mem->cv_reltol = reltol; + cv_mem->cv_Sabstol = abstol; + + cv_mem->cv_itol = CV_SS; + + cv_mem->cv_user_efun = FALSE; + cv_mem->cv_efun = cvEwtSet; + cv_mem->cv_e_data = NULL; /* will be set to cvode_mem in InitialSetup */ + + return(CV_SUCCESS); +} + + +int CVodeSVtolerances(void *cvode_mem, realtype reltol, N_Vector abstol) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSVtolerances", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (cv_mem->cv_MallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_MALLOC, "CVODES", "CVodeSVtolerances", MSGCV_NO_MALLOC); + return(CV_NO_MALLOC); + } + + /* Check inputs */ + + if (reltol < ZERO) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSVtolerances", MSGCV_BAD_RELTOL); + return(CV_ILL_INPUT); + } + + if (N_VMin(abstol) < ZERO) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSVtolerances", MSGCV_BAD_ABSTOL); + return(CV_ILL_INPUT); + } + + /* Copy tolerances into memory */ + + if ( !(cv_mem->cv_VabstolMallocDone) ) { + cv_mem->cv_Vabstol = N_VClone(cv_mem->cv_ewt); + lrw += lrw1; + liw += liw1; + cv_mem->cv_VabstolMallocDone = TRUE; + } + + cv_mem->cv_reltol = reltol; + N_VScale(ONE, abstol, cv_mem->cv_Vabstol); + + cv_mem->cv_itol = CV_SV; + + cv_mem->cv_user_efun = FALSE; + cv_mem->cv_efun = cvEwtSet; + cv_mem->cv_e_data = NULL; /* will be set to cvode_mem in InitialSetup */ + + return(CV_SUCCESS); +} + + +int CVodeWFtolerances(void *cvode_mem, CVEwtFn efun) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeWFtolerances", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (cv_mem->cv_MallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_MALLOC, "CVODES", "CVodeWFtolerances", MSGCV_NO_MALLOC); + return(CV_NO_MALLOC); + } + + cv_mem->cv_itol = CV_WF; + + cv_mem->cv_user_efun = TRUE; + cv_mem->cv_efun = efun; + cv_mem->cv_e_data = NULL; /* will be set to user_data in InitialSetup */ + + return(CV_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +/* + * CVodeQuadInit + * + * CVodeQuadInit allocates and initializes quadrature related + * memory for a problem. All problem specification inputs are + * checked for errors. If any error occurs during initialization, + * it is reported to the file whose file pointer is errfp. + * The return value is CV_SUCCESS = 0 if no errors occurred, or + * a negative value otherwise. + */ + +int CVodeQuadInit(void *cvode_mem, CVQuadRhsFn fQ, N_Vector yQ0) +{ + CVodeMem cv_mem; + booleantype allocOK; + long int lrw1Q, liw1Q; + + /* Check cvode_mem */ + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeQuadInit", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Set space requirements for one N_Vector */ + N_VSpace(yQ0, &lrw1Q, &liw1Q); + cv_mem->cv_lrw1Q = lrw1Q; + cv_mem->cv_liw1Q = liw1Q; + + /* Allocate the vectors (using yQ0 as a template) */ + allocOK = cvQuadAllocVectors(cv_mem, yQ0); + if (!allocOK) { + cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeQuadInit", MSGCV_MEM_FAIL); + return(CV_MEM_FAIL); + } + + /* Initialize znQ[0] in the history array */ + N_VScale(ONE, yQ0, cv_mem->cv_znQ[0]); + + /* Copy the input parameters into CVODES state */ + cv_mem->cv_fQ = fQ; + + /* Initialize counters */ + cv_mem->cv_nfQe = 0; + cv_mem->cv_netfQ = 0; + + /* Quadrature integration turned ON */ + cv_mem->cv_quadr = TRUE; + cv_mem->cv_QuadMallocDone = TRUE; + + /* Quadrature initialization was successfull */ + return(CV_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +#define lrw1Q (cv_mem->cv_lrw1Q) +#define liw1Q (cv_mem->cv_liw1Q) + +/*-----------------------------------------------------------------*/ + +/* + * CVodeQuadReInit + * + * CVodeQuadReInit re-initializes CVODES's quadrature related memory + * for a problem, assuming it has already been allocated in prior + * calls to CVodeInit and CVodeQuadInit. + * All problem specification inputs are checked for errors. + * If any error occurs during initialization, it is reported to the + * file whose file pointer is errfp. + * The return value is CV_SUCCESS = 0 if no errors occurred, or + * a negative value otherwise. + */ + +int CVodeQuadReInit(void *cvode_mem, N_Vector yQ0) +{ + CVodeMem cv_mem; + + /* Check cvode_mem */ + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeQuadReInit", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Ckeck if quadrature was initialized? */ + if (cv_mem->cv_QuadMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_QUAD, "CVODES", "CVodeQuadReInit", MSGCV_NO_QUAD); + return(CV_NO_QUAD); + } + + /* Initialize znQ[0] in the history array */ + N_VScale(ONE, yQ0, cv_mem->cv_znQ[0]); + + /* Initialize counters */ + cv_mem->cv_nfQe = 0; + cv_mem->cv_netfQ = 0; + + /* Quadrature integration turned ON */ + cv_mem->cv_quadr = TRUE; + + /* Quadrature re-initialization was successfull */ + return(CV_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +/* + * CVodeQuadSStolerances + * CVodeQuadSVtolerances + * + * These functions specify the integration tolerances for sensitivity + * variables. One of them MUST be called before the first call to + * CVode IF error control on the quadrature variables is enabled + * (see CVodeSetQuadErrCon). + * + * CVodeQuadSStolerances specifies scalar relative and absolute tolerances. + * CVodeQuadSVtolerances specifies scalar relative tolerance and a vector + * absolute toleranc (a potentially different absolute tolerance for each + * vector component). + */ + +int CVodeQuadSStolerances(void *cvode_mem, realtype reltolQ, realtype abstolQ) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeQuadSStolerances", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Ckeck if quadrature was initialized? */ + + if (cv_mem->cv_QuadMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_QUAD, "CVODES", "CVodeQuadSStolerances", MSGCV_NO_QUAD); + return(CV_NO_QUAD); + } + + /* Test user-supplied tolerances */ + + if (reltolQ < ZERO) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSStolerances", MSGCV_BAD_RELTOLQ); + return(CV_ILL_INPUT); + } + + if (abstolQ < 0) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSStolerances", MSGCV_BAD_ABSTOLQ); + return(CV_ILL_INPUT); + } + + /* Copy tolerances into memory */ + + cv_mem->cv_itolQ = CV_SS; + + cv_mem->cv_reltolQ = reltolQ; + cv_mem->cv_SabstolQ = abstolQ; + + return(CV_SUCCESS); +} + +int CVodeQuadSVtolerances(void *cvode_mem, realtype reltolQ, N_Vector abstolQ) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeQuadSVtolerances", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Ckeck if quadrature was initialized? */ + + if (cv_mem->cv_QuadMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_QUAD, "CVODES", "CVodeQuadSVtolerances", MSGCV_NO_QUAD); + return(CV_NO_QUAD); + } + + /* Test user-supplied tolerances */ + + if (reltolQ < ZERO) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSVtolerances", MSGCV_BAD_RELTOLQ); + return(CV_ILL_INPUT); + } + + if (abstolQ == NULL) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSVtolerances", MSGCV_NULL_ABSTOLQ); + return(CV_ILL_INPUT); + } + + if (N_VMin(abstolQ) < ZERO) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSVtolerances", MSGCV_BAD_ABSTOLQ); + return(CV_ILL_INPUT); + } + + /* Copy tolerances into memory */ + + cv_mem->cv_itolQ = CV_SV; + + cv_mem->cv_reltolQ = reltolQ; + + if ( !(cv_mem->cv_VabstolQMallocDone) ) { + cv_mem->cv_VabstolQ = N_VClone(cv_mem->cv_tempvQ); + lrw += lrw1Q; + liw += liw1Q; + cv_mem->cv_VabstolQMallocDone = TRUE; + } + + N_VScale(ONE, abstolQ, cv_mem->cv_VabstolQ); + + return(CV_SUCCESS); +} + + +/*-----------------------------------------------------------------*/ + +#define stgr1alloc (cv_mem->cv_stgr1alloc) +#define nniS1 (cv_mem->cv_nniS1) +#define ncfnS1 (cv_mem->cv_ncfnS1) +#define ncfS1 (cv_mem->cv_ncfS1) + +/*-----------------------------------------------------------------*/ + +/* + * CVodeSensInit + * + * CVodeSensInit allocates and initializes sensitivity related + * memory for a problem (using a sensitivity RHS function of type + * CVSensRhsFn). All problem specification inputs are checked for + * errors. + * The return value is CV_SUCCESS = 0 if no errors occurred, or + * a negative value otherwise. + */ + +int CVodeSensInit(void *cvode_mem, int Ns, int ism, CVSensRhsFn fS, N_Vector *yS0) +{ + CVodeMem cv_mem; + booleantype allocOK; + int is; + + /* Check cvode_mem */ + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSensInit", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Check if CVodeSensInit or CVodeSensInit1 was already called */ + + if (cv_mem->cv_SensMallocDone) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit", MSGCV_SENSINIT_2); + return(CV_ILL_INPUT); + } + + /* Check if Ns is legal */ + + if (Ns<=0) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit", MSGCV_BAD_NS); + return(CV_ILL_INPUT); + } + cv_mem->cv_Ns = Ns; + + /* Check if ism is compatible */ + + if (ism==CV_STAGGERED1) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit", MSGCV_BAD_ISM_IFS); + return(CV_ILL_INPUT); + } + + /* Check if ism is legal */ + + if ((ism!=CV_SIMULTANEOUS) && (ism!=CV_STAGGERED)) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit", MSGCV_BAD_ISM); + return(CV_ILL_INPUT); + } + cv_mem->cv_ism = ism; + + /* Check if yS0 is non-null */ + + if (yS0 == NULL) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit", MSGCV_NULL_YS0); + return(CV_ILL_INPUT); + } + + /* Store sensitivity RHS-related data */ + + cv_mem->cv_ifS = CV_ALLSENS; + cv_mem->cv_fS1 = NULL; + + if (fS == NULL) { + + cv_mem->cv_fSDQ = TRUE; + cv_mem->cv_fS = cvSensRhsInternalDQ; + cv_mem->cv_fS_data = cvode_mem; + + } else { + + cv_mem->cv_fSDQ = FALSE; + cv_mem->cv_fS = fS; + cv_mem->cv_fS_data = cv_mem->cv_user_data; + + } + + /* No memory allocation for STAGGERED1 */ + + stgr1alloc = FALSE; + + /* Allocate the vectors (using yS0[0] as a template) */ + + allocOK = cvSensAllocVectors(cv_mem, yS0[0]); + if (!allocOK) { + cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeSensInit", MSGCV_MEM_FAIL); + return(CV_MEM_FAIL); + } + + /*---------------------------------------------- + All error checking is complete at this point + -----------------------------------------------*/ + + /* Initialize znS[0] in the history array */ + + for (is=0; iscv_znS[0][is]); + + /* Initialize all sensitivity related counters */ + + cv_mem->cv_nfSe = 0; + cv_mem->cv_nfeS = 0; + cv_mem->cv_ncfnS = 0; + cv_mem->cv_netfS = 0; + cv_mem->cv_nniS = 0; + cv_mem->cv_nsetupsS = 0; + + /* Set default values for plist and pbar */ + + for (is=0; iscv_plist[is] = is; + cv_mem->cv_pbar[is] = ONE; + } + + /* Sensitivities will be computed */ + + cv_mem->cv_sensi = TRUE; + cv_mem->cv_SensMallocDone = TRUE; + + /* Sensitivity initialization was successfull */ + + return(CV_SUCCESS); +} + +/* + * CVodeSensInit1 + * + * CVodeSensInit1 allocates and initializes sensitivity related + * memory for a problem (using a sensitivity RHS function of type + * CVSensRhs1Fn). All problem specification inputs are checked for + * errors. + * The return value is CV_SUCCESS = 0 if no errors occurred, or + * a negative value otherwise. + */ + +int CVodeSensInit1(void *cvode_mem, int Ns, int ism, CVSensRhs1Fn fS1, N_Vector *yS0) +{ + CVodeMem cv_mem; + booleantype allocOK; + int is; + + /* Check cvode_mem */ + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSensInit1", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Check if CVodeSensInit or CVodeSensInit1 was already called */ + + if (cv_mem->cv_SensMallocDone) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit1", MSGCV_SENSINIT_2); + return(CV_ILL_INPUT); + } + + /* Check if Ns is legal */ + + if (Ns<=0) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit1", MSGCV_BAD_NS); + return(CV_ILL_INPUT); + } + cv_mem->cv_Ns = Ns; + + /* Check if ism is legal */ + + if ((ism!=CV_SIMULTANEOUS) && (ism!=CV_STAGGERED) && (ism!=CV_STAGGERED1)) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit1", MSGCV_BAD_ISM); + return(CV_ILL_INPUT); + } + cv_mem->cv_ism = ism; + + /* Check if yS0 is non-null */ + + if (yS0 == NULL) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit1", MSGCV_NULL_YS0); + return(CV_ILL_INPUT); + } + + /* Store sensitivity RHS-related data */ + + cv_mem->cv_ifS = CV_ONESENS; + cv_mem->cv_fS = NULL; + + if (fS1 == NULL) { + + cv_mem->cv_fSDQ = TRUE; + cv_mem->cv_fS1 = cvSensRhs1InternalDQ; + cv_mem->cv_fS_data = cvode_mem; + + } else { + + cv_mem->cv_fSDQ = FALSE; + cv_mem->cv_fS1 = fS1; + cv_mem->cv_fS_data = cv_mem->cv_user_data; + + } + + /* Allocate ncfS1, ncfnS1, and nniS1 if needed */ + + if (ism == CV_STAGGERED1) { + stgr1alloc = TRUE; + ncfS1 = NULL; + ncfS1 = (int*)malloc(Ns*sizeof(int)); + ncfnS1 = NULL; + ncfnS1 = (long int*)malloc(Ns*sizeof(long int)); + nniS1 = NULL; + nniS1 = (long int*)malloc(Ns*sizeof(long int)); + if ( (ncfS1 == NULL) || (ncfnS1 == NULL) || (nniS1 == NULL) ) { + cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeSensInit1", MSGCV_MEM_FAIL); + return(CV_MEM_FAIL); + } + } else { + stgr1alloc = FALSE; + } + + /* Allocate the vectors (using yS0[0] as a template) */ + + allocOK = cvSensAllocVectors(cv_mem, yS0[0]); + if (!allocOK) { + if (stgr1alloc) { + free(ncfS1); ncfS1 = NULL; + free(ncfnS1); ncfnS1 = NULL; + free(nniS1); nniS1 = NULL; + } + cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeSensInit1", MSGCV_MEM_FAIL); + return(CV_MEM_FAIL); + } + + /*---------------------------------------------- + All error checking is complete at this point + -----------------------------------------------*/ + + /* Initialize znS[0] in the history array */ + + for (is=0; iscv_znS[0][is]); + + /* Initialize all sensitivity related counters */ + + cv_mem->cv_nfSe = 0; + cv_mem->cv_nfeS = 0; + cv_mem->cv_ncfnS = 0; + cv_mem->cv_netfS = 0; + cv_mem->cv_nniS = 0; + cv_mem->cv_nsetupsS = 0; + if (ism==CV_STAGGERED1) + for (is=0; iscv_plist[is] = is; + cv_mem->cv_pbar[is] = ONE; + } + + /* Sensitivities will be computed */ + + cv_mem->cv_sensi = TRUE; + cv_mem->cv_SensMallocDone = TRUE; + + /* Sensitivity initialization was successfull */ + + return(CV_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +#define Ns (cv_mem->cv_Ns) +#define ifS (cv_mem->cv_ifS) + +/*-----------------------------------------------------------------*/ + +/* + * CVodeSensReInit + * + * CVodeSensReInit re-initializes CVODES's sensitivity related memory + * for a problem, assuming it has already been allocated in prior + * calls to CVodeInit and CVodeSensInit/CVodeSensInit1. + * All problem specification inputs are checked for errors. + * The number of sensitivities Ns is assumed to be unchanged since + * the previous call to CVodeSensInit. + * If any error occurs during initialization, it is reported to the + * file whose file pointer is errfp. + * The return value is CV_SUCCESS = 0 if no errors occurred, or + * a negative value otherwise. + */ + +int CVodeSensReInit(void *cvode_mem, int ism, N_Vector *yS0) +{ + CVodeMem cv_mem; + int is; + + /* Check cvode_mem */ + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSensReInit", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was sensitivity initialized? */ + + if (cv_mem->cv_SensMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeSensReInit", MSGCV_NO_SENSI); + return(CV_NO_SENS); + } + + /* Check if ism is compatible */ + + if ((ifS==CV_ALLSENS) && (ism==CV_STAGGERED1)) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensReInit", MSGCV_BAD_ISM_IFS); + return(CV_ILL_INPUT); + } + + /* Check if ism is legal */ + + if ((ism!=CV_SIMULTANEOUS) && (ism!=CV_STAGGERED) && (ism!=CV_STAGGERED1)) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensReInit", MSGCV_BAD_ISM); + return(CV_ILL_INPUT); + } + cv_mem->cv_ism = ism; + + /* Check if yS0 is non-null */ + + if (yS0 == NULL) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensReInit", MSGCV_NULL_YS0); + return(CV_ILL_INPUT); + } + + /* Allocate ncfS1, ncfnS1, and nniS1 if needed */ + + if ( (ism==CV_STAGGERED1) && (stgr1alloc==FALSE) ) { + stgr1alloc = TRUE; + ncfS1 = NULL; + ncfS1 = (int*)malloc(Ns*sizeof(int)); + ncfnS1 = NULL; + ncfnS1 = (long int*)malloc(Ns*sizeof(long int)); + nniS1 = NULL; + nniS1 = (long int*)malloc(Ns*sizeof(long int)); + if ( (ncfS1==NULL) || (ncfnS1==NULL) || (nniS1==NULL) ) { + cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeSensReInit", MSGCV_MEM_FAIL); + return(CV_MEM_FAIL); + } + } + + /*---------------------------------------------- + All error checking is complete at this point + -----------------------------------------------*/ + + /* Initialize znS[0] in the history array */ + + for (is=0; iscv_znS[0][is]); + + /* Initialize all sensitivity related counters */ + + cv_mem->cv_nfSe = 0; + cv_mem->cv_nfeS = 0; + cv_mem->cv_ncfnS = 0; + cv_mem->cv_netfS = 0; + cv_mem->cv_nniS = 0; + cv_mem->cv_nsetupsS = 0; + if (ism==CV_STAGGERED1) + for (is=0; iscv_sensi = TRUE; + + return(CV_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +/* + * CVodeSensSStolerances + * CVodeSensSVtolerances + * CVodeSensEEtolerances + * + * These functions specify the integration tolerances for sensitivity + * variables. One of them MUST be called before the first call to CVode. + * + * CVodeSensSStolerances specifies scalar relative and absolute tolerances. + * CVodeSensSVtolerances specifies scalar relative tolerance and a vector + * absolute tolerance for each sensitivity vector (a potentially different + * absolute tolerance for each vector component). + * CVodeEEtolerances specifies that tolerances for sensitivity variables + * should be estimated from those provided for the state variables. + */ + +int CVodeSensSStolerances(void *cvode_mem, realtype reltolS, realtype *abstolS) +{ + CVodeMem cv_mem; + int is; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSensSStolerances", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was sensitivity initialized? */ + + if (cv_mem->cv_SensMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeSensSStolerances", MSGCV_NO_SENSI); + return(CV_NO_SENS); + } + + /* Test user-supplied tolerances */ + + if (reltolS < ZERO) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensSStolerances", MSGCV_BAD_RELTOLS); + return(CV_ILL_INPUT); + } + + if (abstolS == NULL) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensSStolerances", MSGCV_NULL_ABSTOLS); + return(CV_ILL_INPUT); + } + + for (is=0; iscv_itolS = CV_SS; + + cv_mem->cv_reltolS = reltolS; + + if ( !(cv_mem->cv_SabstolSMallocDone) ) { + cv_mem->cv_SabstolS = NULL; + cv_mem->cv_SabstolS = (realtype *)malloc(Ns*sizeof(realtype)); + lrw += Ns; + cv_mem->cv_SabstolSMallocDone = TRUE; + } + + for (is=0; iscv_SabstolS[is] = abstolS[is]; + + return(CV_SUCCESS); +} + +int CVodeSensSVtolerances(void *cvode_mem, realtype reltolS, N_Vector *abstolS) +{ + CVodeMem cv_mem; + int is; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSensSVtolerances", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was sensitivity initialized? */ + + if (cv_mem->cv_SensMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeSensSVtolerances", MSGCV_NO_SENSI); + return(CV_NO_SENS); + } + + Ns = cv_mem->cv_Ns; + + /* Test user-supplied tolerances */ + + if (reltolS < ZERO) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensSVtolerances", MSGCV_BAD_RELTOLS); + return(CV_ILL_INPUT); + } + + if (abstolS == NULL) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensSVtolerances", MSGCV_NULL_ABSTOLS); + return(CV_ILL_INPUT); + } + + for (is=0; iscv_itolS = CV_SV; + + cv_mem->cv_reltolS = reltolS; + + if ( !(cv_mem->cv_VabstolSMallocDone) ) { + cv_mem->cv_VabstolS = N_VCloneVectorArray(Ns, cv_mem->cv_tempv); + lrw += Ns*lrw1; + liw += Ns*liw1; + cv_mem->cv_VabstolSMallocDone = TRUE; + } + + for (is=0; iscv_VabstolS[is]); + + return(CV_SUCCESS); +} + + +int CVodeSensEEtolerances(void *cvode_mem) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSensEEtolerances", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was sensitivity initialized? */ + + if (cv_mem->cv_SensMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeSensEEtolerances", MSGCV_NO_SENSI); + return(CV_NO_SENS); + } + + cv_mem->cv_itolS = CV_EE; + + return(CV_SUCCESS); +} + + +/*-----------------------------------------------------------------*/ + +/* + * CVodeQuadSensInit + * + */ + +int CVodeQuadSensInit(void *cvode_mem, CVQuadSensRhsFn fQS, N_Vector *yQS0) +{ + CVodeMem cv_mem; + booleantype allocOK; + int is; + + /* Check cvode_mem */ + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeQuadSensInit", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Check if sensitivity analysis is active */ + if (!cv_mem->cv_sensi) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSensInit", MSGCV_NO_SENSI); + return(CV_ILL_INPUT); + } + + /* Check if yQS0 is non-null */ + if (yQS0 == NULL) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSensInit", MSGCV_NULL_YQS0); + return(CV_ILL_INPUT); + } + + /* Allocate the vectors (using yQS0[0] as a template) */ + allocOK = cvQuadSensAllocVectors(cv_mem, yQS0[0]); + if (!allocOK) { + cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeQuadSensInit", MSGCV_MEM_FAIL); + return(CV_MEM_FAIL); + } + + /*---------------------------------------------- + All error checking is complete at this point + -----------------------------------------------*/ + + /* Set fQS */ + if (fQS == NULL) { + + cv_mem->cv_fQSDQ = TRUE; + cv_mem->cv_fQS = cvQuadSensRhsInternalDQ; + + cv_mem->cv_fQS_data = cvode_mem; + + } else { + + cv_mem->cv_fQSDQ = FALSE; + cv_mem->cv_fQS = fQS; + + cv_mem->cv_fS_data = cv_mem->cv_user_data; + + } + + /* Initialize znQS[0] in the history array */ + for (is=0; iscv_znQS[0][is]); + + /* Initialize all sensitivity related counters */ + cv_mem->cv_nfQSe = 0; + cv_mem->cv_nfQeS = 0; + cv_mem->cv_netfQS = 0; + + /* Quadrature sensitivities will be computed */ + cv_mem->cv_quadr_sensi = TRUE; + cv_mem->cv_QuadSensMallocDone = TRUE; + + /* Sensitivity initialization was successfull */ + return(CV_SUCCESS); +} + +/* + * CVodeQuadSensReInit + * + */ + +int CVodeQuadSensReInit(void *cvode_mem, N_Vector *yQS0) +{ + CVodeMem cv_mem; + int is; + + /* Check cvode_mem */ + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeQuadSensReInit", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Check if sensitivity analysis is active */ + if (!cv_mem->cv_sensi) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSensReInit", MSGCV_NO_SENSI); + return(CV_NO_SENS); + } + + /* Was quadrature sensitivity initialized? */ + if (cv_mem->cv_QuadSensMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_QUADSENS, "CVODES", "CVodeQuadSensReInit", MSGCV_NO_QUADSENSI); + return(CV_NO_QUADSENS); + } + + /* Check if yQS0 is non-null */ + if (yQS0 == NULL) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSensReInit", MSGCV_NULL_YQS0); + return(CV_ILL_INPUT); + } + + /*---------------------------------------------- + All error checking is complete at this point + -----------------------------------------------*/ + + /* Initialize znQS[0] in the history array */ + for (is=0; iscv_znQS[0][is]); + + /* Initialize all sensitivity related counters */ + cv_mem->cv_nfQSe = 0; + cv_mem->cv_nfQeS = 0; + cv_mem->cv_netfQS = 0; + + /* Quadrature sensitivities will be computed */ + cv_mem->cv_quadr_sensi = TRUE; + + /* Problem has been successfully re-initialized */ + return(CV_SUCCESS); +} + + +/* + * CVodeQuadSensSStolerances + * CVodeQuadSensSVtolerances + * CVodeQuadSensEEtolerances + * + * These functions specify the integration tolerances for quadrature + * sensitivity variables. One of them MUST be called before the first + * call to CVode IF these variables are included in the error test. + * + * CVodeQuadSensSStolerances specifies scalar relative and absolute tolerances. + * CVodeQuadSensSVtolerances specifies scalar relative tolerance and a vector + * absolute tolerance for each quadrature sensitivity vector (a potentially + * different absolute tolerance for each vector component). + * CVodeQuadSensEEtolerances specifies that tolerances for sensitivity variables + * should be estimated from those provided for the quadrature variables. + * In this case, tolerances for the quadrature variables must be + * specified through a call to one of CVodeQuad**tolerances. + */ + +int CVodeQuadSensSStolerances(void *cvode_mem, realtype reltolQS, realtype *abstolQS) +{ + CVodeMem cv_mem; + int is; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeQuadSensSStolerances", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Check if sensitivity was initialized */ + + if (cv_mem->cv_SensMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeQuadSensSStolerances", MSGCV_NO_SENSI); + return(CV_NO_SENS); + } + + /* Ckeck if quadrature sensitivity was initialized? */ + + if (cv_mem->cv_QuadSensMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_QUADSENS, "CVODES", "CVodeQuadSSensSStolerances", MSGCV_NO_QUADSENSI); + return(CV_NO_QUAD); + } + + /* Test user-supplied tolerances */ + + if (reltolQS < ZERO) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSensSStolerances", MSGCV_BAD_RELTOLQS); + return(CV_ILL_INPUT); + } + + if (abstolQS == NULL) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSensSStolerances", MSGCV_NULL_ABSTOLQS); + return(CV_ILL_INPUT); + } + + for (is=0; iscv_itolQS = CV_SS; + + cv_mem->cv_reltolQS = reltolQS; + + if ( !(cv_mem->cv_SabstolQSMallocDone) ) { + cv_mem->cv_SabstolQS = NULL; + cv_mem->cv_SabstolQS = (realtype *)malloc(Ns*sizeof(realtype)); + lrw += Ns; + cv_mem->cv_SabstolQSMallocDone = TRUE; + } + + for (is=0; iscv_SabstolQS[is] = abstolQS[is]; + + return(CV_SUCCESS); +} + +int CVodeQuadSensSVtolerances(void *cvode_mem, realtype reltolQS, N_Vector *abstolQS) +{ + CVodeMem cv_mem; + int is; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeQuadSensSVtolerances", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* check if sensitivity was initialized */ + + if (cv_mem->cv_SensMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeQuadSensSVtolerances", MSGCV_NO_SENSI); + return(CV_NO_SENS); + } + + /* Ckeck if quadrature sensitivity was initialized? */ + + if (cv_mem->cv_QuadSensMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_QUADSENS, "CVODES", "CVodeQuadSensSVtolerances", MSGCV_NO_QUADSENSI); + return(CV_NO_QUAD); + } + + Ns = cv_mem->cv_Ns; + + /* Test user-supplied tolerances */ + + if (reltolQS < ZERO) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSensSVtolerances", MSGCV_BAD_RELTOLQS); + return(CV_ILL_INPUT); + } + + if (abstolQS == NULL) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensSVtolerances", MSGCV_NULL_ABSTOLQS); + return(CV_ILL_INPUT); + } + + for (is=0; iscv_itolQS = CV_SV; + + cv_mem->cv_reltolQS = reltolQS; + + if ( !(cv_mem->cv_VabstolQSMallocDone) ) { + cv_mem->cv_VabstolQS = N_VCloneVectorArray(Ns, cv_mem->cv_tempvQ); + lrw += Ns*lrw1Q; + liw += Ns*liw1Q; + cv_mem->cv_VabstolQSMallocDone = TRUE; + } + + for (is=0; iscv_VabstolQS[is]); + + return(CV_SUCCESS); +} + + +int CVodeQuadSensEEtolerances(void *cvode_mem) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeQuadSensEEtolerances", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* check if sensitivity was initialized */ + + if (cv_mem->cv_SensMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeQuadSensEEtolerances", MSGCV_NO_SENSI); + return(CV_NO_SENS); + } + + /* Ckeck if quadrature sensitivity was initialized? */ + + if (cv_mem->cv_QuadSensMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_QUADSENS, "CVODES", "CVodeQuadSensEEtolerances", MSGCV_NO_QUADSENSI); + return(CV_NO_QUAD); + } + + cv_mem->cv_itolQS = CV_EE; + + return(CV_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +/* + * CVodeSensToggleOff + * + * CVodeSensToggleOff deactivates sensitivity calculations. + * It does NOT deallocate sensitivity-related memory. + */ + +int CVodeSensToggleOff(void *cvode_mem) +{ + CVodeMem cv_mem; + + /* Check cvode_mem */ + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSensToggleOff", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Disable sensitivities */ + cv_mem->cv_sensi = FALSE; + cv_mem->cv_quadr_sensi = FALSE; + + return(CV_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +#define gfun (cv_mem->cv_gfun) +#define glo (cv_mem->cv_glo) +#define ghi (cv_mem->cv_ghi) +#define grout (cv_mem->cv_grout) +#define iroots (cv_mem->cv_iroots) +#define rootdir (cv_mem->cv_rootdir) +#define gactive (cv_mem->cv_gactive) + +/*-----------------------------------------------------------------*/ + +/* + * CVodeRootInit + * + * CVodeRootInit initializes a rootfinding problem to be solved + * during the integration of the ODE system. It loads the root + * function pointer and the number of root functions, and allocates + * workspace memory. The return value is CV_SUCCESS = 0 if no errors + * occurred, or a negative value otherwise. + */ + +int CVodeRootInit(void *cvode_mem, int nrtfn, CVRootFn g) +{ + CVodeMem cv_mem; + int i, nrt; + + /* Check cvode_mem */ + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeRootInit", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + nrt = (nrtfn < 0) ? 0 : nrtfn; + + /* If rerunning CVodeRootInit() with a different number of root + functions (changing number of gfun components), then free + currently held memory resources */ + if ((nrt != cv_mem->cv_nrtfn) && (cv_mem->cv_nrtfn > 0)) { + free(glo); glo = NULL; + free(ghi); ghi = NULL; + free(grout); grout = NULL; + free(iroots); iroots = NULL; + free(rootdir); rootdir = NULL; + free(gactive); gactive = NULL; + + lrw -= 3 * (cv_mem->cv_nrtfn); + liw -= 3 * (cv_mem->cv_nrtfn); + + } + + /* If CVodeRootInit() was called with nrtfn == 0, then set cv_nrtfn to + zero and cv_gfun to NULL before returning */ + if (nrt == 0) { + cv_mem->cv_nrtfn = nrt; + gfun = NULL; + return(CV_SUCCESS); + } + + /* If rerunning CVodeRootInit() with the same number of root functions + (not changing number of gfun components), then check if the root + function argument has changed */ + /* If g != NULL then return as currently reserved memory resources + will suffice */ + if (nrt == cv_mem->cv_nrtfn) { + if (g != gfun) { + if (g == NULL) { + free(glo); glo = NULL; + free(ghi); ghi = NULL; + free(grout); grout = NULL; + free(iroots); iroots = NULL; + free(rootdir); rootdir = NULL; + free(gactive); gactive = NULL; + + lrw -= 3*nrt; + liw -= 3*nrt; + + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeRootInit", MSGCV_NULL_G); + return(CV_ILL_INPUT); + } + else { + gfun = g; + return(CV_SUCCESS); + } + } + else return(CV_SUCCESS); + } + + /* Set variable values in CVode memory block */ + cv_mem->cv_nrtfn = nrt; + if (g == NULL) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeRootInit", MSGCV_NULL_G); + return(CV_ILL_INPUT); + } + else gfun = g; + + /* Allocate necessary memory and return */ + glo = NULL; + glo = (realtype *) malloc(nrt*sizeof(realtype)); + if (glo == NULL) { + cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeRootInit", MSGCV_MEM_FAIL); + return(CV_MEM_FAIL); + } + + ghi = NULL; + ghi = (realtype *) malloc(nrt*sizeof(realtype)); + if (ghi == NULL) { + free(glo); glo = NULL; + cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeRootInit", MSGCV_MEM_FAIL); + return(CV_MEM_FAIL); + } + + grout = NULL; + grout = (realtype *) malloc(nrt*sizeof(realtype)); + if (grout == NULL) { + free(glo); glo = NULL; + free(ghi); ghi = NULL; + cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeRootInit", MSGCV_MEM_FAIL); + return(CV_MEM_FAIL); + } + + iroots = NULL; + iroots = (int *) malloc(nrt*sizeof(int)); + if (iroots == NULL) { + free(glo); glo = NULL; + free(ghi); ghi = NULL; + free(grout); grout = NULL; + cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeRootInit", MSGCV_MEM_FAIL); + return(CV_MEM_FAIL); + } + + rootdir = NULL; + rootdir = (int *) malloc(nrt*sizeof(int)); + if (rootdir == NULL) { + free(glo); glo = NULL; + free(ghi); ghi = NULL; + free(grout); grout = NULL; + free(iroots); iroots = NULL; + cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeRootInit", MSGCV_MEM_FAIL); + return(CV_MEM_FAIL); + } + + + gactive = NULL; + gactive = (booleantype *) malloc(nrt*sizeof(booleantype)); + if (gactive == NULL) { + free(glo); glo = NULL; + free(ghi); ghi = NULL; + free(grout); grout = NULL; + free(iroots); iroots = NULL; + free(rootdir); rootdir = NULL; + cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeRootInit", MSGCV_MEM_FAIL); + return(CV_MEM_FAIL); + } + + + /* Set default values for rootdir (both directions) */ + for(i=0; icv_f) +#define user_data (cv_mem->cv_user_data) +#define efun (cv_mem->cv_efun) +#define e_data (cv_mem->cv_e_data) +#define qmax (cv_mem->cv_qmax) +#define mxstep (cv_mem->cv_mxstep) +#define mxhnil (cv_mem->cv_mxhnil) +#define sldeton (cv_mem->cv_sldeton) +#define hin (cv_mem->cv_hin) +#define hmin (cv_mem->cv_hmin) +#define hmax_inv (cv_mem->cv_hmax_inv) +#define tstop (cv_mem->cv_tstop) +#define tstopset (cv_mem->cv_tstopset) +#define maxnef (cv_mem->cv_maxnef) +#define maxncf (cv_mem->cv_maxncf) +#define maxcor (cv_mem->cv_maxcor) +#define nlscoef (cv_mem->cv_nlscoef) +#define itol (cv_mem->cv_itol) +#define reltol (cv_mem->cv_reltol) +#define Sabstol (cv_mem->cv_Sabstol) +#define Vabstol (cv_mem->cv_Vabstol) + +#define fQ (cv_mem->cv_fQ) +#define errconQ (cv_mem->cv_errconQ) +#define itolQ (cv_mem->cv_itolQ) +#define reltolQ (cv_mem->cv_reltolQ) +#define SabstolQ (cv_mem->cv_SabstolQ) +#define VabstolQ (cv_mem->cv_VabstolQ) + +#define ism (cv_mem->cv_ism) +#define fS (cv_mem->cv_fS) +#define fS1 (cv_mem->cv_fS1) +#define fS_data (cv_mem->cv_fS_data) +#define fSDQ (cv_mem->cv_fSDQ) +#define DQtype (cv_mem->cv_DQtype) +#define DQrhomax (cv_mem->cv_DQrhomax) +#define pbar (cv_mem->cv_pbar) +#define errconS (cv_mem->cv_errconS) +#define maxcorS (cv_mem->cv_maxcorS) +#define itolS (cv_mem->cv_itolS) +#define reltolS (cv_mem->cv_reltolS) +#define SabstolS (cv_mem->cv_SabstolS) +#define VabstolS (cv_mem->cv_VabstolS) +#define p (cv_mem->cv_p) +#define plist (cv_mem->cv_plist) + +#define fQS (cv_mem->cv_fQS) +#define fQS_data (cv_mem->cv_fQS_data) +#define fQSDQ (cv_mem->cv_fQSDQ) +#define errconQS (cv_mem->cv_errconQS) +#define itolQS (cv_mem->cv_itolQS) +#define reltolQS (cv_mem->cv_reltolQS) +#define SabstolQS (cv_mem->cv_SabstolQS) +#define VabstolQS (cv_mem->cv_VabstolQS) + +#define uround (cv_mem->cv_uround) +#define zn (cv_mem->cv_zn) +#define ewt (cv_mem->cv_ewt) +#define y (cv_mem->cv_y) +#define acor (cv_mem->cv_acor) +#define tempv (cv_mem->cv_tempv) +#define ftemp (cv_mem->cv_ftemp) +#define q (cv_mem->cv_q) +#define qprime (cv_mem->cv_qprime) +#define next_q (cv_mem->cv_next_q) +#define qwait (cv_mem->cv_qwait) +#define L (cv_mem->cv_L) +#define h (cv_mem->cv_h) +#define hprime (cv_mem->cv_hprime) +#define next_h (cv_mem->cv_next_h) +#define eta (cv_mem->cv_eta) +#define etaqm1 (cv_mem->cv_etaqm1) +#define etaq (cv_mem->cv_etaq) +#define etaqp1 (cv_mem->cv_etaqp1) +#define nscon (cv_mem->cv_nscon) +#define hscale (cv_mem->cv_hscale) +#define tn (cv_mem->cv_tn) +#define tau (cv_mem->cv_tau) +#define tq (cv_mem->cv_tq) +#define l (cv_mem->cv_l) +#define rl1 (cv_mem->cv_rl1) +#define gamma (cv_mem->cv_gamma) +#define gammap (cv_mem->cv_gammap) +#define gamrat (cv_mem->cv_gamrat) +#define crate (cv_mem->cv_crate) +#define acnrm (cv_mem->cv_acnrm) +#define mnewt (cv_mem->cv_mnewt) +#define etamax (cv_mem->cv_etamax) +#define nst (cv_mem->cv_nst) +#define nfe (cv_mem->cv_nfe) +#define ncfn (cv_mem->cv_ncfn) +#define netf (cv_mem->cv_netf) +#define nni (cv_mem->cv_nni) +#define nsetups (cv_mem->cv_nsetups) +#define nhnil (cv_mem->cv_nhnil) +#define linit (cv_mem->cv_linit) +#define lsetup (cv_mem->cv_lsetup) +#define lsolve (cv_mem->cv_lsolve) +#define lfree (cv_mem->cv_lfree) +#define lmem (cv_mem->cv_lmem) +#define qu (cv_mem->cv_qu) +#define nstlp (cv_mem->cv_nstlp) +#define h0u (cv_mem->cv_h0u) +#define hu (cv_mem->cv_hu) +#define saved_tq5 (cv_mem->cv_saved_tq5) +#define indx_acor (cv_mem->cv_indx_acor) +#define jcur (cv_mem->cv_jcur) +#define tolsf (cv_mem->cv_tolsf) +#define setupNonNull (cv_mem->cv_setupNonNull) +#define forceSetup (cv_mem->cv_forceSetup) +#define nor (cv_mem->cv_nor) +#define ssdat (cv_mem->cv_ssdat) + +#define nrtfn (cv_mem->cv_nrtfn) +#define tlo (cv_mem->cv_tlo) +#define thi (cv_mem->cv_thi) +#define tretlast (cv_mem->cv_tretlast) +#define toutc (cv_mem->cv_toutc) +#define trout (cv_mem->cv_trout) +#define ttol (cv_mem->cv_ttol) +#define taskc (cv_mem->cv_taskc) +#define irfnd (cv_mem->cv_irfnd) +#define nge (cv_mem->cv_nge) + +#define quadr (cv_mem->cv_quadr) +#define znQ (cv_mem->cv_znQ) +#define ewtQ (cv_mem->cv_ewtQ) +#define acorQ (cv_mem->cv_acorQ) +#define yQ (cv_mem->cv_yQ) +#define tempvQ (cv_mem->cv_tempvQ) +#define acnrmQ (cv_mem->cv_acnrmQ) +#define nfQe (cv_mem->cv_nfQe) +#define netfQ (cv_mem->cv_netfQ) +#define QuadMallocDone (cv_mem->cv_QuadMallocDone) + +#define sensi (cv_mem->cv_sensi) +#define znS (cv_mem->cv_znS) +#define ewtS (cv_mem->cv_ewtS) +#define acorS (cv_mem->cv_acorS) +#define yS (cv_mem->cv_yS) +#define tempvS (cv_mem->cv_tempvS) +#define ftempS (cv_mem->cv_ftempS) +#define crateS (cv_mem->cv_crateS) +#define acnrmS (cv_mem->cv_acnrmS) +#define nfSe (cv_mem->cv_nfSe) +#define nfeS (cv_mem->cv_nfeS) +#define nniS (cv_mem->cv_nniS) +#define ncfnS (cv_mem->cv_ncfnS) +#define netfS (cv_mem->cv_netfS) +#define nsetupsS (cv_mem->cv_nsetupsS) +#define stgr1alloc (cv_mem->cv_stgr1alloc) +#define SensMallocDone (cv_mem->cv_SensMallocDone) + +#define quadr_sensi (cv_mem->cv_quadr_sensi) +#define znQS (cv_mem->cv_znQS) +#define ewtQS (cv_mem->cv_ewtQS) +#define acorQS (cv_mem->cv_acorQS) +#define yQS (cv_mem->cv_yQS) +#define tempvQS (cv_mem->cv_tempvQS) +#define ftempQ (cv_mem->cv_ftempQ) +#define acnrmQS (cv_mem->cv_acnrmQS) +#define nfQSe (cv_mem->cv_nfQSe) +#define nfQeS (cv_mem->cv_nfQeS) +#define netfQS (cv_mem->cv_netfQS) + +#define QuadSensMallocDone (cv_mem->cv_QuadSensMallocDone) + + +/* + * ----------------------------------------------------------------- + * Main solver function + * ----------------------------------------------------------------- + */ + +/* + * CVode + * + * This routine is the main driver of the CVODES package. + * + * It integrates over a time interval defined by the user, by calling + * cvStep to do internal time steps. + * + * The first time that CVode is called for a successfully initialized + * problem, it computes a tentative initial step size h. + * + * CVode supports two modes, specified by itask: CV_NORMAL, CV_ONE_STEP. + * In the CV_NORMAL mode, the solver steps until it reaches or passes tout + * and then interpolates to obtain y(tout). + * In the CV_ONE_STEP mode, it takes one internal step and returns. + */ + +int CVode(void *cvode_mem, realtype tout, N_Vector yout, + realtype *tret, int itask ) +{ + CVodeMem cv_mem; + long int nstloc; + int retval, hflag, kflag, istate, is, ir, ier, irfndp; + realtype troundoff, tout_hin, rh, nrm; + booleantype inactive_roots; + time_t tStart, tEnd; + + /* + * ------------------------------------- + * 1. Check and process inputs + * ------------------------------------- + */ + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVode", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Check if cvode_mem was allocated */ + if (cv_mem->cv_MallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_MALLOC, "CVODES", "CVode", MSGCV_NO_MALLOC); + return(CV_NO_MALLOC); + } + + /* Check for yout != NULL */ + if ((y = yout) == NULL) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_YOUT_NULL); + return(CV_ILL_INPUT); + } + + /* Check for tret != NULL */ + if (tret == NULL) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_TRET_NULL); + return(CV_ILL_INPUT); + } + + /* Check for valid itask */ + if ( (itask != CV_NORMAL) && (itask != CV_ONE_STEP) ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_BAD_ITASK); + return(CV_ILL_INPUT); + } + + if (itask == CV_NORMAL) toutc = tout; + taskc = itask; + + /* + * ---------------------------------------- + * 2. Initializations performed only at + * the first step (nst=0): + * - initial setup + * - initialize Nordsieck history array + * - compute initial step size + * - check for approach to tstop + * - check for approach to a root + * ---------------------------------------- + */ + + if (nst == 0) { + + /* Check inputs for corectness */ + ier = cvInitialSetup(cv_mem); + if (ier!= CV_SUCCESS) return(ier); + + /* + * Call f at (t0,y0), set zn[1] = y'(t0). + * If computing any quadratures, call fQ at (t0,y0), set znQ[1] = yQ'(t0) + * If computing sensitivities, call fS at (t0,y0,yS0), set znS[1][is] = yS'(t0), is=1,...,Ns. + * If computing quadr. sensi., call fQS at (t0,y0,yS0), set znQS[1][is] = yQS'(t0), is=1,...,Ns. + */ + + retval = f(tn, zn[0], zn[1], user_data); + nfe++; + if (retval < 0) { + cvProcessError(cv_mem, CV_RHSFUNC_FAIL, "CVODES", "CVode", MSGCV_RHSFUNC_FAILED, tn); + return(CV_RHSFUNC_FAIL); + } + if (retval > 0) { + cvProcessError(cv_mem, CV_FIRST_RHSFUNC_ERR, "CVODES", "CVode", MSGCV_RHSFUNC_FIRST); + return(CV_FIRST_RHSFUNC_ERR); + } + + if (quadr) { + retval = fQ(tn, zn[0], znQ[1], user_data); + nfQe++; + if (retval < 0) { + cvProcessError(cv_mem, CV_QRHSFUNC_FAIL, "CVODES", "CVode", MSGCV_QRHSFUNC_FAILED, tn); + return(CV_QRHSFUNC_FAIL); + } + if (retval > 0) { + cvProcessError(cv_mem, CV_FIRST_QRHSFUNC_ERR, "CVODES", "CVode", MSGCV_QRHSFUNC_FIRST); + return(CV_FIRST_QRHSFUNC_ERR); + } + } + + if (sensi) { + retval = cvSensRhsWrapper(cv_mem, tn, zn[0], zn[1], znS[0], znS[1], tempv, ftemp); + if (retval < 0) { + cvProcessError(cv_mem, CV_SRHSFUNC_FAIL, "CVODES", "CVode", MSGCV_SRHSFUNC_FAILED, tn); + return(CV_SRHSFUNC_FAIL); + } + if (retval > 0) { + cvProcessError(cv_mem, CV_FIRST_SRHSFUNC_ERR, "CVODES", "CVode", MSGCV_SRHSFUNC_FIRST); + return(CV_FIRST_SRHSFUNC_ERR); + } + } + + if (quadr_sensi) { + retval = fQS(Ns, tn, zn[0], znS[0], znQ[1], znQS[1], fQS_data, tempv, tempvQ); + nfQSe++; + if (retval < 0) { + cvProcessError(cv_mem, CV_QSRHSFUNC_FAIL, "CVODES", "CVode", MSGCV_QSRHSFUNC_FAILED, tn); + return(CV_QSRHSFUNC_FAIL); + } + if (retval > 0) { + cvProcessError(cv_mem, CV_FIRST_QSRHSFUNC_ERR, "CVODES", "CVode", MSGCV_QSRHSFUNC_FIRST); + return(CV_FIRST_QSRHSFUNC_ERR); + } + } + + /* Set initial h (from H0 or cvHin). */ + + h = hin; + if ( (h != ZERO) && ((tout-tn)*h < ZERO) ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_BAD_H0); + return(CV_ILL_INPUT); + } + if (h == ZERO) { + tout_hin = tout; + if ( tstopset && (tout-tn)*(tout-tstop) > 0 ) tout_hin = tstop; + hflag = cvHin(cv_mem, tout_hin); + if (hflag != CV_SUCCESS) { + istate = cvHandleFailure(cv_mem, hflag); + return(istate); + } + } + rh = ABS(h)*hmax_inv; + if (rh > ONE) h /= rh; + if (ABS(h) < hmin) h *= hmin/ABS(h); + + /* Check for approach to tstop */ + + if (tstopset) { + if ( (tstop - tn)*h < ZERO ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_BAD_TSTOP, tstop, tn); + return(CV_ILL_INPUT); + } + if ( (tn + h - tstop)*h > ZERO ) + h = (tstop - tn)*(ONE-FOUR*uround); + } + + /* + * Scale zn[1] by h. + * If computing any quadratures, scale znQ[1] by h. + * If computing sensitivities, scale znS[1][is] by h. + * If computing quadrature sensitivities, scale znQS[1][is] by h. + */ + + hscale = h; + h0u = h; + hprime = h; + + N_VScale(h, zn[1], zn[1]); + + if (quadr) + N_VScale(h, znQ[1], znQ[1]); + + if (sensi) + for (is=0; is 0) { + + retval = cvRcheck1(cv_mem); + + if (retval == CV_RTFUNC_FAIL) { + cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODES", "cvRcheck1", MSGCV_RTFUNC_FAILED, tn); + return(CV_RTFUNC_FAIL); + } + + } + + } /* end first call block */ + + /* + * ------------------------------------------------------ + * 3. At following steps, perform stop tests: + * - check for root in last step + * - check if we passed tstop + * - check if we passed tout (NORMAL mode) + * - check if current tn was returned (ONE_STEP mode) + * - check if we are close to tstop + * (adjust step size if needed) + * ------------------------------------------------------- + */ + + if (nst > 0) { + + /* Estimate an infinitesimal time interval to be used as + a roundoff for time quantities (based on current time + and step size) */ + troundoff = FUZZ_FACTOR*uround*(ABS(tn) + ABS(h)); + + /* First check for a root in the last step taken, other than the + last root found, if any. If itask = CV_ONE_STEP and y(tn) was not + returned because of an intervening root, return y(tn) now. */ + if (nrtfn > 0) { + + irfndp = irfnd; + + retval = cvRcheck2(cv_mem); + + if (retval == CLOSERT) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvRcheck2", MSGCV_CLOSE_ROOTS, tlo); + return(CV_ILL_INPUT); + } else if (retval == CV_RTFUNC_FAIL) { + cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODES", "cvRcheck2", MSGCV_RTFUNC_FAILED, tlo); + return(CV_RTFUNC_FAIL); + } else if (retval == RTFOUND) { + tretlast = *tret = tlo; + return(CV_ROOT_RETURN); + } + + /* If tn is distinct from tretlast (within roundoff), + check remaining interval for roots */ + if ( ABS(tn - tretlast) > troundoff ) { + + retval = cvRcheck3(cv_mem); + + if (retval == CV_SUCCESS) { /* no root found */ + irfnd = 0; + if ((irfndp == 1) && (itask == CV_ONE_STEP)) { + tretlast = *tret = tn; + N_VScale(ONE, zn[0], yout); + return(CV_SUCCESS); + } + } else if (retval == RTFOUND) { /* a new root was found */ + irfnd = 1; + tretlast = *tret = tlo; + return(CV_ROOT_RETURN); + } else if (retval == CV_RTFUNC_FAIL) { /* g failed */ + cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODES", "cvRcheck3", MSGCV_RTFUNC_FAILED, tlo); + return(CV_RTFUNC_FAIL); + } + + } + + } /* end of root stop check */ + + /* In CV_NORMAL mode, test if tout was reached */ + if ( (itask == CV_NORMAL) && ((tn-tout)*h >= ZERO) ) { + tretlast = *tret = tout; + ier = CVodeGetDky(cv_mem, tout, 0, yout); + if (ier != CV_SUCCESS) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_BAD_TOUT, tout); + return(CV_ILL_INPUT); + } + return(CV_SUCCESS); + } + + /* In CV_ONE_STEP mode, test if tn was returned */ + if ( itask == CV_ONE_STEP && ABS(tn - tretlast) > troundoff ) { + tretlast = *tret = tn; + N_VScale(ONE, zn[0], yout); + return(CV_SUCCESS); + } + + /* Test for tn at tstop or near tstop */ + if ( tstopset ) { + + if ( ABS(tn - tstop) <= troundoff ) { + ier = CVodeGetDky(cv_mem, tstop, 0, yout); + if (ier != CV_SUCCESS) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_BAD_TSTOP, tstop, tn); + return(CV_ILL_INPUT); + } + tretlast = *tret = tstop; + tstopset = FALSE; + return(CV_TSTOP_RETURN); + } + + /* If next step would overtake tstop, adjust stepsize */ + if ( (tn + hprime - tstop)*h > ZERO ) { + hprime = (tstop - tn)*(ONE-FOUR*uround); + eta = hprime/h; + } + + } + + } /* end stopping tests block at nst>0 */ + + /* + * -------------------------------------------------- + * 4. Looping point for internal steps + * + * 4.1. check for errors (too many steps, too much + * accuracy requested, step size too small) + * 4.2. take a new step (call cvStep) + * 4.3. stop on error + * 4.4. perform stop tests: + * - check for root in last step + * - check if tout was passed + * - check if close to tstop + * - check if in ONE_STEP mode (must return) + * -------------------------------------------------- + */ + + nstloc = 0; + time( &tStart ); /* Added by J. Vanlier */ + loop { + time( &tEnd ); /* Added by J. Vanlier */ + if ( difftime( tEnd, tStart ) > cv_mem->tMax ) { /* Added by Joep Vanlier */ + fprintf(stderr, "Simulation time exceeded: t=%e, dt=%e\n", tn, h ); + cvProcessError(cv_mem, CV_TOO_MUCH_WORK, "CVODES", "CVode", MSGCV_MAX_STEPS, tn); + istate = CV_TOO_MUCH_WORK; + tretlast = *tret = tn; + N_VScale(ONE, zn[0], yout); + break; + } + + next_h = h; + next_q = q; + + /* Reset and check ewt, ewtQ, ewtS */ + if (nst > 0) { + + ier = efun(zn[0], ewt, e_data); + if(ier != 0) { + if (itol == CV_WF) cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_EWT_NOW_FAIL, tn); + else cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_EWT_NOW_BAD, tn); + istate = CV_ILL_INPUT; + tretlast = *tret = tn; + N_VScale(ONE, zn[0], yout); + break; + } + + if (quadr && errconQ) { + ier = cvQuadEwtSet(cv_mem, znQ[0], ewtQ); + if(ier != 0) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_EWTQ_NOW_BAD, tn); + istate = CV_ILL_INPUT; + tretlast = *tret = tn; + N_VScale(ONE, zn[0], yout); + break; + } + } + + if (sensi) { + ier = cvSensEwtSet(cv_mem, znS[0], ewtS); + if (ier != 0) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_EWTS_NOW_BAD, tn); + istate = CV_ILL_INPUT; + tretlast = *tret = tn; + N_VScale(ONE, zn[0], yout); + break; + } + } + + if (quadr_sensi && errconQS) { + ier = cvQuadSensEwtSet(cv_mem, znQS[0], ewtQS); + if (ier != 0) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_EWTQS_NOW_BAD, tn); + istate = CV_ILL_INPUT; + tretlast = *tret = tn; + N_VScale(ONE, zn[0], yout); + break; + } + } + + } + + /* Check for too many steps */ + if ( (mxstep>0) && (nstloc >= mxstep) ) { + cvProcessError(cv_mem, CV_TOO_MUCH_WORK, "CVODES", "CVode", MSGCV_MAX_STEPS, tn); + istate = CV_TOO_MUCH_WORK; + tretlast = *tret = tn; + N_VScale(ONE, zn[0], yout); + break; + } + + /* Check for too much accuracy requested */ + nrm = N_VWrmsNorm(zn[0], ewt); + if (quadr && errconQ) { + nrm = cvQuadUpdateNorm(cv_mem, nrm, znQ[0], ewtQ); + } + if (sensi && errconS) { + nrm = cvSensUpdateNorm(cv_mem, nrm, znS[0], ewtS); + } + if (quadr_sensi && errconQS) { + nrm = cvQuadSensUpdateNorm(cv_mem, nrm, znQS[0], ewtQS); + } + tolsf = uround * nrm; + if (tolsf > ONE) { + cvProcessError(cv_mem, CV_TOO_MUCH_ACC, "CVODES", "CVode", MSGCV_TOO_MUCH_ACC, tn); + istate = CV_TOO_MUCH_ACC; + tretlast = *tret = tn; + N_VScale(ONE, zn[0], yout); + tolsf *= TWO; + break; + } else { + tolsf = ONE; + } + + /* Check for h below roundoff level in tn */ + if (tn + h == tn) { + nhnil++; + if (nhnil <= mxhnil) + cvProcessError(cv_mem, CV_WARNING, "CVODES", "CVode", MSGCV_HNIL, tn, h); + if (nhnil == mxhnil) + cvProcessError(cv_mem, CV_WARNING, "CVODES", "CVode", MSGCV_HNIL_DONE); + } + + /* Call cvStep to take a step */ + kflag = cvStep(cv_mem); + + /* Process failed step cases, and exit loop */ + if (kflag != CV_SUCCESS) { + istate = cvHandleFailure(cv_mem, kflag); + tretlast = *tret = tn; + N_VScale(ONE, zn[0], yout); + break; + } + + nstloc++; + + /* Check for root in last step taken. */ + if (nrtfn > 0) { + + retval = cvRcheck3(cv_mem); + + if (retval == RTFOUND) { /* A new root was found */ + irfnd = 1; + istate = CV_ROOT_RETURN; + tretlast = *tret = tlo; + break; + } else if (retval == CV_RTFUNC_FAIL) { /* g failed */ + cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODES", "cvRcheck3", MSGCV_RTFUNC_FAILED, tlo); + istate = CV_RTFUNC_FAIL; + break; + } + + /* If we are at the end of the first step and we still have + * some event functions that are inactive, issue a warning + * as this may indicate a user error in the implementation + * of the root function. */ + + if (nst==1) { + inactive_roots = FALSE; + for (ir=0; ircv_mxgnull > 0) && inactive_roots) { + cvProcessError(cv_mem, CV_WARNING, "CVODES", "CVode", MSGCV_INACTIVE_ROOTS); + } + } + + } + + /* In NORMAL mode, check if tout reached */ + if ( (itask == CV_NORMAL) && (tn-tout)*h >= ZERO ) { + istate = CV_SUCCESS; + tretlast = *tret = tout; + (void) CVodeGetDky(cv_mem, tout, 0, yout); + next_q = qprime; + next_h = hprime; + break; + } + + /* Check if tn is at tstop or near tstop */ + if ( tstopset ) { + + troundoff = FUZZ_FACTOR*uround*(ABS(tn) + ABS(h)); + if ( ABS(tn - tstop) <= troundoff) { + (void) CVodeGetDky(cv_mem, tstop, 0, yout); + tretlast = *tret = tstop; + tstopset = FALSE; + istate = CV_TSTOP_RETURN; + break; + } + + if ( (tn + hprime - tstop)*h > ZERO ) { + hprime = (tstop - tn)*(ONE-FOUR*uround); + eta = hprime/h; + } + + } + + /* In ONE_STEP mode, copy y and exit loop */ + if (itask == CV_ONE_STEP) { + istate = CV_SUCCESS; + tretlast = *tret = tn; + N_VScale(ONE, zn[0], yout); + next_q = qprime; + next_h = hprime; + break; + } + + } /* end looping for internal steps */ + + /* Load optional output */ + if (sensi && (ism==CV_STAGGERED1)) { + nniS = 0; + ncfnS = 0; + for (is=0; is q)) { + cvProcessError(cv_mem, CV_BAD_K, "CVODES", "CVodeGetDky", MSGCV_BAD_K); + return(CV_BAD_K); + } + + /* Allow for some slack */ + tfuzz = FUZZ_FACTOR * uround * (ABS(tn) + ABS(hu)); + if (hu < ZERO) tfuzz = -tfuzz; + tp = tn - hu - tfuzz; + tn1 = tn + tfuzz; + if ((t-tp)*(t-tn1) > ZERO) { + cvProcessError(cv_mem, CV_BAD_T, "CVODES", "CVodeGetDky", MSGCV_BAD_T, t, tn-hu, tn); + return(CV_BAD_T); + } + + /* Sum the differentiated interpolating polynomial */ + + s = (t - tn) / h; + for (j=q; j >= k; j--) { + c = ONE; + for (i=j; i >= j-k+1; i--) c *= i; + if (j == q) { + N_VScale(c, zn[q], dky); + } else { + N_VLinearSum(c, zn[j], s, dky, dky); + } + } + if (k == 0) return(CV_SUCCESS); + r = RPowerI(h,-k); + N_VScale(r, dky, dky); + return(CV_SUCCESS); +} + +/* + * CVodeGetQuad + * + * This routine extracts quadrature solution into yQout at the + * time which CVode returned the solution. + * This is just a wrapper that calls CVodeGetQuadDky with k=0. + */ + +int CVodeGetQuad(void *cvode_mem, realtype *tret, N_Vector yQout) +{ + CVodeMem cv_mem; + int flag; + + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuad", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + *tret = tretlast; + + flag = CVodeGetQuadDky(cvode_mem,tretlast,0,yQout); + + return(flag); +} + +/* + * CVodeGetQuadDky + * + * CVodeQuadDky computes the kth derivative of the yQ function at + * time t, where tn-hu <= t <= tn, tn denotes the current + * internal time reached, and hu is the last internal step size + * successfully used by the solver. The user may request + * k=0, 1, ..., qu, where qu is the current order. + * The derivative vector is returned in dky. This vector + * must be allocated by the caller. It is only legal to call this + * function after a successful return from CVode with quadrature + * computation enabled. + */ + +int CVodeGetQuadDky(void *cvode_mem, realtype t, int k, N_Vector dkyQ) +{ + realtype s, c, r; + realtype tfuzz, tp, tn1; + int i, j; + CVodeMem cv_mem; + + /* Check all inputs for legality */ + + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadDky", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if(quadr != TRUE) { + cvProcessError(cv_mem, CV_NO_QUAD, "CVODES", "CVodeGetQuadDky", MSGCV_NO_QUAD); + return(CV_NO_QUAD); + } + + if (dkyQ == NULL) { + cvProcessError(cv_mem, CV_BAD_DKY, "CVODES", "CVodeGetQuadDky", MSGCV_NULL_DKY); + return(CV_BAD_DKY); + } + + if ((k < 0) || (k > q)) { + cvProcessError(cv_mem, CV_BAD_K, "CVODES", "CVodeGetQuadDky", MSGCV_BAD_K); + return(CV_BAD_K); + } + + /* Allow for some slack */ + tfuzz = FUZZ_FACTOR * uround * (ABS(tn) + ABS(hu)); + if (hu < ZERO) tfuzz = -tfuzz; + tp = tn - hu - tfuzz; + tn1 = tn + tfuzz; + if ((t-tp)*(t-tn1) > ZERO) { + cvProcessError(cv_mem, CV_BAD_T, "CVODES", "CVodeGetQuadDky", MSGCV_BAD_T); + return(CV_BAD_T); + } + + /* Sum the differentiated interpolating polynomial */ + + s = (t - tn) / h; + for (j=q; j >= k; j--) { + c = ONE; + for (i=j; i >= j-k+1; i--) c *= i; + if (j == q) { + N_VScale(c, znQ[q], dkyQ); + } else { + N_VLinearSum(c, znQ[j], s, dkyQ, dkyQ); + } + } + if (k == 0) return(CV_SUCCESS); + r = RPowerI(h,-k); + N_VScale(r, dkyQ, dkyQ); + return(CV_SUCCESS); + +} + +/* + * CVodeGetSens + * + * This routine extracts sensitivity solution into ySout at the + * time at which CVode returned the solution. + * This is just a wrapper that calls CVodeSensDky with k=0. + */ + +int CVodeGetSens(void *cvode_mem, realtype *tret, N_Vector *ySout) +{ + CVodeMem cv_mem; + int flag; + + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetSens", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + *tret = tretlast; + + flag = CVodeGetSensDky(cvode_mem,tretlast,0,ySout); + + return(flag); +} + +/* + * CVodeGetSens1 + * + * This routine extracts the is-th sensitivity solution into ySout + * at the time at which CVode returned the solution. + * This is just a wrapper that calls CVodeSensDky1 with k=0. + */ + +int CVodeGetSens1(void *cvode_mem, realtype *tret, int is, N_Vector ySout) +{ + CVodeMem cv_mem; + int flag; + + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetSens1", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + *tret = tretlast; + + flag = CVodeGetSensDky1(cvode_mem,tretlast,0,is,ySout); + + return(flag); +} + +/* + * CVodeGetSensDky + * + * If the user calls directly CVodeSensDky then s must be allocated + * prior to this call. When CVodeSensDky is called by + * CVodeGetSens, only ier=CV_SUCCESS, ier=CV_NO_SENS, or + * ier=CV_BAD_T are possible. + */ + +int CVodeGetSensDky(void *cvode_mem, realtype t, int k, N_Vector *dkyS) +{ + int ier=CV_SUCCESS; + int is; + CVodeMem cv_mem; + + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetSensDky", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (dkyS == NULL) { + cvProcessError(cv_mem, CV_BAD_DKY, "CVODES", "CVodeGetSensDky", MSGCV_NULL_DKYA); + return(CV_BAD_DKY); + } + + for (is=0; is q)) { + cvProcessError(cv_mem, CV_BAD_K, "CVODES", "CVodeGetSensDky1", MSGCV_BAD_K); + return(CV_BAD_K); + } + + if ((is < 0) || (is > Ns-1)) { + cvProcessError(cv_mem, CV_BAD_IS, "CVODES", "CVodeGetSensDky1", MSGCV_BAD_IS); + return(CV_BAD_IS); + } + + /* Allow for some slack */ + tfuzz = FUZZ_FACTOR * uround * (ABS(tn) + ABS(hu)); + if (hu < ZERO) tfuzz = -tfuzz; + tp = tn - hu - tfuzz; + tn1 = tn + tfuzz; + if ((t-tp)*(t-tn1) > ZERO) { + cvProcessError(cv_mem, CV_BAD_T, "CVODES", "CVodeGetSensDky1", MSGCV_BAD_T); + return(CV_BAD_T); + } + + /* Sum the differentiated interpolating polynomial */ + + s = (t - tn) / h; + for (j=q; j >= k; j--) { + c = ONE; + for (i=j; i >= j-k+1; i--) c *= i; + if (j == q) { + N_VScale(c, znS[q][is], dkyS); + } else { + N_VLinearSum(c, znS[j][is], s, dkyS, dkyS); + } + } + if (k == 0) return(CV_SUCCESS); + r = RPowerI(h,-k); + N_VScale(r, dkyS, dkyS); + return(CV_SUCCESS); + +} + +/* + * CVodeGetQuadSens and CVodeGetQuadSens1 + * + * Extraction functions for all or only one of the quadrature sensitivity + * vectors at the time at which CVode returned the ODE solution. + */ + +int CVodeGetQuadSens(void *cvode_mem, realtype *tret, N_Vector *yQSout) +{ + CVodeMem cv_mem; + int flag; + + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadSens", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + *tret = tretlast; + + flag = CVodeGetQuadSensDky(cvode_mem,tretlast,0,yQSout); + + return(flag); +} + +int CVodeGetQuadSens1(void *cvode_mem, realtype *tret, int is, N_Vector yQSout) +{ + CVodeMem cv_mem; + int flag; + + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadSens1", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + *tret = tretlast; + + flag = CVodeGetQuadSensDky1(cvode_mem,tretlast,0,is,yQSout); + + return(flag); +} + +/* + * CVodeGetQuadSensDky and CVodeGetQuadSensDky1 + * + * Dense output functions for all or only one of the quadrature sensitivity + * vectors (or derivative thereof). + */ + +int CVodeGetQuadSensDky(void *cvode_mem, realtype t, int k, N_Vector *dkyQS_all) +{ + int ier=CV_SUCCESS; + int is; + CVodeMem cv_mem; + + if (cvode_mem == NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadSensDky", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (dkyQS_all == NULL) { + cvProcessError(cv_mem, CV_BAD_DKY, "CVODES", "CVodeGetSensDky", MSGCV_NULL_DKYA); + return(CV_BAD_DKY); + } + + for (is=0; is q)) { + cvProcessError(cv_mem, CV_BAD_K, "CVODES", "CVodeGetQuadSensDky1", MSGCV_BAD_K); + return(CV_BAD_K); + } + + if ((is < 0) || (is > Ns-1)) { + cvProcessError(cv_mem, CV_BAD_IS, "CVODES", "CVodeGetQuadSensDky1", MSGCV_BAD_IS); + return(CV_BAD_IS); + } + + /* Allow for some slack */ + tfuzz = FUZZ_FACTOR * uround * (ABS(tn) + ABS(hu)); + if (hu < ZERO) tfuzz = -tfuzz; + tp = tn - hu - tfuzz; + tn1 = tn + tfuzz; + if ((t-tp)*(t-tn1) > ZERO) { + cvProcessError(cv_mem, CV_BAD_T, "CVODES", "CVodeGetQuadSensDky1", MSGCV_BAD_T); + return(CV_BAD_T); + } + + /* Sum the differentiated interpolating polynomial */ + + s = (t - tn) / h; + for (j=q; j >= k; j--) { + c = ONE; + for (i=j; i >= j-k+1; i--) c *= i; + if (j == q) { + N_VScale(c, znQS[q][is], dkyQS); + } else { + N_VLinearSum(c, znQS[j][is], s, dkyQS, dkyQS); + } + } + if (k == 0) return(CV_SUCCESS); + r = RPowerI(h,-k); + N_VScale(r, dkyQS, dkyQS); + return(CV_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * Deallocation functions + * ----------------------------------------------------------------- + */ + +/* + * CVodeFree + * + * This routine frees the problem memory allocated by CVodeInit. + * Such memory includes all the vectors allocated by cvAllocVectors, + * and the memory lmem for the linear solver (deallocated by a call + * to lfree), as well as (if Ns!=0) all memory allocated for + * sensitivity computations by CVodeSensInit. + */ + +void CVodeFree(void **cvode_mem) +{ + CVodeMem cv_mem; + + if (*cvode_mem == NULL) return; + + cv_mem = (CVodeMem) (*cvode_mem); + + cvFreeVectors(cv_mem); + + CVodeQuadFree(cv_mem); + + CVodeSensFree(cv_mem); + + CVodeQuadSensFree(cv_mem); + + CVodeAdjFree(cv_mem); + + if (iter == CV_NEWTON && lfree != NULL) lfree(cv_mem); + + if (nrtfn > 0) { + free(glo); glo = NULL; + free(ghi); ghi = NULL; + free(grout); grout = NULL; + free(iroots); iroots = NULL; + free(rootdir); rootdir = NULL; + free(gactive); gactive = NULL; + } + + free(*cvode_mem); + *cvode_mem = NULL; +} + +/* + * CVodeQuadFree + * + * CVodeQuadFree frees the problem memory in cvode_mem allocated + * for quadrature integration. Its only argument is the pointer + * cvode_mem returned by CVodeCreate. + */ + +void CVodeQuadFree(void *cvode_mem) +{ + CVodeMem cv_mem; + + if (cvode_mem == NULL) return; + cv_mem = (CVodeMem) cvode_mem; + + if(QuadMallocDone) { + cvQuadFreeVectors(cv_mem); + QuadMallocDone = FALSE; + quadr = FALSE; + } +} + +/* + * CVodeSensFree + * + * CVodeSensFree frees the problem memory in cvode_mem allocated + * for sensitivity analysis. Its only argument is the pointer + * cvode_mem returned by CVodeCreate. + */ + +void CVodeSensFree(void *cvode_mem) +{ + CVodeMem cv_mem; + + if (cvode_mem == NULL) return; + cv_mem = (CVodeMem) cvode_mem; + + if(SensMallocDone) { + if (stgr1alloc) { + free(ncfS1); ncfS1 = NULL; + free(ncfnS1); ncfnS1 = NULL; + free(nniS1); nniS1 = NULL; + stgr1alloc = FALSE; + } + cvSensFreeVectors(cv_mem); + SensMallocDone = FALSE; + sensi = FALSE; + } +} + +/* + * CVodeQuadSensFree + * + * CVodeQuadSensFree frees the problem memory in cvode_mem allocated + * for quadrature sensitivity analysis. Its only argument is the pointer + * cvode_mem returned by CVodeCreate. + */ + +void CVodeQuadSensFree(void *cvode_mem) +{ + CVodeMem cv_mem; + + if (cvode_mem == NULL) return; + cv_mem = (CVodeMem) cvode_mem; + + if(QuadSensMallocDone) { + cvQuadSensFreeVectors(cv_mem); + QuadSensMallocDone = FALSE; + quadr_sensi = FALSE; + } +} + + +/* + * ================================================================= + * PRIVATE FUNCTIONS + * ================================================================= + */ + +/* + * cvCheckNvector + * This routine checks if all required vector operations are present. + * If any of them is missing it returns FALSE. + */ + +static booleantype cvCheckNvector(N_Vector tmpl) +{ + if((tmpl->ops->nvclone == NULL) || + (tmpl->ops->nvdestroy == NULL) || + (tmpl->ops->nvlinearsum == NULL) || + (tmpl->ops->nvconst == NULL) || + (tmpl->ops->nvprod == NULL) || + (tmpl->ops->nvdiv == NULL) || + (tmpl->ops->nvscale == NULL) || + (tmpl->ops->nvabs == NULL) || + (tmpl->ops->nvinv == NULL) || + (tmpl->ops->nvaddconst == NULL) || + (tmpl->ops->nvmaxnorm == NULL) || + (tmpl->ops->nvwrmsnorm == NULL) || + (tmpl->ops->nvmin == NULL)) + return(FALSE); + else + return(TRUE); +} + +/* + * ----------------------------------------------------------------- + * Memory allocation/deallocation + * ----------------------------------------------------------------- + */ + +/* + * cvAllocVectors + * + * This routine allocates the CVODES vectors ewt, acor, tempv, ftemp, and + * zn[0], ..., zn[maxord]. + * If all memory allocations are successful, cvAllocVectors returns TRUE. + * Otherwise all allocated memory is freed and cvAllocVectors returns FALSE. + * This routine also sets the optional outputs lrw and liw, which are + * (respectively) the lengths of the real and integer work spaces + * allocated here. + */ + +static booleantype cvAllocVectors(CVodeMem cv_mem, N_Vector tmpl) +{ + int i, j; + + /* Allocate ewt, acor, tempv, ftemp */ + + ewt = N_VClone(tmpl); + if (ewt == NULL) return(FALSE); + + acor = N_VClone(tmpl); + if (acor == NULL) { + N_VDestroy(ewt); + return(FALSE); + } + + tempv = N_VClone(tmpl); + if (tempv == NULL) { + N_VDestroy(ewt); + N_VDestroy(acor); + return(FALSE); + } + + ftemp = N_VClone(tmpl); + if (ftemp == NULL) { + N_VDestroy(tempv); + N_VDestroy(ewt); + N_VDestroy(acor); + return(FALSE); + } + + /* Allocate zn[0] ... zn[qmax] */ + + for (j=0; j <= qmax; j++) { + zn[j] = N_VClone(tmpl); + if (zn[j] == NULL) { + N_VDestroy(ewt); + N_VDestroy(acor); + N_VDestroy(tempv); + N_VDestroy(ftemp); + for (i=0; i < j; i++) N_VDestroy(zn[i]); + return(FALSE); + } + } + + /* Update solver workspace lengths */ + lrw += (qmax + 5)*lrw1; + liw += (qmax + 5)*liw1; + + /* Store the value of qmax used here */ + cv_mem->cv_qmax_alloc = qmax; + + return(TRUE); +} + +/* + * cvFreeVectors + * + * This routine frees the CVODES vectors allocated in cvAllocVectors. + */ + +static void cvFreeVectors(CVodeMem cv_mem) +{ + int j, maxord; + + maxord = cv_mem->cv_qmax_alloc; + + N_VDestroy(ewt); + N_VDestroy(acor); + N_VDestroy(tempv); + N_VDestroy(ftemp); + for (j=0; j <= maxord; j++) + N_VDestroy(zn[j]); + + lrw -= (maxord + 5)*lrw1; + liw -= (maxord + 5)*liw1; + + if (cv_mem->cv_VabstolMallocDone) { + N_VDestroy(Vabstol); + lrw -= lrw1; + liw -= liw1; + } +} + +/* + * CVodeQuadAllocVectors + * + * NOTE: Space for ewtQ is allocated even when errconQ=FALSE, + * although in this case, ewtQ is never used. The reason for this + * decision is to allow the user to re-initialize the quadrature + * computation with errconQ=TRUE, after an initialization with + * errconQ=FALSE, without new memory allocation within + * CVodeQuadReInit. + */ + +static booleantype cvQuadAllocVectors(CVodeMem cv_mem, N_Vector tmpl) +{ + int i, j; + + /* Allocate ewtQ */ + ewtQ = N_VClone(tmpl); + if (ewtQ == NULL) { + return(FALSE); + } + + /* Allocate acorQ */ + acorQ = N_VClone(tmpl); + if (acorQ == NULL) { + N_VDestroy(ewtQ); + return(FALSE); + } + + /* Allocate yQ */ + yQ = N_VClone(tmpl); + if (yQ == NULL) { + N_VDestroy(ewtQ); + N_VDestroy(acorQ); + return(FALSE); + } + + /* Allocate tempvQ */ + tempvQ = N_VClone(tmpl); + if (tempvQ == NULL) { + N_VDestroy(ewtQ); + N_VDestroy(acorQ); + N_VDestroy(yQ); + return(FALSE); + } + + /* Allocate zQn[0] ... zQn[maxord] */ + + for (j=0; j <= qmax; j++) { + znQ[j] = N_VClone(tmpl); + if (znQ[j] == NULL) { + N_VDestroy(ewtQ); + N_VDestroy(acorQ); + N_VDestroy(yQ); + N_VDestroy(tempvQ); + for (i=0; i < j; i++) N_VDestroy(znQ[i]); + return(FALSE); + } + } + + /* Store the value of qmax used here */ + cv_mem->cv_qmax_allocQ = qmax; + + /* Update solver workspace lengths */ + lrw += (qmax + 5)*lrw1Q; + liw += (qmax + 5)*liw1Q; + + return(TRUE); +} + +/* + * cvQuadFreeVectors + * + * This routine frees the CVODES vectors allocated in cvQuadAllocVectors. + */ + +static void cvQuadFreeVectors(CVodeMem cv_mem) +{ + int j, maxord; + + maxord = cv_mem->cv_qmax_allocQ; + + N_VDestroy(ewtQ); + N_VDestroy(acorQ); + N_VDestroy(yQ); + N_VDestroy(tempvQ); + + for (j=0; j<=maxord; j++) N_VDestroy(znQ[j]); + + lrw -= (maxord + 5)*lrw1Q; + liw -= (maxord + 5)*liw1Q; + + if (cv_mem->cv_VabstolQMallocDone) { + N_VDestroy(VabstolQ); + lrw -= lrw1Q; + liw -= liw1Q; + } + + cv_mem->cv_VabstolQMallocDone = FALSE; +} + +/* + * cvSensAllocVectors + * + * Create (through duplication) N_Vectors used for sensitivity analysis, + * using the N_Vector 'tmpl' as a template. + */ + +static booleantype cvSensAllocVectors(CVodeMem cv_mem, N_Vector tmpl) +{ + int i, j; + + /* Allocate yS */ + yS = N_VCloneVectorArray(Ns, tmpl); + if (yS == NULL) { + return(FALSE); + } + + /* Allocate ewtS */ + ewtS = N_VCloneVectorArray(Ns, tmpl); + if (ewtS == NULL) { + N_VDestroyVectorArray(yS, Ns); + return(FALSE); + } + + /* Allocate acorS */ + acorS = N_VCloneVectorArray(Ns, tmpl); + if (acorS == NULL) { + N_VDestroyVectorArray(yS, Ns); + N_VDestroyVectorArray(ewtS, Ns); + return(FALSE); + } + + /* Allocate tempvS */ + tempvS = N_VCloneVectorArray(Ns, tmpl); + if (tempvS == NULL) { + N_VDestroyVectorArray(yS, Ns); + N_VDestroyVectorArray(ewtS, Ns); + N_VDestroyVectorArray(acorS, Ns); + return(FALSE); + } + + /* Allocate ftempS */ + ftempS = N_VCloneVectorArray(Ns, tmpl); + if (ftempS == NULL) { + N_VDestroyVectorArray(yS, Ns); + N_VDestroyVectorArray(ewtS, Ns); + N_VDestroyVectorArray(acorS, Ns); + N_VDestroyVectorArray(tempvS, Ns); + return(FALSE); + } + + /* Allocate znS */ + for (j=0; j<=qmax; j++) { + znS[j] = N_VCloneVectorArray(Ns, tmpl); + if (znS[j] == NULL) { + N_VDestroyVectorArray(yS, Ns); + N_VDestroyVectorArray(ewtS, Ns); + N_VDestroyVectorArray(acorS, Ns); + N_VDestroyVectorArray(tempvS, Ns); + N_VDestroyVectorArray(ftempS, Ns); + for (i=0; icv_qmax_allocS = qmax; + + return(TRUE); +} + +/* + * cvSensFreeVectors + * + * This routine frees the CVODES vectors allocated in cvSensAllocVectors. + */ + +static void cvSensFreeVectors(CVodeMem cv_mem) +{ + int j, maxord; + + maxord = cv_mem->cv_qmax_allocS; + + N_VDestroyVectorArray(yS, Ns); + N_VDestroyVectorArray(ewtS, Ns); + N_VDestroyVectorArray(acorS, Ns); + N_VDestroyVectorArray(tempvS, Ns); + N_VDestroyVectorArray(ftempS, Ns); + + for (j=0; j<=maxord; j++) N_VDestroyVectorArray(znS[j], Ns); + + free(pbar); pbar = NULL; + free(plist); plist = NULL; + + lrw -= (maxord + 6)*Ns*lrw1 + Ns; + liw -= (maxord + 6)*Ns*liw1 + Ns; + + if (cv_mem->cv_VabstolSMallocDone) { + N_VDestroyVectorArray(VabstolS, Ns); + lrw -= Ns*lrw1; + liw -= Ns*liw1; + } + if (cv_mem->cv_SabstolSMallocDone) { + free(SabstolS); SabstolS = NULL; + lrw -= Ns; + } + cv_mem->cv_VabstolSMallocDone = FALSE; + cv_mem->cv_SabstolSMallocDone = FALSE; +} + +/* + * cvQuadSensAllocVectors + * + * Create (through duplication) N_Vectors used for quadrature sensitivity analysis, + * using the N_Vector 'tmpl' as a template. + */ + +static booleantype cvQuadSensAllocVectors(CVodeMem cv_mem, N_Vector tmpl) +{ + int i, j; + + /* Allocate ftempQ */ + ftempQ = N_VClone(tmpl); + if (ftempQ == NULL) { + return(FALSE); + } + + /* Allocate yQS */ + yQS = N_VCloneVectorArray(Ns, tmpl); + if (yQS == NULL) { + N_VDestroy(ftempQ); + return(FALSE); + } + + /* Allocate ewtQS */ + ewtQS = N_VCloneVectorArray(Ns, tmpl); + if (ewtQS == NULL) { + N_VDestroy(ftempQ); + N_VDestroyVectorArray(yQS, Ns); + return(FALSE); + } + + /* Allocate acorQS */ + acorQS = N_VCloneVectorArray(Ns, tmpl); + if (acorQS == NULL) { + N_VDestroy(ftempQ); + N_VDestroyVectorArray(yQS, Ns); + N_VDestroyVectorArray(ewtQS, Ns); + return(FALSE); + } + + /* Allocate tempvQS */ + tempvQS = N_VCloneVectorArray(Ns, tmpl); + if (tempvQS == NULL) { + N_VDestroy(ftempQ); + N_VDestroyVectorArray(yQS, Ns); + N_VDestroyVectorArray(ewtQS, Ns); + N_VDestroyVectorArray(acorQS, Ns); + return(FALSE); + } + + /* Allocate znQS */ + for (j=0; j<=qmax; j++) { + znQS[j] = N_VCloneVectorArray(Ns, tmpl); + if (znQS[j] == NULL) { + N_VDestroy(ftempQ); + N_VDestroyVectorArray(yQS, Ns); + N_VDestroyVectorArray(ewtQS, Ns); + N_VDestroyVectorArray(acorQS, Ns); + N_VDestroyVectorArray(tempvQS, Ns); + for (i=0; icv_qmax_allocQS = qmax; + + return(TRUE); +} + +/* + * cvQuadSensFreeVectors + * + * This routine frees the CVODES vectors allocated in cvQuadSensAllocVectors. + */ + +static void cvQuadSensFreeVectors(CVodeMem cv_mem) +{ + int j, maxord; + + maxord = cv_mem->cv_qmax_allocQS; + + N_VDestroy(ftempQ); + + N_VDestroyVectorArray(yQS, Ns); + N_VDestroyVectorArray(ewtQS, Ns); + N_VDestroyVectorArray(acorQS, Ns); + N_VDestroyVectorArray(tempvQS, Ns); + + for (j=0; j<=maxord; j++) N_VDestroyVectorArray(znQS[j], Ns); + + lrw -= (maxord + 5)*Ns*lrw1Q; + liw -= (maxord + 5)*Ns*liw1Q; + + if (cv_mem->cv_VabstolQSMallocDone) { + N_VDestroyVectorArray(VabstolQS, Ns); + lrw -= Ns*lrw1Q; + liw -= Ns*liw1Q; + } + if (cv_mem->cv_SabstolQSMallocDone) { + free(SabstolQS); SabstolQS = NULL; + lrw -= Ns; + } + cv_mem->cv_VabstolQSMallocDone = FALSE; + cv_mem->cv_SabstolQSMallocDone = FALSE; + +} + + +/* + * ----------------------------------------------------------------- + * Initial stepsize calculation + * ----------------------------------------------------------------- + */ + +/* + * cvHin + * + * This routine computes a tentative initial step size h0. + * If tout is too close to tn (= t0), then cvHin returns CV_TOO_CLOSE + * and h remains uninitialized. Note that here tout is either the value + * passed to CVode at the first call or the value of tstop (if tstop is + * enabled and it is closer to t0=tn than tout). + * If any RHS function fails unrecoverably, cvHin returns CV_*RHSFUNC_FAIL. + * If any RHS function fails recoverably too many times and recovery is + * not possible, cvHin returns CV_REPTD_*RHSFUNC_ERR. + * Otherwise, cvHin sets h to the chosen value h0 and returns CV_SUCCESS. + * + * The algorithm used seeks to find h0 as a solution of + * (WRMS norm of (h0^2 ydd / 2)) = 1, + * where ydd = estimated second derivative of y. Here, y includes + * all variables considered in the error test. + * + * We start with an initial estimate equal to the geometric mean of the + * lower and upper bounds on the step size. + * + * Loop up to MAX_ITERS times to find h0. + * Stop if new and previous values differ by a factor < 2. + * Stop if hnew/hg > 2 after one iteration, as this probably means + * that the ydd value is bad because of cancellation error. + * + * For each new proposed hg, we allow MAX_ITERS attempts to + * resolve a possible recoverable failure from f() by reducing + * the proposed stepsize by a factor of 0.2. If a legal stepsize + * still cannot be found, fall back on a previous value if possible, + * or else return CV_REPTD_RHSFUNC_ERR. + * + * Finally, we apply a bias (0.5) and verify that h0 is within bounds. + */ + +static int cvHin(CVodeMem cv_mem, realtype tout) +{ + int retval, sign, count1, count2; + realtype tdiff, tdist, tround, hlb, hub; + realtype hg, hgs, hs, hnew, hrat, h0, yddnrm; + booleantype hgOK, hnewOK; + + /* If tout is too close to tn, give up */ + + if ((tdiff = tout-tn) == ZERO) return(CV_TOO_CLOSE); + + sign = (tdiff > ZERO) ? 1 : -1; + tdist = ABS(tdiff); + tround = uround * MAX(ABS(tn), ABS(tout)); + + if (tdist < TWO*tround) return(CV_TOO_CLOSE); + + /* + Set lower and upper bounds on h0, and take geometric mean + as first trial value. + Exit with this value if the bounds cross each other. + */ + + hlb = HLB_FACTOR * tround; + hub = cvUpperBoundH0(cv_mem, tdist); + + hg = RSqrt(hlb*hub); + + if (hub < hlb) { + if (sign == -1) h = -hg; + else h = hg; + return(CV_SUCCESS); + } + + /* Outer loop */ + + hnewOK = FALSE; + hs = hg; /* safeguard against 'uninitialized variable' warning */ + + for(count1 = 1; count1 <= MAX_ITERS; count1++) { + + /* Attempts to estimate ydd */ + + hgOK = FALSE; + + for (count2 = 1; count2 <= MAX_ITERS; count2++) { + hgs = hg*sign; + retval = cvYddNorm(cv_mem, hgs, &yddnrm); + /* If a RHS function failed unrecoverably, give up */ + if (retval < 0) return(retval); + /* If successful, we can use ydd */ + if (retval == CV_SUCCESS) {hgOK = TRUE; break;} + /* A RHS function failed recoverably; cut step size and test it again */ + hg *= POINT2; + } + + /* If a RHS function failed recoverably MAX_ITERS times */ + + if (!hgOK) { + /* Exit if this is the first or second pass. No recovery possible */ + if (count1 <= 2) + if (retval == RHSFUNC_RECVR) return(CV_REPTD_RHSFUNC_ERR); + if (retval == QRHSFUNC_RECVR) return(CV_REPTD_QRHSFUNC_ERR); + if (retval == SRHSFUNC_RECVR) return(CV_REPTD_SRHSFUNC_ERR); + /* We have a fall-back option. The value hs is a previous hnew which + passed through f(). Use it and break */ + hnew = hs; + break; + } + + /* The proposed step size is feasible. Save it. */ + hs = hg; + + /* If the stopping criteria was met, or if this is the last pass, stop */ + if ( (hnewOK) || (count1 == MAX_ITERS)) {hnew = hg; break;} + + /* Propose new step size */ + hnew = (yddnrm*hub*hub > TWO) ? RSqrt(TWO/yddnrm) : RSqrt(hg*hub); + hrat = hnew/hg; + + /* Accept hnew if it does not differ from hg by more than a factor of 2 */ + if ((hrat > HALF) && (hrat < TWO)) { + hnewOK = TRUE; + } + + /* After one pass, if ydd seems to be bad, use fall-back value. */ + if ((count1 > 1) && (hrat > TWO)) { + hnew = hg; + hnewOK = TRUE; + } + + /* Send this value back through f() */ + hg = hnew; + + } + + /* Apply bounds, bias factor, and attach sign */ + + h0 = H_BIAS*hnew; + if (h0 < hlb) h0 = hlb; + if (h0 > hub) h0 = hub; + if (sign == -1) h0 = -h0; + h = h0; + + return(CV_SUCCESS); +} + +/* + * cvUpperBoundH0 + * + * This routine sets an upper bound on abs(h0) based on + * tdist = tn - t0 and the values of y[i]/y'[i]. + */ + +static realtype cvUpperBoundH0(CVodeMem cv_mem, realtype tdist) +{ + realtype hub_inv, hubQ_inv, hubS_inv, hubQS_inv, hub; + N_Vector temp1, temp2; + N_Vector tempQ1, tempQ2; + N_Vector *tempS1; + N_Vector *tempQS1; + int is; + + /* + * Bound based on |y|/|y'| -- allow at most an increase of + * HUB_FACTOR in y0 (based on a forward Euler step). The weight + * factor is used as a safeguard against zero components in y0. + */ + + temp1 = tempv; + temp2 = acor; + + N_VAbs(zn[0], temp2); + efun(zn[0], temp1, e_data); + N_VInv(temp1, temp1); + N_VLinearSum(HUB_FACTOR, temp2, ONE, temp1, temp1); + + N_VAbs(zn[1], temp2); + + N_VDiv(temp2, temp1, temp1); + hub_inv = N_VMaxNorm(temp1); + + /* Bound based on |yQ|/|yQ'| */ + + if (quadr && errconQ) { + + tempQ1 = tempvQ; + tempQ2 = acorQ; + + N_VAbs(znQ[0], tempQ2); + cvQuadEwtSet(cv_mem, znQ[0], tempQ1); + N_VInv(tempQ1, tempQ1); + N_VLinearSum(HUB_FACTOR, tempQ2, ONE, tempQ1, tempQ1); + + N_VAbs(znQ[1], tempQ2); + + N_VDiv(tempQ2, tempQ1, tempQ1); + hubQ_inv = N_VMaxNorm(tempQ1); + + if (hubQ_inv > hub_inv) hub_inv = hubQ_inv; + + } + + /* Bound based on |yS|/|yS'| */ + + if (sensi && errconS) { + + tempS1 = acorS; + cvSensEwtSet(cv_mem, znS[0], tempS1); + + for (is=0; is hub_inv) hub_inv = hubS_inv; + + } + + } + + /* Bound based on |yQS|/|yQS'| */ + + if (quadr_sensi && errconQS) { + + tempQ1 = tempvQ; + tempQ2 = acorQ; + + tempQS1 = acorQS; + cvQuadSensEwtSet(cv_mem, znQS[0], tempQS1); + + for (is=0; is hub_inv) hub_inv = hubQS_inv; + + } + + } + + + /* + * bound based on tdist -- allow at most a step of magnitude + * HUB_FACTOR * tdist + */ + + hub = HUB_FACTOR*tdist; + + /* Use the smaler of the two */ + + if (hub*hub_inv > ONE) hub = ONE/hub_inv; + + return(hub); +} + +/* + * cvYddNorm + * + * This routine computes an estimate of the second derivative of Y + * using a difference quotient, and returns its WRMS norm. + * + * Y contains all variables included in the error test. + */ + +static int cvYddNorm(CVodeMem cv_mem, realtype hg, realtype *yddnrm) +{ + int retval, is; + N_Vector wrk1, wrk2; + + /* y <- h*y'(t) + y(t) */ + + N_VLinearSum(hg, zn[1], ONE, zn[0], y); + + if (sensi && errconS) + for (is=0; is 0) return(RHSFUNC_RECVR); + + if (quadr && errconQ) { + retval = fQ(tn+hg, y, tempvQ, user_data); + nfQe++; + if (retval < 0) return(CV_QRHSFUNC_FAIL); + if (retval > 0) return(QRHSFUNC_RECVR); + } + + if (sensi && errconS) { + wrk1 = ftemp; + wrk2 = acor; + retval = cvSensRhsWrapper(cv_mem, tn+hg, y, tempv, yS, tempvS, wrk1, wrk2); + if (retval < 0) return(CV_SRHSFUNC_FAIL); + if (retval > 0) return(SRHSFUNC_RECVR); + } + + if (quadr_sensi && errconQS) { + wrk1 = ftemp; + wrk2 = acorQ; + retval = fQS(Ns, tn+hg, y, yS, tempvQ, tempvQS, fQS_data, wrk1, wrk2); + + nfQSe++; + if (retval < 0) return(CV_QSRHSFUNC_FAIL); + if (retval > 0) return(QSRHSFUNC_RECVR); + } + + /* Load estimate of ||y''|| into tempv: + * tempv <- (1/h) * f(t+h, h*y'(t)+y(t)) - y'(t) */ + + N_VLinearSum(ONE, tempv, -ONE, zn[1], tempv); + N_VScale(ONE/hg, tempv, tempv); + *yddnrm = N_VWrmsNorm(tempv, ewt); + + if (quadr && errconQ) { + N_VLinearSum(ONE, tempvQ, -ONE, znQ[1], tempvQ); + N_VScale(ONE/hg, tempvQ, tempvQ); + *yddnrm = cvQuadUpdateNorm(cv_mem, *yddnrm, tempvQ, ewtQ); + } + + if (sensi && errconS) { + for (is=0; iscv_user_efun) e_data = user_data; + else e_data = cv_mem; + + /* Load intial error weights */ + ier = efun(zn[0], ewt, e_data); + if (ier != 0) { + if (itol == CV_WF) + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_EWT_FAIL); + else + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_BAD_EWT); + return(CV_ILL_INPUT); + } + + /* Quadrature initial setup */ + + if (quadr && errconQ) { + + /* Did the user specify tolerances? */ + if (itolQ == CV_NN) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_NO_TOLQ); + return(CV_ILL_INPUT); + } + + /* Load ewtQ */ + ier = cvQuadEwtSet(cv_mem, znQ[0], ewtQ); + if (ier != 0) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_BAD_EWTQ); + return(CV_ILL_INPUT); + } + + } + + if (!quadr) errconQ = FALSE; + + /* Forward sensitivity initial setup */ + + if (sensi) { + + /* Did the user specify tolerances? */ + if (itolS == CV_NN) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_NO_TOLS); + return(CV_ILL_INPUT); + } + + /* If using the internal DQ functions, we must have access to the problem parameters */ + if(fSDQ && (p == NULL)) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_NULL_P); + return(CV_ILL_INPUT); + } + + /* Load ewtS */ + ier = cvSensEwtSet(cv_mem, znS[0], ewtS); + if (ier != 0) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_BAD_EWTS); + return(CV_ILL_INPUT); + } + + } + + /* FSA of quadrature variables */ + + if (quadr_sensi) { + + /* If using the internal DQ functions, we must have access to fQ + * (i.e. quadrature integration must be enabled) and to the problem parameters */ + + if (fQSDQ) { + + /* Test if quadratures are defined, so we can use fQ */ + if (!quadr) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_NULL_FQ); + return(CV_ILL_INPUT); + } + + /* Test if we have the problem parameters */ + if(p == NULL) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_NULL_P); + return(CV_ILL_INPUT); + } + + } + + if (errconQS) { + + /* Did the user specify tolerances? */ + if (itolQS == CV_NN) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_NO_TOLQS); + return(CV_ILL_INPUT); + } + + /* If needed, did the user provide quadrature tolerances? */ + if ( (itolQS == CV_EE) && (itolQ == CV_NN) ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_NO_TOLQ); + return(CV_ILL_INPUT); + } + + /* Load ewtQS */ + ier = cvQuadSensEwtSet(cv_mem, znQS[0], ewtQS); + if (ier != 0) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_BAD_EWTQS); + return(CV_ILL_INPUT); + } + + } + + } else { + + errconQS = FALSE; + + } + + /* Check if lsolve function exists (if needed) and call linit function (if it exists) */ + if (iter == CV_NEWTON) { + if (lsolve == NULL) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_LSOLVE_NULL); + return(CV_ILL_INPUT); + } + if (linit != NULL) { + ier = linit(cv_mem); + if (ier != 0) { + cvProcessError(cv_mem, CV_LINIT_FAIL, "CVODES", "CVode", MSGCV_LINIT_FAIL); + return(CV_LINIT_FAIL); + } + } + } + + return(CV_SUCCESS); +} + +/* + * cvEwtSet + * + * This routine is responsible for setting the error weight vector ewt, + * according to tol_type, as follows: + * + * (1) ewt[i] = 1 / (reltol * ABS(ycur[i]) + *abstol), i=0,...,neq-1 + * if tol_type = CV_SS + * (2) ewt[i] = 1 / (reltol * ABS(ycur[i]) + abstol[i]), i=0,...,neq-1 + * if tol_type = CV_SV + * + * cvEwtSet returns 0 if ewt is successfully set as above to a + * positive vector and -1 otherwise. In the latter case, ewt is + * considered undefined. + * + * All the real work is done in the routines cvEwtSetSS, cvEwtSetSV. + */ + +int cvEwtSet(N_Vector ycur, N_Vector weight, void *data) +{ + CVodeMem cv_mem; + int flag = 0; + + /* data points to cv_mem here */ + + cv_mem = (CVodeMem) data; + + switch(itol) { + case CV_SS: + flag = cvEwtSetSS(cv_mem, ycur, weight); + break; + case CV_SV: + flag = cvEwtSetSV(cv_mem, ycur, weight); + break; + } + + return(flag); +} + +/* + * cvEwtSetSS + * + * This routine sets ewt as decribed above in the case tol_type = CV_SS. + * It tests for non-positive components before inverting. cvEwtSetSS + * returns 0 if ewt is successfully set to a positive vector + * and -1 otherwise. In the latter case, ewt is considered undefined. + */ + +static int cvEwtSetSS(CVodeMem cv_mem, N_Vector ycur, N_Vector weight) +{ + N_VAbs(ycur, tempv); + N_VScale(reltol, tempv, tempv); + N_VAddConst(tempv, Sabstol, tempv); + if (N_VMin(tempv) <= ZERO) return(-1); + N_VInv(tempv, weight); + + return(0); +} + +/* + * cvEwtSetSV + * + * This routine sets ewt as decribed above in the case tol_type = CV_SV. + * It tests for non-positive components before inverting. cvEwtSetSV + * returns 0 if ewt is successfully set to a positive vector + * and -1 otherwise. In the latter case, ewt is considered undefined. + */ + +static int cvEwtSetSV(CVodeMem cv_mem, N_Vector ycur, N_Vector weight) +{ + N_VAbs(ycur, tempv); + N_VLinearSum(reltol, tempv, ONE, Vabstol, tempv); + if (N_VMin(tempv) <= ZERO) return(-1); + N_VInv(tempv, weight); + return(0); +} + +/* + * cvQuadEwtSet + * + */ + +static int cvQuadEwtSet(CVodeMem cv_mem, N_Vector qcur, N_Vector weightQ) +{ + int flag=0; + + switch (itolQ) { + case CV_SS: + flag = cvQuadEwtSetSS(cv_mem, qcur, weightQ); + break; + case CV_SV: + flag = cvQuadEwtSetSV(cv_mem, qcur, weightQ); + break; + } + + return(flag); + +} + +/* + * cvQuadEwtSetSS + * + */ + +static int cvQuadEwtSetSS(CVodeMem cv_mem, N_Vector qcur, N_Vector weightQ) +{ + N_VAbs(qcur, tempvQ); + N_VScale(reltolQ, tempvQ, tempvQ); + N_VAddConst(tempvQ, SabstolQ, tempvQ); + if (N_VMin(tempvQ) <= ZERO) return(-1); + N_VInv(tempvQ, weightQ); + + return(0); +} + +/* + * cvQuadEwtSetSV + * + */ + +static int cvQuadEwtSetSV(CVodeMem cv_mem, N_Vector qcur, N_Vector weightQ) +{ + N_VAbs(qcur, tempvQ); + N_VLinearSum(reltolQ, tempvQ, ONE, VabstolQ, tempvQ); + if (N_VMin(tempvQ) <= ZERO) return(-1); + N_VInv(tempvQ, weightQ); + + return(0); +} + +/* + * cvSensEwtSet + * + */ + +static int cvSensEwtSet(CVodeMem cv_mem, N_Vector *yScur, N_Vector *weightS) +{ + int flag=0; + + switch (itolS) { + case CV_EE: + flag = cvSensEwtSetEE(cv_mem, yScur, weightS); + break; + case CV_SS: + flag = cvSensEwtSetSS(cv_mem, yScur, weightS); + break; + case CV_SV: + flag = cvSensEwtSetSV(cv_mem, yScur, weightS); + break; + } + + return(flag); +} + +/* + * cvSensEwtSetEE + * + * In this case, the error weight vector for the i-th sensitivity is set to + * + * ewtS_i = pbar_i * efun(pbar_i*yS_i) + * + * In other words, the scaled sensitivity pbar_i * yS_i has the same error + * weight vector calculation as the solution vector. + * + */ + +static int cvSensEwtSetEE(CVodeMem cv_mem, N_Vector *yScur, N_Vector *weightS) +{ + int is; + N_Vector pyS; + int flag; + + /* Use tempvS[0] as temporary storage for the scaled sensitivity */ + pyS = tempvS[0]; + + for (is=0; is 0) && (hprime != h)) cvAdjustParams(cv_mem); + + /* Looping point for attempts to take a step */ + + saved_t = tn; + nflag = FIRST_CALL; + + loop { + + cvPredict(cv_mem); + cvSet(cv_mem); + + /* ------ Correct state variables ------ */ + + nflag = cvNls(cv_mem, nflag); + kflag = cvHandleNFlag(cv_mem, &nflag, saved_t, &ncf, &ncfn); + + /* Go back in loop if we need to predict again (nflag=PREV_CONV_FAIL) */ + if (kflag == PREDICT_AGAIN) continue; + + /* Return if nonlinear solve failed and recovery not possible. */ + if (kflag != DO_ERROR_TEST) return(kflag); + + /* Perform error test (nflag=CV_SUCCESS) */ + eflag = cvDoErrorTest(cv_mem, &nflag, saved_t, acnrm, &nef, &netf, &dsm); + + /* Go back in loop if we need to predict again (nflag=PREV_ERR_FAIL) */ + if (eflag == TRY_AGAIN) continue; + + /* Return if error test failed and recovery not possible. */ + if (eflag != CV_SUCCESS) return(eflag); + + /* Error test passed (eflag=CV_SUCCESS, nflag=CV_SUCCESS), go on */ + + /* ------ Correct the quadrature variables ------ */ + + if (quadr) { + + ncf = nef = 0; /* reset counters for states */ + + nflag = cvQuadNls(cv_mem); + kflag = cvHandleNFlag(cv_mem, &nflag, saved_t, &ncf, &ncfn); + + if (kflag == PREDICT_AGAIN) continue; + if (kflag != DO_ERROR_TEST) return(kflag); + + /* Error test on quadratures */ + if (errconQ) { + acnrmQ = N_VWrmsNorm(acorQ, ewtQ); + eflag = cvDoErrorTest(cv_mem, &nflag, saved_t, acnrmQ, &nefQ, &netfQ, &dsmQ); + + if (eflag == TRY_AGAIN) continue; + if (eflag != CV_SUCCESS) return(eflag); + + /* Set dsm = max(dsm, dsmQ) to be used in cvPrepareNextStep */ + if (dsmQ > dsm) dsm = dsmQ; + } + + } + + /* ------ Correct the sensitivity variables (STAGGERED or STAGGERED1) ------- */ + + if (do_sensi_stg || do_sensi_stg1) { + + ncf = nef = 0; /* reset counters for states */ + if (quadr) nefQ = 0; /* reset counter for quadratures */ + + /* Evaluate f at converged y, needed for future evaluations of sens. RHS + * If f() fails recoverably, treat it as a convergence failure and + * attempt the step again */ + + retval = f(tn, y, ftemp, user_data); + nfe++; + if (retval < 0) return(CV_RHSFUNC_FAIL); + if (retval > 0) { + nflag = PREV_CONV_FAIL; + continue; + } + + if (do_sensi_stg) { + /* Nonlinear solve for sensitivities (all-at-once) */ + nflag = cvStgrNls(cv_mem); + kflag = cvHandleNFlag(cv_mem, &nflag, saved_t, &ncfS, &ncfnS); + } else { + /* Nonlinear solve for sensitivities (one-by-one) */ + for (is=0; is dsm) dsm = dsmS; + + } + + } + + /* ------ Correct the quadrature sensitivity variables ------ */ + + if (quadr_sensi) { + + /* Reset local convergence and error test failure counters */ + ncf = nef = 0; + if (quadr) nefQ = 0; + if (do_sensi_stg) ncfS = nefS = 0; + if (do_sensi_stg1) { + for (is=0; is dsm) dsm = dsmQS; + } + + + } + + + /* Everything went fine; exit loop */ + break; + + } + + /* Nonlinear system solve and error test were both successful. + Update data, and consider change of step and/or order. */ + + cvCompleteStep(cv_mem); + + cvPrepareNextStep(cv_mem, dsm); + + /* If Stablilty Limit Detection is turned on, call stability limit + detection routine for possible order reduction. */ + + if (sldeton) cvBDFStab(cv_mem); + + etamax = (nst <= SMALL_NST) ? ETAMX2 : ETAMX3; + + /* Finally, we rescale the acor array to be the + estimated local error vector. */ + + N_VScale(tq[2], acor, acor); + + if (quadr) + N_VScale(tq[2], acorQ, acorQ); + + if (sensi) + for (is=0; is xi_0 = 0 + */ + + for (i=0; i <= qmax; i++) l[i] = ZERO; + l[1] = ONE; + hsum = ZERO; + for (j=1; j <= q-2; j++) { + hsum += tau[j]; + xi = hsum / hscale; + for (i=j+1; i >= 1; i--) l[i] = l[i]*xi + l[i-1]; + } + + for (j=1; j <= q-2; j++) l[j+1] = q * (l[j] / (j+1)); + + for (j=2; j < q; j++) + N_VLinearSum(-l[j], zn[q], ONE, zn[j], zn[j]); + + if (quadr) + for (j=2; j < q; j++) + N_VLinearSum(-l[j], znQ[q], ONE, znQ[j], znQ[j]); + + if (sensi) + for (is=0; is 1) { + for (j=1; j < q; j++) { + hsum += tau[j+1]; + xi = hsum / hscale; + prod *= xi; + alpha0 -= ONE / (j+1); + alpha1 += ONE / xi; + for (i=j+2; i >= 2; i--) l[i] = l[i]*xiold + l[i-1]; + xiold = xi; + } + } + A1 = (-alpha0 - alpha1) / prod; + + /* + zn[indx_acor] contains the value Delta_n = y_n - y_n(0) + This value was stored there at the previous successful + step (in cvCompleteStep) + + A1 contains dbar = (1/xi* - 1/xi_q)/prod(xi_j) + */ + + N_VScale(A1, zn[indx_acor], zn[L]); + for (j=2; j <= q; j++) + N_VLinearSum(l[j], zn[L], ONE, zn[j], zn[j]); + + if (quadr) { + N_VScale(A1, znQ[indx_acor], znQ[L]); + for (j=2; j <= q; j++) + N_VLinearSum(l[j], znQ[L], ONE, znQ[j], znQ[j]); + } + + if (sensi) { + for (is=0; is= 2; i--) l[i] = l[i]*xi + l[i-1]; + } + + for (j=2; j < q; j++) + N_VLinearSum(-l[j], zn[q], ONE, zn[j], zn[j]); + + if (quadr) { + for (j=2; j < q; j++) + N_VLinearSum(-l[j], znQ[q], ONE, znQ[j], znQ[j]); + } + + if (sensi) { + for (is=0; is ZERO) tn = tstop; + } + + for (k = 1; k <= q; k++) + for (j = q; j >= k; j--) + N_VLinearSum(ONE, zn[j-1], ONE, zn[j], zn[j-1]); + + if (quadr) { + for (k = 1; k <= q; k++) + for (j = q; j >= k; j--) + N_VLinearSum(ONE, znQ[j-1], ONE, znQ[j], znQ[j-1]); + } + + if (sensi) { + for (is=0; is= k; j--) + N_VLinearSum(ONE, znS[j-1][is], ONE, znS[j][is], znS[j-1][is]); + } + } + + if (quadr_sensi) { + for (is=0; is= k; j--) + N_VLinearSum(ONE, znQS[j-1][is], ONE, znQS[j][is], znQS[j-1][is]); + } + } + +} + +/* + * cvSet + * + * This routine is a high level routine which calls cvSetAdams or + * cvSetBDF to set the polynomial l, the test quantity array tq, + * and the related variables rl1, gamma, and gamrat. + * + * The array tq is loaded with constants used in the control of estimated + * local errors and in the nonlinear convergence test. Specifically, while + * running at order q, the components of tq are as follows: + * tq[1] = a coefficient used to get the est. local error at order q-1 + * tq[2] = a coefficient used to get the est. local error at order q + * tq[3] = a coefficient used to get the est. local error at order q+1 + * tq[4] = constant used in nonlinear iteration convergence test + * tq[5] = coefficient used to get the order q+2 derivative vector used in + * the est. local error at order q+1 + */ + +static void cvSet(CVodeMem cv_mem) +{ + switch(lmm) { + case CV_ADAMS: + cvSetAdams(cv_mem); + break; + case CV_BDF: + cvSetBDF(cv_mem); + break; + } + rl1 = ONE / l[1]; + gamma = h * rl1; + if (nst == 0) gammap = gamma; + gamrat = (nst > 0) ? gamma / gammap : ONE; /* protect x / x != 1.0 */ +} + +/* + * cvSetAdams + * + * This routine handles the computation of l and tq for the + * case lmm == CV_ADAMS. + * + * The components of the array l are the coefficients of a + * polynomial Lambda(x) = l_0 + l_1 x + ... + l_q x^q, given by + * q-1 + * (d/dx) Lambda(x) = c * PRODUCT (1 + x / xi_i) , where + * i=1 + * Lambda(-1) = 0, Lambda(0) = 1, and c is a normalization factor. + * Here xi_i = [t_n - t_(n-i)] / h. + * + * The array tq is set to test quantities used in the convergence + * test, the error test, and the selection of h at a new order. + */ + +static void cvSetAdams(CVodeMem cv_mem) +{ + realtype m[L_MAX], M[3], hsum; + + if (q == 1) { + l[0] = l[1] = tq[1] = tq[5] = ONE; + tq[2] = HALF; + tq[3] = ONE/TWELVE; + tq[4] = nlscoef / tq[2]; /* = 0.1 / tq[2] */ + return; + } + + hsum = cvAdamsStart(cv_mem, m); + + M[0] = cvAltSum(q-1, m, 1); + M[1] = cvAltSum(q-1, m, 2); + + cvAdamsFinish(cv_mem, m, M, hsum); +} + +/* + * cvAdamsStart + * + * This routine generates in m[] the coefficients of the product + * polynomial needed for the Adams l and tq coefficients for q > 1. + */ + +static realtype cvAdamsStart(CVodeMem cv_mem, realtype m[]) +{ + realtype hsum, xi_inv, sum; + int i, j; + + hsum = h; + m[0] = ONE; + for (i=1; i <= q; i++) m[i] = ZERO; + for (j=1; j < q; j++) { + if ((j==q-1) && (qwait == 1)) { + sum = cvAltSum(q-2, m, 2); + tq[1] = q * sum / m[q-2]; + } + xi_inv = h / hsum; + for (i=j; i >= 1; i--) m[i] += m[i-1] * xi_inv; + hsum += tau[j]; + /* The m[i] are coefficients of product(1 to j) (1 + x/xi_i) */ + } + return(hsum); +} + +/* + * cvAdamsFinish + * + * This routine completes the calculation of the Adams l and tq. + */ + +static void cvAdamsFinish(CVodeMem cv_mem, realtype m[], realtype M[], realtype hsum) +{ + int i; + realtype M0_inv, xi, xi_inv; + + M0_inv = ONE / M[0]; + + l[0] = ONE; + for (i=1; i <= q; i++) l[i] = M0_inv * (m[i-1] / i); + xi = hsum / h; + xi_inv = ONE / xi; + + tq[2] = M[1] * M0_inv / xi; + tq[5] = xi / l[q]; + + if (qwait == 1) { + for (i=q; i >= 1; i--) m[i] += m[i-1] * xi_inv; + M[2] = cvAltSum(q, m, 2); + tq[3] = M[2] * M0_inv / L; + } + + tq[4] = nlscoef / tq[2]; +} + +/* + * cvAltSum + * + * cvAltSum returns the value of the alternating sum + * sum (i= 0 ... iend) [ (-1)^i * (a[i] / (i + k)) ]. + * If iend < 0 then cvAltSum returns 0. + * This operation is needed to compute the integral, from -1 to 0, + * of a polynomial x^(k-1) M(x) given the coefficients of M(x). + */ + +static realtype cvAltSum(int iend, realtype a[], int k) +{ + int i, sign; + realtype sum; + + if (iend < 0) return(ZERO); + + sum = ZERO; + sign = 1; + for (i=0; i <= iend; i++) { + sum += sign * (a[i] / (i+k)); + sign = -sign; + } + return(sum); +} + +/* + * cvSetBDF + * + * This routine computes the coefficients l and tq in the case + * lmm == CV_BDF. cvSetBDF calls cvSetTqBDF to set the test + * quantity array tq. + * + * The components of the array l are the coefficients of a + * polynomial Lambda(x) = l_0 + l_1 x + ... + l_q x^q, given by + * q-1 + * Lambda(x) = (1 + x / xi*_q) * PRODUCT (1 + x / xi_i) , where + * i=1 + * xi_i = [t_n - t_(n-i)] / h. + * + * The array tq is set to test quantities used in the convergence + * test, the error test, and the selection of h at a new order. + */ + +static void cvSetBDF(CVodeMem cv_mem) +{ + realtype alpha0, alpha0_hat, xi_inv, xistar_inv, hsum; + int i,j; + + l[0] = l[1] = xi_inv = xistar_inv = ONE; + for (i=2; i <= q; i++) l[i] = ZERO; + alpha0 = alpha0_hat = -ONE; + hsum = h; + if (q > 1) { + for (j=2; j < q; j++) { + hsum += tau[j-1]; + xi_inv = h / hsum; + alpha0 -= ONE / j; + for (i=j; i >= 1; i--) l[i] += l[i-1]*xi_inv; + /* The l[i] are coefficients of product(1 to j) (1 + x/xi_i) */ + } + + /* j = q */ + alpha0 -= ONE / q; + xistar_inv = -l[1] - alpha0; + hsum += tau[q-1]; + xi_inv = h / hsum; + alpha0_hat = -l[1] - xi_inv; + for (i=q; i >= 1; i--) l[i] += l[i-1]*xistar_inv; + } + + cvSetTqBDF(cv_mem, hsum, alpha0, alpha0_hat, xi_inv, xistar_inv); +} + +/* + * cvSetTqBDF + * + * This routine sets the test quantity array tq in the case + * lmm == CV_BDF. + */ + +static void cvSetTqBDF(CVodeMem cv_mem, realtype hsum, realtype alpha0, + realtype alpha0_hat, realtype xi_inv, realtype xistar_inv) +{ + realtype A1, A2, A3, A4, A5, A6; + realtype C, Cpinv, Cppinv; + + A1 = ONE - alpha0_hat + alpha0; + A2 = ONE + q * A1; + tq[2] = ABS(A1 / (alpha0 * A2)); + tq[5] = ABS(A2 * xistar_inv / (l[q] * xi_inv)); + if (qwait == 1) { + C = xistar_inv / l[q]; + A3 = alpha0 + ONE / q; + A4 = alpha0_hat + xi_inv; + Cpinv = (ONE - A4 + A3) / A3; + tq[1] = ABS(C * Cpinv); + hsum += tau[q]; + xi_inv = h / hsum; + A5 = alpha0 - (ONE / (q+1)); + A6 = alpha0_hat - xi_inv; + Cppinv = (ONE - A6 + A5) / A2; + tq[3] = ABS(Cppinv / (xi_inv * (q+2) * A5)); + } + tq[4] = nlscoef / tq[2]; +} + +/* + * ----------------------------------------------------------------- + * Nonlinear solver functions + * ----------------------------------------------------------------- + */ + +/* + * cvNls + * + * This routine attempts to solve the nonlinear system associated + * with a single implicit step of the linear multistep method. + * Depending on iter, it calls cvNlsFunctional or cvNlsNewton + * to do the work. + */ + +static int cvNls(CVodeMem cv_mem, int nflag) +{ + int flag=CV_SUCCESS; + + switch(iter) { + case CV_FUNCTIONAL: + flag = cvNlsFunctional(cv_mem); + break; + case CV_NEWTON: + flag = cvNlsNewton(cv_mem, nflag); + break; + } + + return(flag); + +} + +/* + * cvNlsFunctional + * + * This routine attempts to solve the nonlinear system using + * functional iteration (no matrices involved). + * + * This routine also handles the functional iteration of the + * combined system (states + sensitivities) when sensitivities are + * computed using the CV_SIMULTANEOUS approach. + * + * Possible return values are: + * + * CV_SUCCESS ---> continue with error test + * + * CV_RHSFUNC_FAIL -+ + * CV_SRHSFUNC_FAIL -+-> halt the integration + * + * CONV_FAIL -+ + * RHSFUNC_RECVR |-> predict again or stop if too many + * SRHSFUNC_RECVR -+ + * + */ + +static int cvNlsFunctional(CVodeMem cv_mem) +{ + int m; + realtype del, delS, Del, Delp, dcon; + int retval, is; + booleantype do_sensi_sim; + N_Vector wrk1, wrk2; + + /* Are we computing sensitivities with the CV_SIMULTANEOUS approach? */ + do_sensi_sim = (sensi && (ism==CV_SIMULTANEOUS)); + + /* Initialize counter and evaluate f at predicted y */ + crate = ONE; + m = 0; + + /* Initialize delS and Delp to avoid compiler warning message */ + delS = Delp = ZERO; + + retval = f(tn, zn[0], tempv, user_data); + nfe++; + if (retval < 0) return(CV_RHSFUNC_FAIL); + if (retval > 0) return(RHSFUNC_RECVR); + + if (do_sensi_sim) { + wrk1 = ftemp; + wrk2 = ftempS[0]; + retval = cvSensRhsWrapper(cv_mem, tn, zn[0], tempv, znS[0], tempvS, wrk1, wrk2); + if (retval < 0) return(CV_SRHSFUNC_FAIL); + if (retval > 0) return(SRHSFUNC_RECVR); + } + + /* Initialize correction to zero */ + + N_VConst(ZERO, acor); + if (do_sensi_sim) { + for (is=0; is 0, an estimate of the convergence + rate constant is stored in crate, and used in the test. + + Recall that, even when errconS=FALSE, all variables are used in the + convergence test. Hence, we use Del (and not del). However, acnrm + is used in the error test and thus it has different forms + depending on errconS (and this explains why we have to carry around + del and delS) + */ + + Del = (do_sensi_sim) ? delS : del; + if (m > 0) crate = MAX(CRDOWN * crate, Del / Delp); + dcon = Del * MIN(ONE, crate) / tq[4]; + + if (dcon <= ONE) { + if (m == 0) + if (do_sensi_sim && errconS) acnrm = delS; + else acnrm = del; + else { + acnrm = N_VWrmsNorm(acor, ewt); + if (do_sensi_sim && errconS) + acnrm = cvSensUpdateNorm(cv_mem, acnrm, acorS, ewtS); + } + return(CV_SUCCESS); /* Convergence achieved */ + } + + /* Stop at maxcor iterations or if iter. seems to be diverging */ + + m++; + if ((m==maxcor) || ((m >= 2) && (Del > RDIV * Delp))) return(CONV_FAIL); + + /* Save norm of correction, evaluate f, and loop again */ + + Delp = Del; + + retval = f(tn, y, tempv, user_data); + nfe++; + if (retval < 0) return(CV_RHSFUNC_FAIL); + if (retval > 0) return(RHSFUNC_RECVR); + + if (do_sensi_sim) { + wrk1 = ftemp; + wrk2 = ftempS[0]; + retval = cvSensRhsWrapper(cv_mem, tn, y, tempv, yS, tempvS, wrk1, wrk2); + if (retval < 0) return(CV_SRHSFUNC_FAIL); + if (retval > 0) return(SRHSFUNC_RECVR); + } + + } /* end loop */ + +} + +/* + * cvNlsNewton + * + * This routine handles the Newton iteration. It calls lsetup if + * indicated, calls cvNewtonIteration to perform the iteration, and + * retries a failed attempt at Newton iteration if that is indicated. + * See return values at top of this file. + * + * This routine also handles the Newton iteration of the combined + * system when sensitivities are computed using the CV_SIMULTANEOUS + * approach. Since in that case we use a quasi-Newton on the + * combined system (by approximating the Jacobian matrix by its + * block diagonal) and thus only solve linear systems with + * multiple right hand sides (all sharing the same coefficient + * matrix - whatever iteration matrix we decide on) we set-up + * the linear solver to handle N equations at a time. + * + * Possible return values: + * + * CV_SUCCESS ---> continue with error test + * + * CV_RHSFUNC_FAIL -+ + * CV_LSETUP_FAIL | + * CV_LSOLVE_FAIL |-> halt the integration + * CV_SRHSFUNC_FAIL -+ + * + * CONV_FAIL -+ + * RHSFUNC_RECVR |-> predict again or stop if too many + * SRHSFUNC_RECVR -+ + * + */ + +static int cvNlsNewton(CVodeMem cv_mem, int nflag) +{ + N_Vector vtemp1, vtemp2, vtemp3, wrk1, wrk2; + int convfail, ier; + booleantype callSetup, do_sensi_sim; + int retval, is; + + /* Are we computing sensitivities with the CV_SIMULTANEOUS approach? */ + do_sensi_sim = (sensi && (ism==CV_SIMULTANEOUS)); + + vtemp1 = acor; /* rename acor as vtemp1 for readability */ + vtemp2 = y; /* rename y as vtemp2 for readability */ + vtemp3 = tempv; /* rename tempv as vtemp3 for readability */ + + /* Set flag convfail, input to lsetup for its evaluation decision */ + convfail = ((nflag == FIRST_CALL) || (nflag == PREV_ERR_FAIL)) ? + CV_NO_FAILURES : CV_FAIL_OTHER; + + /* Decide whether or not to call setup routine (if one exists) */ + if (setupNonNull) { + callSetup = (nflag == PREV_CONV_FAIL) || (nflag == PREV_ERR_FAIL) || + (nst == 0) || (nst >= nstlp + MSBP) || (ABS(gamrat-ONE) > DGMAX); + + /* Decide whether to force a call to setup */ + if (forceSetup) { + callSetup = TRUE; + convfail = CV_FAIL_OTHER; + } + + } else { + crate = ONE; + crateS = ONE; /* if NO lsetup all conv. rates are set to ONE */ + callSetup = FALSE; + } + + /* Looping point for the solution of the nonlinear system. + Evaluate f at the predicted y, call lsetup if indicated, and + call cvNewtonIteration for the Newton iteration itself. */ + + loop { + + retval = f(tn, zn[0], ftemp, user_data); + nfe++; + if (retval < 0) return(CV_RHSFUNC_FAIL); + if (retval > 0) return(RHSFUNC_RECVR); + + if (do_sensi_sim) { + wrk1 = tempv; + wrk2 = tempvS[0]; + retval = cvSensRhsWrapper(cv_mem, tn, zn[0], ftemp, znS[0], ftempS, wrk1, wrk2); + if (retval < 0) return(CV_SRHSFUNC_FAIL); + if (retval > 0) return(SRHSFUNC_RECVR); + } + + if (callSetup) { + ier = lsetup(cv_mem, convfail, zn[0], ftemp, &jcur, + vtemp1, vtemp2, vtemp3); + nsetups++; + callSetup = FALSE; + forceSetup = FALSE; + gamrat = ONE; + gammap = gamma; + crate = ONE; + crateS = ONE; /* after lsetup all conv. rates are reset to ONE */ + nstlp = nst; + /* Return if lsetup failed */ + if (ier < 0) return(CV_LSETUP_FAIL); + if (ier > 0) return(CONV_FAIL); + } + + /* Set acor to zero and load prediction into y vector */ + N_VConst(ZERO, acor); + N_VScale(ONE, zn[0], y); + + if (do_sensi_sim) + for (is=0; is 0) { + if ((!jcur) && (setupNonNull)) return(TRY_AGAIN); + else return(CONV_FAIL); + } + + /* Solve the sensitivity linear systems and do the same + tests on the return value of lsolve. */ + + if (do_sensi_sim) { + + for (is=0; is 0) { + if ((!jcur) && (setupNonNull)) return(TRY_AGAIN); + else return(CONV_FAIL); + } + } + } + + /* Get WRMS norm of correction; add correction to acor and y */ + + del = N_VWrmsNorm(b, ewt); + N_VLinearSum(ONE, acor, ONE, b, acor); + N_VLinearSum(ONE, zn[0], ONE, acor, y); + + if (do_sensi_sim) { + delS = cvSensUpdateNorm(cv_mem, del, bS, ewtS); + for (is=0; is 0, an estimate of the convergence + rate constant is stored in crate, and used in the test. */ + + Del = (do_sensi_sim) ? delS : del; + if (m > 0) crate = MAX(CRDOWN * crate, Del/Delp); + dcon = Del * MIN(ONE, crate) / tq[4]; + + if (dcon <= ONE) { + if (m == 0) + if (do_sensi_sim && errconS) acnrm = delS; + else acnrm = del; + else { + acnrm = N_VWrmsNorm(acor, ewt); + if (do_sensi_sim && errconS) + acnrm = cvSensUpdateNorm(cv_mem, acnrm, acorS, ewtS); + } + jcur = FALSE; + return(CV_SUCCESS); /* Convergence achieved */ + } + + mnewt = ++m; + + /* Stop at maxcor iterations or if iter. seems to be diverging. + If still not converged and Jacobian data is not current, + signal to try the solution again */ + if ((m == maxcor) || ((m >= 2) && (Del > RDIV * Delp))) { + if ((!jcur) && (setupNonNull)) return(TRY_AGAIN); + else return(CONV_FAIL); + } + + /* Save norm of correction, evaluate f, and loop again */ + Delp = Del; + retval = f(tn, y, ftemp, user_data); + nfe++; + if (retval < 0) return(CV_RHSFUNC_FAIL); + if (retval > 0) { + if ((!jcur) && (setupNonNull)) return(TRY_AGAIN); + else return(RHSFUNC_RECVR); + } + + if (do_sensi_sim) { + wrk1 = tempv; + wrk2 = tempvS[0]; + retval = cvSensRhsWrapper(cv_mem, tn, y, ftemp, yS, ftempS, wrk1, wrk2); + if (retval < 0) return(CV_SRHSFUNC_FAIL); + if (retval > 0) { + if ((!jcur) && (setupNonNull)) return(TRY_AGAIN); + else return(SRHSFUNC_RECVR); + } + } + + } /* end loop */ + +} + +/* + * cvQuadNls + * + * This routine solves for the quadrature variables at the new step. + * It does not solve a nonlinear system, but rather updates the + * quadrature variables. The name for this function is just for + * uniformity purposes. + * + * Possible return values (interpreted by cvHandleNFlag) + * + * CV_SUCCESS -> continue with error test + * CV_QRHSFUNC_FAIL -> halt the integration + * QRHSFUNC_RECVR -> predict again or stop if too many + * + */ + +static int cvQuadNls(CVodeMem cv_mem) +{ + int retval; + + /* Save quadrature correction in acorQ */ + retval = fQ(tn, y, acorQ, user_data); + nfQe++; + if (retval < 0) return(CV_QRHSFUNC_FAIL); + if (retval > 0) return(QRHSFUNC_RECVR); + + /* If needed, save the value of yQdot = fQ into ftempQ + * for use in evaluating fQS */ + if (quadr_sensi) { + N_VScale(ONE, acorQ, ftempQ); + } + + N_VLinearSum(h, acorQ, -ONE, znQ[1], acorQ); + N_VScale(rl1, acorQ, acorQ); + + /* Apply correction to quadrature variables */ + N_VLinearSum(ONE, znQ[0], ONE, acorQ, yQ); + + return(CV_SUCCESS); +} + +/* + * cvQuadSensNls + * + * This routine solves for the quadrature sensitivity variables + * at the new step. It does not solve a nonlinear system, but + * rather updates the quadrature variables. The name for this + * function is just for uniformity purposes. + * + * Possible return values (interpreted by cvHandleNFlag) + * + * CV_SUCCESS -> continue with error test + * CV_QSRHSFUNC_FAIL -> halt the integration + * QSRHSFUNC_RECVR -> predict again or stop if too many + * + */ + +static int cvQuadSensNls(CVodeMem cv_mem) +{ + int is, retval; + + /* Save quadrature correction in acorQ */ + retval = fQS(Ns, tn, y, yS, ftempQ, acorQS, user_data, tempv, tempvQ); + nfQSe++; + if (retval < 0) return(CV_QSRHSFUNC_FAIL); + if (retval > 0) return(QSRHSFUNC_RECVR); + + + for (is=0; is 0) return(SRHSFUNC_RECVR); + + /* Initialize correction to zero */ + for (is=0; is 0, an estimate of the convergence + rate constant is stored in crateS, and used in the test. + acnrmS contains the norm of the corrections (yS_n-yS_n(0)) and + will be used in the error test (if errconS==TRUE) */ + if (m > 0) crateS = MAX(CRDOWN * crateS, Del / Delp); + dcon = Del * MIN(ONE, crateS) / tq[4]; + + if (dcon <= ONE) { + if (errconS) + acnrmS = (m==0)? Del : cvSensNorm(cv_mem, acorS, ewtS); + return(CV_SUCCESS); /* Convergence achieved */ + } + + /* Stop at maxcor iterations or if iter. seems to be diverging */ + m++; + if ((m==maxcorS) || ((m >= 2) && (Del > RDIV * Delp))) return(CONV_FAIL); + + /* Save norm of correction, evaluate f, and loop again */ + Delp = Del; + + wrk1 = tempv; + wrk2 = ftempS[0]; + retval = cvSensRhsWrapper(cv_mem, tn, y, ftemp, yS, tempvS, wrk1, wrk2); + if (retval < 0) return(CV_SRHSFUNC_FAIL); + if (retval > 0) return(SRHSFUNC_RECVR); + + } /* end loop */ + +} + +/* + * cvStgrNlsNewton + * + * This routine attempts to solve the sensitivity linear systems using + * Newton iteration. It calls cvStgrNlsNewton to perform the actual + * iteration. If the Newton iteration fails with out-of-date Jacobian + * data (ier=TRY_AGAIN), it calls lsetup and retries the Newton iteration. + * This second try is unlikely to happen when using a Krylov linear solver. + * + * Possible return values: + * + * CV_SUCCESS + * + * CV_LSOLVE_FAIL -+ + * CV_LSETUP_FAIL | + * CV_SRHSFUNC_FAIL -+ + * + * CONV_FAIL -+ + * SRHSFUNC_RECVR -+ + */ + +static int cvStgrNlsNewton(CVodeMem cv_mem) +{ + int retval, is; + int convfail, ier; + N_Vector vtemp1, vtemp2, vtemp3, wrk1, wrk2; + + loop { + + /* Set acorS to zero and load prediction into yS vector */ + for (is=0; is 0) return(SRHSFUNC_RECVR); + + /* Do the Newton iteration */ + ier = cvStgrNewtonIteration(cv_mem); + + /* If the solve was successful (ier=CV_SUCCESS) or if an error + that cannot be fixed by a call to lsetup occured + (ier = CV_LSOLVE_FAIL or CONV_FAIL) return */ + if (ier != TRY_AGAIN) return(ier); + + /* There was a convergence failure and the Jacobian-related data + appears not to be current. Call lsetup with convfail=CV_FAIL_BAD_J + and then loop again */ + convfail = CV_FAIL_BAD_J; + + /* Rename some vectors for readibility */ + vtemp1 = tempv; + vtemp2 = yS[0]; + vtemp3 = ftempS[0]; + + /* Call linear solver setup at converged y */ + ier = lsetup(cv_mem, convfail, y, ftemp, &jcur, + vtemp1, vtemp2, vtemp3); + nsetups++; + nsetupsS++; + gamrat = ONE; + gammap = gamma; + crate = ONE; + crateS = ONE; /* after lsetup all conv. rates are reset to ONE */ + nstlp = nst; + + /* Return if lsetup failed */ + if (ier < 0) return(CV_LSETUP_FAIL); + if (ier > 0) return(CONV_FAIL); + + } /* end loop */ + +} + +/* + * cvStgrNewtonIteration + * + * This routine performs the Newton iteration for all sensitivities. + * If the iteration succeeds, it returns the value CV_SUCCESS. + * If not, it may signal the cvStgrNlsNewton routine to call lsetup and + * reattempt the iteration, by returning the value TRY_AGAIN. (In this case, + * cvStgrNlsNewton must set convfail to CV_FAIL_BAD_J before calling setup again). + * Otherwise, this routine returns one of the appropriate values + * CV_LSOLVE_FAIL or CONV_FAIL back to cvStgrNlsNewton. + */ + +static int cvStgrNewtonIteration(CVodeMem cv_mem) +{ + int m, retval; + realtype Del, Delp, dcon; + N_Vector *bS, wrk1, wrk2; + int is; + + m = 0; + + /* Initialize Delp to avoid compiler warning message */ + Delp = ZERO; + + /* ftemp <- f(t_n, y_n) + y <- y_n + ftempS <- fS(t_n, y_n(0), s_n(0)) + acorS <- 0 + yS <- yS_n(0) */ + + loop { + + /* Evaluate the residual of the nonlinear systems */ + for (is=0; is 0) { + if ((!jcur) && (setupNonNull)) return(TRY_AGAIN); + else return(CONV_FAIL); + } + + } + + /* Get norm of correction; add correction to acorS and yS */ + Del = cvSensNorm(cv_mem, bS, ewtS); + for (is=0; is 0, an estimate of the convergence + rate constant is stored in crateS, and used in the test. */ + if (m > 0) crateS = MAX(CRDOWN * crateS, Del/Delp); + dcon = Del * MIN(ONE, crateS) / tq[4]; + if (dcon <= ONE) { + if (errconS) + acnrmS = (m==0) ? Del : cvSensNorm(cv_mem, acorS, ewtS); + jcur = FALSE; + return(CV_SUCCESS); /* Convergence achieved */ + } + + m++; + + /* Stop at maxcor iterations or if iter. seems to be diverging. + If still not converged and Jacobian data is not current, + signal to try the solution again */ + if ((m == maxcorS) || ((m >= 2) && (Del > RDIV * Delp))) { + if ((!jcur) && (setupNonNull)) return(TRY_AGAIN); + else return(CONV_FAIL); + } + + /* Save norm of correction, evaluate fS, and loop again */ + Delp = Del; + + wrk1 = tempv; + wrk2 = tempvS[0]; + retval = cvSensRhsWrapper(cv_mem, tn, y, ftemp, yS, ftempS, wrk1, wrk2); + if (retval < 0) return(CV_SRHSFUNC_FAIL); + if (retval > 0) { + if ((!jcur) && (setupNonNull)) return(TRY_AGAIN); + else return(SRHSFUNC_RECVR); + } + + } /* end loop */ + +} + +/* + * cvStgr1Nls + * + * This is a high-level routine that attempts to solve the i-th + * sensitivity linear system using nonlinear iterations (CV_FUNCTIONAL + * or CV_NEWTON - depending on the value of iter) once the states y_n + * were obtained and passed the error test. + */ + +static int cvStgr1Nls(CVodeMem cv_mem, int is) +{ + int flag=CV_SUCCESS; + + switch(iter) { + case CV_FUNCTIONAL: + flag = cvStgr1NlsFunctional(cv_mem,is); + break; + case CV_NEWTON: + flag = cvStgr1NlsNewton(cv_mem,is); + break; + } + + return(flag); + +} + +/* + * cvStgr1NlsFunctional + * + * This routine attempts to solve the i-th sensitivity linear system + * using functional iteration (no matrices involved). + * + * Possible return values: + * CV_SUCCESS, + * CV_SRHSFUNC_FAIL, + * CONV_FAIL, SRHSFUNC_RECVR + */ + +static int cvStgr1NlsFunctional(CVodeMem cv_mem, int is) +{ + int retval, m; + realtype Del, Delp, dcon; + N_Vector wrk1, wrk2; + + /* Initialize estimated conv. rate and counter */ + crateS = ONE; + m = 0; + + /* Initialize Delp to avoid compiler warning message */ + Delp = ZERO; + + /* Evaluate fS at predicted yS but with converged y (and corresponding f) */ + wrk1 = tempv; + wrk2 = ftempS[0]; + retval = cvSensRhs1Wrapper(cv_mem, tn, y, ftemp, is, znS[0][is], tempvS[is], wrk1, wrk2); + if (retval < 0) return(CV_SRHSFUNC_FAIL); + if (retval > 0) return(SRHSFUNC_RECVR); + + /* Initialize correction to zero */ + N_VConst(ZERO,acorS[is]); + + /* Loop until convergence; accumulate corrections in acorS */ + + loop { + + nniS1[is]++; + + /* Correct yS from last fS value */ + N_VLinearSum(h, tempvS[is], -ONE, znS[1][is], tempvS[is]); + N_VScale(rl1, tempvS[is], tempvS[is]); + N_VLinearSum(ONE, znS[0][is], ONE, tempvS[is], yS[is]); + + /* Get WRMS norm of current correction to use in convergence test */ + N_VLinearSum(ONE, tempvS[is], -ONE, acorS[is], acorS[is]); + Del = N_VWrmsNorm(acorS[is], ewtS[is]); + N_VScale(ONE, tempvS[is], acorS[is]); + + /* Test for convergence. If m > 0, an estimate of the convergence + rate constant is stored in crateS, and used in the test. */ + + if (m > 0) crateS = MAX(CRDOWN * crateS, Del / Delp); + dcon = Del * MIN(ONE, crateS) / tq[4]; + + if (dcon <= ONE) { + return(CV_SUCCESS); /* Convergence achieved */ + } + + /* Stop at maxcor iterations or if iter. seems to be diverging */ + m++; + if ((m==maxcorS) || ((m >= 2) && (Del > RDIV * Delp))) return(CONV_FAIL); + + /* Save norm of correction, evaluate f, and loop again */ + Delp = Del; + + wrk1 = tempv; + wrk2 = ftempS[0]; + + retval = cvSensRhs1Wrapper(cv_mem, tn, y, ftemp, is, yS[is], tempvS[is], wrk1, wrk2); + if (retval < 0) return(CV_SRHSFUNC_FAIL); + if (retval > 0) return(SRHSFUNC_RECVR); + + } /* end loop */ + +} + +/* + * cvStgr1NlsNewton + * + * This routine attempts to solve the i-th sensitivity linear system + * using Newton iteration. It calls cvStgr1NlsNewton to perform the + * actual iteration. If the Newton iteration fails with out-of-date + * Jacobian data (ier=TRY_AGAIN), it calls lsetup and retries the + * Newton iteration. This second try is unlikely to happen when + * using a Krylov linear solver. + * + * Possible return values: + * + * CV_SUCCESS + * + * CV_LSOLVE_FAIL + * CV_LSETUP_FAIL + * CV_SRHSFUNC_FAIL + * + * CONV_FAIL + * SRHSFUNC_RECVR + */ + +static int cvStgr1NlsNewton(CVodeMem cv_mem, int is) +{ + int convfail, retval, ier; + N_Vector vtemp1, vtemp2, vtemp3, wrk1, wrk2; + + loop { + + /* Set acorS to zero and load prediction into yS vector */ + N_VConst(ZERO, acorS[is]); + N_VScale(ONE, znS[0][is], yS[is]); + + /* Evaluate fS at predicted yS but with converged y (and corresponding f) */ + wrk1 = tempv; + wrk2 = tempvS[0]; + retval = cvSensRhs1Wrapper(cv_mem, tn, y, ftemp, is, yS[is], ftempS[is], wrk1, wrk2); + if (retval < 0) return(CV_SRHSFUNC_FAIL); + if (retval > 0) return(SRHSFUNC_RECVR); + + /* Do the Newton iteration */ + ier = cvStgr1NewtonIteration(cv_mem, is); + + /* If the solve was successful (ier=CV_SUCCESS) or if an error + that cannot be fixed by a call to lsetup occured + (ier = CV_LSOLVE_FAIL or CONV_FAIL) return */ + if (ier != TRY_AGAIN) return(ier); + + /* There was a convergence failure and the Jacobian-related data + appears not to be current. Call lsetup with convfail=CV_FAIL_BAD_J + and then loop again */ + convfail = CV_FAIL_BAD_J; + + /* Rename some vectors for readibility */ + vtemp1 = tempv; + vtemp2 = yS[0]; + vtemp3 = ftempS[0]; + + /* Call linear solver setup at converged y */ + ier = lsetup(cv_mem, convfail, y, ftemp, &jcur, + vtemp1, vtemp2, vtemp3); + nsetups++; + nsetupsS++; + gamrat = ONE; + crate = ONE; + crateS = ONE; /* after lsetup all conv. rates are reset to ONE */ + gammap = gamma; + nstlp = nst; + + /* Return if lsetup failed */ + if (ier < 0) return(CV_LSETUP_FAIL); + if (ier > 0) return(CONV_FAIL); + + } /* end loop */ + +} + +/* + * cvStgr1NewtonIteration + * + * This routine performs the Newton iteration for the i-th sensitivity. + * If the iteration succeeds, it returns the value CV_SUCCESS. + * If not, it may signal the cvStgr1NlsNewton routine to call lsetup + * and reattempt the iteration, by returning the value TRY_AGAIN. + * (In this case, cvStgr1NlsNewton must set convfail to CV_FAIL_BAD_J + * before calling setup again). Otherwise, this routine returns one + * of the appropriate values CV_LSOLVE_FAIL or CONV_FAIL back to + * cvStgr1NlsNewton. + */ + +static int cvStgr1NewtonIteration(CVodeMem cv_mem, int is) +{ + int m, retval; + realtype Del, Delp, dcon; + N_Vector *bS, wrk1, wrk2; + + m = 0; + + /* Initialize Delp to avoid compiler warning message */ + Delp = ZERO; + + /* ftemp <- f(t_n, y_n) + y <- y_n + ftempS[is] <- fS(is, t_n, y_n(0), s_n(0)) + acorS[is] <- 0 + yS[is] <- yS_n(0)[is] */ + + loop { + + /* Evaluate the residual of the nonlinear systems */ + N_VLinearSum(rl1, znS[1][is], ONE, acorS[is], tempvS[is]); + N_VLinearSum(gamma, ftempS[is], -ONE, tempvS[is], tempvS[is]); + + /* Call the lsolve function */ + bS = tempvS; + + nniS1[is]++; + + retval = lsolve(cv_mem, bS[is], ewtS[is], y, ftemp); + + /* Unrecoverable error in lsolve */ + if (retval < 0) return(CV_LSOLVE_FAIL); + + /* Recoverable error in lsolve and Jacobian data not current */ + if (retval > 0) { + if ((!jcur) && (setupNonNull)) return(TRY_AGAIN); + else return(CONV_FAIL); + } + + /* Get norm of correction; add correction to acorS and yS */ + Del = N_VWrmsNorm(bS[is], ewtS[is]); + N_VLinearSum(ONE, acorS[is], ONE, bS[is], acorS[is]); + N_VLinearSum(ONE, znS[0][is], ONE, acorS[is], yS[is]); + + /* Test for convergence. If m > 0, an estimate of the convergence + rate constant is stored in crateS, and used in the test. */ + if (m > 0) crateS = MAX(CRDOWN * crateS, Del/Delp); + dcon = Del * MIN(ONE, crateS) / tq[4]; + if (dcon <= ONE) { + jcur = FALSE; + return(CV_SUCCESS); /* Convergence achieved */ + } + + m++; + + /* Stop at maxcor iterations or if iter. seems to be diverging. + If still not converged and Jacobian data is not current, + signal to try the solution again */ + if ((m == maxcorS) || ((m >= 2) && (Del > RDIV * Delp))) { + if ((!jcur) && (setupNonNull)) return(TRY_AGAIN); + else return(CONV_FAIL); + } + + /* Save norm of correction, evaluate fS, and loop again */ + Delp = Del; + + wrk1 = tempv; + wrk2 = tempvS[0]; + retval = cvSensRhs1Wrapper(cv_mem, tn, y, ftemp, is, yS[is], ftempS[is], wrk1, wrk2); + if (retval < 0) return(CV_SRHSFUNC_FAIL); + if (retval > 0) { + if ((!jcur) && (setupNonNull)) return(TRY_AGAIN); + else return(SRHSFUNC_RECVR); + } + + } /* end loop */ + +} + +/* + * cvHandleNFlag + * + * This routine takes action on the return value nflag = *nflagPtr + * returned by cvNls, as follows: + * + * If cvNls succeeded in solving the nonlinear system, then + * cvHandleNFlag returns the constant DO_ERROR_TEST, which tells cvStep + * to perform the error test. + * + * If the nonlinear system was not solved successfully, then ncfn and + * ncf = *ncfPtr are incremented and Nordsieck array zn is restored. + * + * If the solution of the nonlinear system failed due to an + * unrecoverable failure by setup, we return the value CV_LSETUP_FAIL. + * + * If it failed due to an unrecoverable failure in solve, then we return + * the value CV_LSOLVE_FAIL. + * + * If it failed due to an unrecoverable failure in rhs, then we return + * the value CV_RHSFUNC_FAIL. + * + * If it failed due to an unrecoverable failure in quad rhs, then we return + * the value CV_QRHSFUNC_FAIL. + * + * If it failed due to an unrecoverable failure in sensi rhs, then we return + * the value CV_SRHSFUNC_FAIL. + * + * Otherwise, a recoverable failure occurred when solving the + * nonlinear system (cvNls returned nflag = CONV_FAIL, RHSFUNC_RECVR, or + * SRHSFUNC_RECVR). + * In this case, if ncf is now equal to maxncf or |h| = hmin, + * we return the value CV_CONV_FAILURE (if nflag=CONV_FAIL), or + * CV_REPTD_RHSFUNC_ERR (if nflag=RHSFUNC_RECVR), or CV_REPTD_SRHSFUNC_ERR + * (if nflag=SRHSFUNC_RECVR). + * If not, we set *nflagPtr = PREV_CONV_FAIL and return the value + * PREDICT_AGAIN, telling cvStep to reattempt the step. + * + */ + +static int cvHandleNFlag(CVodeMem cv_mem, int *nflagPtr, realtype saved_t, + int *ncfPtr, long int *ncfnPtr) +{ + int nflag; + + nflag = *nflagPtr; + + if (nflag == CV_SUCCESS) return(DO_ERROR_TEST); + + /* The nonlinear soln. failed; increment ncfn and restore zn */ + (*ncfnPtr)++; + cvRestore(cv_mem, saved_t); + + /* Return if lsetup, lsolve, or some rhs failed unrecoverably */ + if (nflag == CV_LSETUP_FAIL) return(CV_LSETUP_FAIL); + if (nflag == CV_LSOLVE_FAIL) return(CV_LSOLVE_FAIL); + if (nflag == CV_RHSFUNC_FAIL) return(CV_RHSFUNC_FAIL); + if (nflag == CV_QRHSFUNC_FAIL) return(CV_QRHSFUNC_FAIL); + if (nflag == CV_SRHSFUNC_FAIL) return(CV_SRHSFUNC_FAIL); + if (nflag == CV_QSRHSFUNC_FAIL) return(CV_QSRHSFUNC_FAIL); + + /* At this point, nflag = CONV_FAIL, RHSFUNC_RECVR, or SRHSFUNC_RECVR; + increment ncf */ + + (*ncfPtr)++; + etamax = ONE; + + /* If we had maxncf failures or |h| = hmin, + return CV_CONV_FAILURE, CV_REPTD_RHSFUNC_ERR, + CV_REPTD_QRHSFUNC_ERR, or CV_REPTD_SRHSFUNC_ERR */ + + if ((ABS(h) <= hmin*ONEPSM) || (*ncfPtr == maxncf)) { + if (nflag == CONV_FAIL) return(CV_CONV_FAILURE); + if (nflag == RHSFUNC_RECVR) return(CV_REPTD_RHSFUNC_ERR); + if (nflag == QRHSFUNC_RECVR) return(CV_REPTD_QRHSFUNC_ERR); + if (nflag == SRHSFUNC_RECVR) return(CV_REPTD_SRHSFUNC_ERR); + if (nflag == QSRHSFUNC_RECVR) return(CV_REPTD_QSRHSFUNC_ERR); + } + + /* Reduce step size; return to reattempt the step */ + + eta = MAX(ETACF, hmin / ABS(h)); + *nflagPtr = PREV_CONV_FAIL; + cvRescale(cv_mem); + + return(PREDICT_AGAIN); +} + +/* + * cvRestore + * + * This routine restores the value of tn to saved_t and undoes the + * prediction. After execution of cvRestore, the Nordsieck array zn has + * the same values as before the call to cvPredict. + */ + +static void cvRestore(CVodeMem cv_mem, realtype saved_t) +{ + int j, k; + int is; + + tn = saved_t; + for (k = 1; k <= q; k++) + for (j = q; j >= k; j--) + N_VLinearSum(ONE, zn[j-1], -ONE, zn[j], zn[j-1]); + + if (quadr) { + for (k = 1; k <= q; k++) + for (j = q; j >= k; j--) + N_VLinearSum(ONE, znQ[j-1], -ONE, znQ[j], znQ[j-1]); + } + + if (sensi) { + for (is=0; is= k; j--) + N_VLinearSum(ONE, znS[j-1][is], -ONE, znS[j][is], znS[j-1][is]); + } + } + + if (quadr_sensi) { + for (is=0; is= k; j--) + N_VLinearSum(ONE, znQS[j-1][is], -ONE, znQS[j][is], znQS[j-1][is]); + } + } +} + +/* + * ----------------------------------------------------------------- + * Error Test + * ----------------------------------------------------------------- + */ + +/* + * cvDoErrorTest + * + * This routine performs the local error test, for the state, quadrature, + * or sensitivity variables. Its last three arguments change depending + * on which variables the error test is to be performed on. + * + * The weighted local error norm dsm is loaded into *dsmPtr, and + * the test dsm ?<= 1 is made. + * + * If the test passes, cvDoErrorTest returns CV_SUCCESS. + * + * If the test fails, we undo the step just taken (call cvRestore) and + * + * - if maxnef error test failures have occurred or if ABS(h) = hmin, + * we return CV_ERR_FAILURE. + * + * - if more than MXNEF1 error test failures have occurred, an order + * reduction is forced. If already at order 1, restart by reloading + * zn from scratch (also znQ and znS if appropriate). + * If f() fails, we return CV_RHSFUNC_FAIL or CV_UNREC_RHSFUNC_ERR; + * if fQ() fails, we return CV_QRHSFUNC_FAIL or CV_UNREC_QRHSFUNC_ERR; + * if cvSensRhsWrapper() fails, we return CV_SRHSFUNC_FAIL or CV_UNREC_SRHSFUNC_ERR; + * (no recovery is possible at this stage). + * + * - otherwise, set *nflagPtr to PREV_ERR_FAIL, and return TRY_AGAIN. + * + */ + +static int cvDoErrorTest(CVodeMem cv_mem, int *nflagPtr, realtype saved_t, + realtype acor_nrm, + int *nefPtr, long int *netfPtr, realtype *dsmPtr) +{ + realtype dsm; + int retval, is; + N_Vector wrk1, wrk2; + + dsm = acor_nrm * tq[2]; + + /* If est. local error norm dsm passes test, return CV_SUCCESS */ + *dsmPtr = dsm; + if (dsm <= ONE) return(CV_SUCCESS); + + /* Test failed; increment counters, set nflag, and restore zn array */ + (*nefPtr)++; + (*netfPtr)++; + *nflagPtr = PREV_ERR_FAIL; + cvRestore(cv_mem, saved_t); + + /* At maxnef failures or |h| = hmin, return CV_ERR_FAILURE */ + if ((ABS(h) <= hmin*ONEPSM) || (*nefPtr == maxnef)) return(CV_ERR_FAILURE); + + /* Set etamax = 1 to prevent step size increase at end of this step */ + etamax = ONE; + + /* Set h ratio eta from dsm, rescale, and return for retry of step */ + if (*nefPtr <= MXNEF1) { + eta = ONE / (RPowerR(BIAS2*dsm,ONE/L) + ADDON); + eta = MAX(ETAMIN, MAX(eta, hmin / ABS(h))); + if (*nefPtr >= SMALL_NEF) eta = MIN(eta, ETAMXF); + cvRescale(cv_mem); + return(TRY_AGAIN); + } + + /* After MXNEF1 failures, force an order reduction and retry step */ + if (q > 1) { + eta = MAX(ETAMIN, hmin / ABS(h)); + cvAdjustOrder(cv_mem,-1); + L = q; + q--; + qwait = L; + cvRescale(cv_mem); + return(TRY_AGAIN); + } + + /* If already at order 1, restart: reload zn, znQ, znS, znQS from scratch */ + eta = MAX(ETAMIN, hmin / ABS(h)); + h *= eta; + next_h = h; + hscale = h; + qwait = LONG_WAIT; + nscon = 0; + + retval = f(tn, zn[0], tempv, user_data); + nfe++; + if (retval < 0) return(CV_RHSFUNC_FAIL); + if (retval > 0) return(CV_UNREC_RHSFUNC_ERR); + + N_VScale(h, tempv, zn[1]); + + if (quadr) { + + retval = fQ(tn, zn[0], tempvQ, user_data); + nfQe++; + if (retval < 0) return(CV_QRHSFUNC_FAIL); + if (retval > 0) return(CV_UNREC_QRHSFUNC_ERR); + + N_VScale(h, tempvQ, znQ[1]); + + } + + if (sensi) { + + wrk1 = ftemp; + wrk2 = ftempS[0]; + + retval = cvSensRhsWrapper(cv_mem, tn, zn[0], tempv, znS[0], tempvS, wrk1, wrk2); + if (retval < 0) return(CV_SRHSFUNC_FAIL); + if (retval > 0) return(CV_UNREC_SRHSFUNC_ERR); + + for (is=0; is 0) return(CV_UNREC_QSRHSFUNC_ERR); + + for (is=0; is= 2; i--) tau[i] = tau[i-1]; + if ((q==1) && (nst > 1)) tau[2] = tau[1]; + tau[1] = h; + + /* Apply correction to column j of zn: l_j * Delta_n */ + + for (j=0; j <= q; j++) + N_VLinearSum(l[j], acor, ONE, zn[j], zn[j]); + + if (quadr) { + for (j=0; j <= q; j++) + N_VLinearSum(l[j], acorQ, ONE, znQ[j], znQ[j]); + } + + if (sensi) { + for (is=0; is 1) { + + ddn = N_VWrmsNorm(zn[q], ewt); + + if ( quadr && errconQ) { + ddn = cvQuadUpdateNorm(cv_mem, ddn, znQ[q], ewtQ); + } + + if ( sensi && errconS ) { + ddn = cvSensUpdateNorm(cv_mem, ddn, znS[q], ewtS); + } + + if ( quadr_sensi && errconQS ) { + ddn = cvQuadSensUpdateNorm(cv_mem, ddn, znQS[q], ewtQS); + } + + ddn = ddn * tq[1]; + + etaqm1 = ONE/(RPowerR(BIAS1*ddn, ONE/q) + ADDON); + + } + + return(etaqm1); +} + +/* + * cvComputeEtaqp1 + * + * This routine computes and returns the value of etaqp1 for a + * possible increase in order by 1. + */ + +static realtype cvComputeEtaqp1(CVodeMem cv_mem) +{ + realtype dup, cquot; + int is; + + etaqp1 = ZERO; + + if (q != qmax) { + + if (saved_tq5 == ZERO) return(etaqp1); + + cquot = (tq[5] / saved_tq5) * RPowerI(h/tau[2], L); + + N_VLinearSum(-cquot, zn[qmax], ONE, acor, tempv); + + dup = N_VWrmsNorm(tempv, ewt); + + if ( quadr && errconQ ) { + N_VLinearSum(-cquot, znQ[qmax], ONE, acorQ, tempvQ); + dup = cvQuadUpdateNorm(cv_mem, dup, tempvQ, ewtQ); + } + + if ( sensi && errconS ) { + for (is=0; is= 3) { + for (k = 1; k <= 3; k++) + for (i = 5; i >= 2; i--) + ssdat[i][k] = ssdat[i-1][k]; + factorial = 1; + for (i = 1; i <= q-1; i++) factorial *= i; + sq = factorial*q*(q+1)*acnrm/MAX(tq[5],TINY); + sqm1 = factorial*q*N_VWrmsNorm(zn[q], ewt); + sqm2 = factorial*N_VWrmsNorm(zn[q-1], ewt); + ssdat[1][1] = sqm2*sqm2; + ssdat[1][2] = sqm1*sqm1; + ssdat[1][3] = sq*sq; + } + + if (qprime >= q) { + + /* If order is 3 or greater, and enough ssdat has been saved, + nscon >= q+5, then call stability limit detection routine. */ + + if ( (q >= 3) && (nscon >= q+5) ) { + ldflag = cvSLdet(cv_mem); + if (ldflag > 3) { + /* A stability limit violation is indicated by + a return flag of 4, 5, or 6. + Reduce new order. */ + qprime = q-1; + eta = etaqm1; + eta = MIN(eta,etamax); + eta = eta/MAX(ONE,ABS(h)*hmax_inv*eta); + hprime = h*eta; + nor = nor + 1; + } + } + } + else { + /* Otherwise, let order increase happen, and + reset stability limit counter, nscon. */ + nscon = 0; + } +} + +/* + * cvSLdet + * + * This routine detects stability limitation using stored scaled + * derivatives data. cvSLdet returns the magnitude of the + * dominate characteristic root, rr. The presents of a stability + * limit is indicated by rr > "something a little less then 1.0", + * and a positive kflag. This routine should only be called if + * order is greater than or equal to 3, and data has been collected + * for 5 time steps. + * + * Returned values: + * kflag = 1 -> Found stable characteristic root, normal matrix case + * kflag = 2 -> Found stable characteristic root, quartic solution + * kflag = 3 -> Found stable characteristic root, quartic solution, + * with Newton correction + * kflag = 4 -> Found stability violation, normal matrix case + * kflag = 5 -> Found stability violation, quartic solution + * kflag = 6 -> Found stability violation, quartic solution, + * with Newton correction + * + * kflag < 0 -> No stability limitation, + * or could not compute limitation. + * + * kflag = -1 -> Min/max ratio of ssdat too small. + * kflag = -2 -> For normal matrix case, vmax > vrrt2*vrrt2 + * kflag = -3 -> For normal matrix case, The three ratios + * are inconsistent. + * kflag = -4 -> Small coefficient prevents elimination of quartics. + * kflag = -5 -> R value from quartics not consistent. + * kflag = -6 -> No corrected root passes test on qk values + * kflag = -7 -> Trouble solving for sigsq. + * kflag = -8 -> Trouble solving for B, or R via B. + * kflag = -9 -> R via sigsq[k] disagrees with R from data. + */ + +static int cvSLdet(CVodeMem cv_mem) +{ + int i, k, j, it, kmin=0, kflag=0; + realtype rat[5][4], rav[4], qkr[4], sigsq[4], smax[4], ssmax[4]; + realtype drr[4], rrc[4],sqmx[4], qjk[4][4], vrat[5], qc[6][4], qco[6][4]; + realtype rr, rrcut, vrrtol, vrrt2, sqtol, rrtol; + realtype smink, smaxk, sumrat, sumrsq, vmin, vmax, drrmax, adrr; + realtype tem, sqmax, saqk, qp, s, sqmaxk, saqj, sqmin; + realtype rsa, rsb, rsc, rsd, rd1a, rd1b, rd1c; + realtype rd2a, rd2b, rd3a, cest1, corr1; + realtype ratp, ratm, qfac1, qfac2, bb, rrb; + + /* The following are cutoffs and tolerances used by this routine */ + + rrcut = RCONST(0.98); + vrrtol = RCONST(1.0e-4); + vrrt2 = RCONST(5.0e-4); + sqtol = RCONST(1.0e-3); + rrtol = RCONST(1.0e-2); + + rr = ZERO; + + /* Index k corresponds to the degree of the interpolating polynomial. */ + /* k = 1 -> q-1 */ + /* k = 2 -> q */ + /* k = 3 -> q+1 */ + + /* Index i is a backward-in-time index, i = 1 -> current time, */ + /* i = 2 -> previous step, etc */ + + /* get maxima, minima, and variances, and form quartic coefficients */ + + for (k=1; k<=3; k++) { + smink = ssdat[1][k]; + smaxk = ZERO; + + for (i=1; i<=5; i++) { + smink = MIN(smink,ssdat[i][k]); + smaxk = MAX(smaxk,ssdat[i][k]); + } + + if (smink < TINY*smaxk) { + kflag = -1; + return(kflag); + } + smax[k] = smaxk; + ssmax[k] = smaxk*smaxk; + + sumrat = ZERO; + sumrsq = ZERO; + for (i=1; i<=4; i++) { + rat[i][k] = ssdat[i][k]/ssdat[i+1][k]; + sumrat = sumrat + rat[i][k]; + sumrsq = sumrsq + rat[i][k]*rat[i][k]; + } + rav[k] = FOURTH*sumrat; + vrat[k] = ABS(FOURTH*sumrsq - rav[k]*rav[k]); + + qc[5][k] = ssdat[1][k]*ssdat[3][k] - ssdat[2][k]*ssdat[2][k]; + qc[4][k] = ssdat[2][k]*ssdat[3][k] - ssdat[1][k]*ssdat[4][k]; + qc[3][k] = ZERO; + qc[2][k] = ssdat[2][k]*ssdat[5][k] - ssdat[3][k]*ssdat[4][k]; + qc[1][k] = ssdat[4][k]*ssdat[4][k] - ssdat[3][k]*ssdat[5][k]; + + for (i=1; i<=5; i++) { + qco[i][k] = qc[i][k]; + } + } /* End of k loop */ + + /* Isolate normal or nearly-normal matrix case. Three quartic will + have common or nearly-common roots in this case. + Return a kflag = 1 if this procedure works. If three root + differ more than vrrt2, return error kflag = -3. */ + + vmin = MIN(vrat[1],MIN(vrat[2],vrat[3])); + vmax = MAX(vrat[1],MAX(vrat[2],vrat[3])); + + if (vmin < vrrtol*vrrtol) { + + if (vmax > vrrt2*vrrt2) { + kflag = -2; + return(kflag); + } else { + rr = (rav[1] + rav[2] + rav[3])/THREE; + drrmax = ZERO; + for (k = 1;k<=3;k++) { + adrr = ABS(rav[k] - rr); + drrmax = MAX(drrmax, adrr); + } + if (drrmax > vrrt2) + kflag = -3; + kflag = 1; + /* can compute charactistic root, drop to next section */ + } + + } else { + + /* use the quartics to get rr. */ + + if (ABS(qco[1][1]) < TINY*ssmax[1]) { + kflag = -4; + return(kflag); + } + + tem = qco[1][2]/qco[1][1]; + for (i=2; i<=5; i++) { + qco[i][2] = qco[i][2] - tem*qco[i][1]; + } + + qco[1][2] = ZERO; + tem = qco[1][3]/qco[1][1]; + for (i=2; i<=5; i++) { + qco[i][3] = qco[i][3] - tem*qco[i][1]; + } + qco[1][3] = ZERO; + + if (ABS(qco[2][2]) < TINY*ssmax[2]) { + kflag = -4; + return(kflag); + } + + tem = qco[2][3]/qco[2][2]; + for (i=3; i<=5; i++) { + qco[i][3] = qco[i][3] - tem*qco[i][2]; + } + + if (ABS(qco[4][3]) < TINY*ssmax[3]) { + kflag = -4; + return(kflag); + } + + rr = -qco[5][3]/qco[4][3]; + + if (rr < TINY || rr > HUN) { + kflag = -5; + return(kflag); + } + + for (k=1; k<=3; k++) { + qkr[k] = qc[5][k] + rr*(qc[4][k] + rr*rr*(qc[2][k] + rr*qc[1][k])); + } + + sqmax = ZERO; + for (k=1; k<=3; k++) { + saqk = ABS(qkr[k])/ssmax[k]; + if (saqk > sqmax) sqmax = saqk; + } + + if (sqmax < sqtol) { + kflag = 2; + + /* can compute charactistic root, drop to "given rr,etc" */ + + } else { + + /* do Newton corrections to improve rr. */ + + for (it=1; it<=3; it++) { + for (k=1; k<=3; k++) { + qp = qc[4][k] + rr*rr*(THREE*qc[2][k] + rr*FOUR*qc[1][k]); + drr[k] = ZERO; + if (ABS(qp) > TINY*ssmax[k]) drr[k] = -qkr[k]/qp; + rrc[k] = rr + drr[k]; + } + + for (k=1; k<=3; k++) { + s = rrc[k]; + sqmaxk = ZERO; + for (j=1; j<=3; j++) { + qjk[j][k] = qc[5][j] + s*(qc[4][j] + + s*s*(qc[2][j] + s*qc[1][j])); + saqj = ABS(qjk[j][k])/ssmax[j]; + if (saqj > sqmaxk) sqmaxk = saqj; + } + sqmx[k] = sqmaxk; + } + + sqmin = sqmx[1] + ONE; + for (k=1; k<=3; k++) { + if (sqmx[k] < sqmin) { + kmin = k; + sqmin = sqmx[k]; + } + } + rr = rrc[kmin]; + + if (sqmin < sqtol) { + kflag = 3; + /* can compute charactistic root */ + /* break out of Newton correction loop and drop to "given rr,etc" */ + break; + } else { + for (j=1; j<=3; j++) { + qkr[j] = qjk[j][kmin]; + } + } + } /* end of Newton correction loop */ + + if (sqmin > sqtol) { + kflag = -6; + return(kflag); + } + } /* end of if (sqmax < sqtol) else */ + } /* end of if (vmin < vrrtol*vrrtol) else, quartics to get rr. */ + + /* given rr, find sigsq[k] and verify rr. */ + /* All positive kflag drop to this section */ + + for (k=1; k<=3; k++) { + rsa = ssdat[1][k]; + rsb = ssdat[2][k]*rr; + rsc = ssdat[3][k]*rr*rr; + rsd = ssdat[4][k]*rr*rr*rr; + rd1a = rsa - rsb; + rd1b = rsb - rsc; + rd1c = rsc - rsd; + rd2a = rd1a - rd1b; + rd2b = rd1b - rd1c; + rd3a = rd2a - rd2b; + + if (ABS(rd1b) < TINY*smax[k]) { + kflag = -7; + return(kflag); + } + + cest1 = -rd3a/rd1b; + if (cest1 < TINY || cest1 > FOUR) { + kflag = -7; + return(kflag); + } + corr1 = (rd2b/cest1)/(rr*rr); + sigsq[k] = ssdat[3][k] + corr1; + } + + if (sigsq[2] < TINY) { + kflag = -8; + return(kflag); + } + + ratp = sigsq[3]/sigsq[2]; + ratm = sigsq[1]/sigsq[2]; + qfac1 = FOURTH*(q*q - ONE); + qfac2 = TWO/(q - ONE); + bb = ratp*ratm - ONE - qfac1*ratp; + tem = ONE - qfac2*bb; + + if (ABS(tem) < TINY) { + kflag = -8; + return(kflag); + } + + rrb = ONE/tem; + + if (ABS(rrb - rr) > rrtol) { + kflag = -9; + return(kflag); + } + + /* Check to see if rr is above cutoff rrcut */ + if (rr > rrcut) { + if (kflag == 1) kflag = 4; + if (kflag == 2) kflag = 5; + if (kflag == 3) kflag = 6; + } + + /* All positive kflag returned at this point */ + + return(kflag); + +} + +/* + * ----------------------------------------------------------------- + * Functions for rootfinding + * ----------------------------------------------------------------- + */ + +/* + * cvRcheck1 + * + * This routine completes the initialization of rootfinding memory + * information, and checks whether g has a zero both at and very near + * the initial point of the IVP. + * + * This routine returns an int equal to: + * CV_RTFUNC_FAIL = -12 if the g function failed, or + * CV_SUCCESS = 0 otherwise. + */ + +static int cvRcheck1(CVodeMem cv_mem) +{ + int i, retval; + realtype smallh, hratio; + booleantype zroot; + + for (i = 0; i < nrtfn; i++) iroots[i] = 0; + tlo = tn; + ttol = (ABS(tn) + ABS(h))*uround*HUN; + + /* Evaluate g at initial t and check for zero values. */ + retval = gfun(tlo, zn[0], glo, user_data); + nge = 1; + if (retval != 0) return(CV_RTFUNC_FAIL); + + zroot = FALSE; + for (i = 0; i < nrtfn; i++) { + if (ABS(glo[i]) == ZERO) { + zroot = TRUE; + gactive[i] = FALSE; + } + } + if (!zroot) return(CV_SUCCESS); + + /* Some g_i is zero at t0; look at g at t0+(small increment). */ + hratio = MAX(ttol/ABS(h), TENTH); + smallh = hratio*h; + tlo += smallh; + N_VLinearSum(ONE, zn[0], hratio, zn[1], y); + retval = gfun(tlo, y, glo, user_data); + nge++; + if (retval != 0) return(CV_RTFUNC_FAIL); + + /* We check now only the components of g which were exactly 0.0 at t0 + * to see if we can 'activate' them. */ + + for (i = 0; i < nrtfn; i++) { + if (!gactive[i] && ABS(glo[i]) != ZERO) { + gactive[i] = TRUE; + } + } + + return(CV_SUCCESS); +} + +/* + * cvRcheck2 + * + * This routine checks for exact zeros of g at the last root found, + * if the last return was a root. It then checks for a close + * pair of zeros (an error condition), and for a new root at a + * nearby point. The left endpoint (tlo) of the search interval + * is adjusted if necessary to assure that all g_i are nonzero + * there, before returning to do a root search in the interval. + * + * On entry, tlo = tretlast is the last value of tret returned by + * CVode. This may be the previous tn, the previous tout value, or + * the last root location. + * + * This routine returns an int equal to: + * CV_RTFUNC_FAIL = -12 if the g function failed, or + * CLOSERT = 3 if a close pair of zeros was found, or + * RTFOUND = 1 if a new zero of g was found near tlo, or + * CV_SUCCESS = 0 otherwise. + */ + +static int cvRcheck2(CVodeMem cv_mem) +{ + int i, retval; + realtype smallh, hratio; + booleantype zroot; + + if (irfnd == 0) return(CV_SUCCESS); + + (void) CVodeGetDky(cv_mem, tlo, 0, y); + retval = gfun(tlo, y, glo, user_data); + nge++; + if (retval != 0) return(CV_RTFUNC_FAIL); + + zroot = FALSE; + for (i = 0; i < nrtfn; i++) iroots[i] = 0; + for (i = 0; i < nrtfn; i++) { + if (!gactive[i]) continue; + if (ABS(glo[i]) == ZERO) { + zroot = TRUE; + iroots[i] = 1; + } + } + if (!zroot) return(CV_SUCCESS); + + /* One or more g_i has a zero at tlo. Check g at tlo+smallh. */ + ttol = (ABS(tn) + ABS(h))*uround*HUN; + smallh = (h > ZERO) ? ttol : -ttol; + tlo += smallh; + if ( (tlo - tn)*h >= ZERO) { + hratio = smallh/h; + N_VLinearSum(ONE, y, hratio, zn[1], y); + } else { + (void) CVodeGetDky(cv_mem, tlo, 0, y); + } + retval = gfun(tlo, y, glo, user_data); + nge++; + if (retval != 0) return(CV_RTFUNC_FAIL); + + zroot = FALSE; + for (i = 0; i < nrtfn; i++) { + if (ABS(glo[i]) == ZERO) { + if (!gactive[i]) continue; + if (iroots[i] == 1) return(CLOSERT); + zroot = TRUE; + iroots[i] = 1; + } + } + if (zroot) return(RTFOUND); + return(CV_SUCCESS); + +} + +/* + * cvRcheck3 + * + * This routine interfaces to cvRootFind to look for a root of g + * between tlo and either tn or tout, whichever comes first. + * Only roots beyond tlo in the direction of integration are sought. + * + * This routine returns an int equal to: + * CV_RTFUNC_FAIL = -12 if the g function failed, or + * RTFOUND = 1 if a root of g was found, or + * CV_SUCCESS = 0 otherwise. + */ + +static int cvRcheck3(CVodeMem cv_mem) +{ + int i, retval, ier; + + /* Set thi = tn or tout, whichever comes first; set y = y(thi). */ + if (taskc == CV_ONE_STEP) { + thi = tn; + N_VScale(ONE, zn[0], y); + } + if (taskc == CV_NORMAL) { + if ( (toutc - tn)*h >= ZERO) { + thi = tn; + N_VScale(ONE, zn[0], y); + } else { + thi = toutc; + (void) CVodeGetDky(cv_mem, thi, 0, y); + } + } + + /* Set ghi = g(thi) and call cvRootFind to search (tlo,thi) for roots. */ + retval = gfun(thi, y, ghi, user_data); + nge++; + if (retval != 0) return(CV_RTFUNC_FAIL); + + ttol = (ABS(tn) + ABS(h))*uround*HUN; + ier = cvRootFind(cv_mem); + if (ier == CV_RTFUNC_FAIL) return(CV_RTFUNC_FAIL); + for(i=0; i 0, search for roots of g_i only if + * g_i is increasing; if rootdir[i] < 0, search for + * roots of g_i only if g_i is decreasing; otherwise + * always search for roots of g_i. + * + * gactive = array specifying whether a component of g should + * or should not be monitored. gactive[i] is initially + * set to TRUE for all i=0,...,nrtfn-1, but it may be + * reset to FALSE if at the first step g[i] is 0.0 + * both at the I.C. and at a small perturbation of them. + * gactive[i] is then set back on TRUE only after the + * corresponding g function moves away from 0.0. + * + * nge = cumulative counter for gfun calls. + * + * ttol = a convergence tolerance for trout. Input only. + * When a root at trout is found, it is located only to + * within a tolerance of ttol. Typically, ttol should + * be set to a value on the order of + * 100 * UROUND * max (ABS(tlo), ABS(thi)) + * where UROUND is the unit roundoff of the machine. + * + * tlo, thi = endpoints of the interval in which roots are sought. + * On input, and must be distinct, but tlo - thi may + * be of either sign. The direction of integration is + * assumed to be from tlo to thi. On return, tlo and thi + * are the endpoints of the final relevant interval. + * + * glo, ghi = arrays of length nrtfn containing the vectors g(tlo) + * and g(thi) respectively. Input and output. On input, + * none of the glo[i] should be zero. + * + * trout = root location, if a root was found, or thi if not. + * Output only. If a root was found other than an exact + * zero of g, trout is the endpoint thi of the final + * interval bracketing the root, with size at most ttol. + * + * grout = array of length nrtfn containing g(trout) on return. + * + * iroots = int array of length nrtfn with root information. + * Output only. If a root was found, iroots indicates + * which components g_i have a root at trout. For + * i = 0, ..., nrtfn-1, iroots[i] = 1 if g_i has a root + * and g_i is increasing, iroots[i] = -1 if g_i has a + * root and g_i is decreasing, and iroots[i] = 0 if g_i + * has no roots or g_i varies in the direction opposite + * to that indicated by rootdir[i]. + * + * This routine returns an int equal to: + * CV_RTFUNC_FAIL = -12 if the g function failed, or + * RTFOUND = 1 if a root of g was found, or + * CV_SUCCESS = 0 otherwise. + */ + +static int cvRootFind(CVodeMem cv_mem) +{ + realtype alpha, tmid, gfrac, maxfrac, fracint, fracsub; + int i, retval, imax, side, sideprev; + booleantype zroot, sgnchg; + + imax = 0; + + /* First check for change in sign in ghi or for a zero in ghi. */ + maxfrac = ZERO; + zroot = FALSE; + sgnchg = FALSE; + for (i = 0; i < nrtfn; i++) { + if(!gactive[i]) continue; + if (ABS(ghi[i]) == ZERO) { + if(rootdir[i]*glo[i] <= ZERO) { + zroot = TRUE; + } + } else { + if ( (glo[i]*ghi[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) { + gfrac = ABS(ghi[i]/(ghi[i] - glo[i])); + if (gfrac > maxfrac) { + sgnchg = TRUE; + maxfrac = gfrac; + imax = i; + } + } + } + } + + /* If no sign change was found, reset trout and grout. Then return + CV_SUCCESS if no zero was found, or set iroots and return RTFOUND. */ + if (!sgnchg) { + trout = thi; + for (i = 0; i < nrtfn; i++) grout[i] = ghi[i]; + if (!zroot) return(CV_SUCCESS); + for (i = 0; i < nrtfn; i++) { + iroots[i] = 0; + if(!gactive[i]) continue; + if (ABS(ghi[i]) == ZERO) iroots[i] = glo[i] > 0 ? -1:1; + } + return(RTFOUND); + } + + /* Initialize alpha to avoid compiler warning */ + alpha = ONE; + + /* A sign change was found. Loop to locate nearest root. */ + + side = 0; sideprev = -1; + loop { /* Looping point */ + + /* Set weight alpha. + On the first two passes, set alpha = 1. Thereafter, reset alpha + according to the side (low vs high) of the subinterval in which + the sign change was found in the previous two passes. + If the sides were opposite, set alpha = 1. + If the sides were the same, then double alpha (if high side), + or halve alpha (if low side). + The next guess tmid is the secant method value if alpha = 1, but + is closer to tlo if alpha < 1, and closer to thi if alpha > 1. */ + + if (sideprev == side) { + alpha = (side == 2) ? alpha*TWO : alpha*HALF; + } else { + alpha = ONE; + } + + /* Set next root approximation tmid and get g(tmid). + If tmid is too close to tlo or thi, adjust it inward, + by a fractional distance that is between 0.1 and 0.5. */ + tmid = thi - (thi - tlo)*ghi[imax]/(ghi[imax] - alpha*glo[imax]); + if (ABS(tmid - tlo) < HALF*ttol) { + fracint = ABS(thi - tlo)/ttol; + fracsub = (fracint > FIVE) ? TENTH : HALF/fracint; + tmid = tlo + fracsub*(thi - tlo); + } + if (ABS(thi - tmid) < HALF*ttol) { + fracint = ABS(thi - tlo)/ttol; + fracsub = (fracint > FIVE) ? TENTH : HALF/fracint; + tmid = thi - fracsub*(thi - tlo); + } + + (void) CVodeGetDky(cv_mem, tmid, 0, y); + retval = gfun(tmid, y, grout, user_data); + nge++; + if (retval != 0) return(CV_RTFUNC_FAIL); + + /* Check to see in which subinterval g changes sign, and reset imax. + Set side = 1 if sign change is on low side, or 2 if on high side. */ + maxfrac = ZERO; + zroot = FALSE; + sgnchg = FALSE; + sideprev = side; + for (i = 0; i < nrtfn; i++) { + if(!gactive[i]) continue; + if (ABS(grout[i]) == ZERO) { + if(rootdir[i]*glo[i] <= ZERO) { + zroot = TRUE; + } + } else { + if ( (glo[i]*grout[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) { + gfrac = ABS(grout[i]/(grout[i] - glo[i])); + if (gfrac > maxfrac) { + sgnchg = TRUE; + maxfrac = gfrac; + imax = i; + } + } + } + } + if (sgnchg) { + /* Sign change found in (tlo,tmid); replace thi with tmid. */ + thi = tmid; + for (i = 0; i < nrtfn; i++) ghi[i] = grout[i]; + side = 1; + /* Stop at root thi if converged; otherwise loop. */ + if (ABS(thi - tlo) <= ttol) break; + continue; /* Return to looping point. */ + } + + if (zroot) { + /* No sign change in (tlo,tmid), but g = 0 at tmid; return root tmid. */ + thi = tmid; + for (i = 0; i < nrtfn; i++) ghi[i] = grout[i]; + break; + } + + /* No sign change in (tlo,tmid), and no zero at tmid. + Sign change must be in (tmid,thi). Replace tlo with tmid. */ + tlo = tmid; + for (i = 0; i < nrtfn; i++) glo[i] = grout[i]; + side = 2; + /* Stop at root thi if converged; otherwise loop back. */ + if (ABS(thi - tlo) <= ttol) break; + + } /* End of root-search loop */ + + /* Reset trout and grout, set iroots, and return RTFOUND. */ + trout = thi; + for (i = 0; i < nrtfn; i++) { + grout[i] = ghi[i]; + iroots[i] = 0; + if(!gactive[i]) continue; + if ( (ABS(ghi[i]) == ZERO) && (rootdir[i]*glo[i] <= ZERO) ) + iroots[i] = glo[i] > 0 ? -1:1; + if ( (glo[i]*ghi[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) + iroots[i] = glo[i] > 0 ? -1:1; + } + return(RTFOUND); +} + +/* + * ----------------------------------------------------------------- + * Functions for combined norms + * ----------------------------------------------------------------- + */ + +/* + * cvQuadUpdateNorm + * + * Updates the norm old_nrm to account for all quadratures. + */ + +static realtype cvQuadUpdateNorm(CVodeMem cv_mem, realtype old_nrm, + N_Vector xQ, N_Vector wQ) +{ + realtype qnrm; + + qnrm = N_VWrmsNorm(xQ, wQ); + if (old_nrm > qnrm) return(old_nrm); + else return(qnrm); +} + +/* + * cvSensNorm + * + * This routine returns the maximum over the weighted root mean + * square norm of xS with weight vectors wS: + * + * max { wrms(xS[0],wS[0]) ... wrms(xS[Ns-1],wS[Ns-1]) } + * + * Called by cvSensUpdateNorm or directly in the CV_STAGGERED approach + * during the NLS solution and before the error test. + */ + +static realtype cvSensNorm(CVodeMem cv_mem, N_Vector *xS, N_Vector *wS) +{ + int is; + realtype nrm, snrm; + + nrm = N_VWrmsNorm(xS[0],wS[0]); + for (is=1; is nrm ) nrm = snrm; + } + + return(nrm); +} + +/* + * cvSensUpdateNorm + * + * Updates the norm old_nrm to account for all sensitivities. + */ + +static realtype cvSensUpdateNorm(CVodeMem cv_mem, realtype old_nrm, + N_Vector *xS, N_Vector *wS) +{ + realtype snrm; + + snrm = cvSensNorm(cv_mem, xS, wS); + if (old_nrm > snrm) return(old_nrm); + else return(snrm); +} + +/* + * cvQuadSensNorm + * + * This routine returns the maximum over the weighted root mean + * square norm of xQS with weight vectors wQS: + * + * max { wrms(xQS[0],wS[0]) ... wrms(xQS[Ns-1],wS[Ns-1]) } + * + * Called by cvQuadSensUpdateNorm. + */ + +static realtype cvQuadSensNorm(CVodeMem cv_mem, N_Vector *xQS, N_Vector *wQS) +{ + int is; + realtype nrm, snrm; + + nrm = N_VWrmsNorm(xQS[0],wQS[0]); + for (is=1; is nrm ) nrm = snrm; + } + + return(nrm); +} + +/* + * cvSensUpdateNorm + * + * Updates the norm old_nrm to account for all quadrature sensitivities. + */ + +static realtype cvQuadSensUpdateNorm(CVodeMem cv_mem, realtype old_nrm, + N_Vector *xQS, N_Vector *wQS) +{ + realtype snrm; + + snrm = cvQuadSensNorm(cv_mem, xQS, wQS); + if (old_nrm > snrm) return(old_nrm); + else return(snrm); +} + +/* + * ----------------------------------------------------------------- + * Wrappers for sensitivity RHS + * ----------------------------------------------------------------- + */ + +/* + * cvSensRhsWrapper + * + * CVSensRhs is a high level routine that returns right hand side + * of sensitivity equations. Depending on the 'ifS' flag, it either + * calls directly the fS routine (ifS=CV_ALLSENS) or (if ifS=CV_ONESENS) + * calls the fS1 routine in a loop over all sensitivities. + * + * CVSensRhs is called: + * (*) by CVode at the first step + * (*) by cvYddNorm if errcon=TRUE + * (*) by cvNlsFunctional, cvNlsNewton, and cvNewtonIteration + * if ism=CV_SIMULTANEOUS + * (*) by cvDoErrorTest when restarting from scratch + * (*) in the corrector loop if ism=CV_STAGGERED + * (*) by cvStgrDoErrorTest when restarting from scratch + * + * The return value is that of the sensitivity RHS function fS, + * + */ + +int cvSensRhsWrapper(CVodeMem cv_mem, realtype time, + N_Vector ycur, N_Vector fcur, + N_Vector *yScur, N_Vector *fScur, + N_Vector temp1, N_Vector temp2) +{ + int retval=0, is; + + if (ifS==CV_ALLSENS) { + retval = fS(Ns, time, ycur, fcur, yScur, fScur, + fS_data, temp1, temp2); + nfSe++; + } else { + for (is=0; iscv_ehfun) +#define eh_data (cv_mem->cv_eh_data) + +void cvProcessError(CVodeMem cv_mem, + int error_code, const char *module, const char *fname, + const char *msgfmt, ...) +{ + va_list ap; + char msg[256]; + + /* Initialize the argument pointer variable + (msgfmt is the last required argument to cvProcessError) */ + + va_start(ap, msgfmt); + + /* Compose the message */ + + vsprintf(msg, msgfmt, ap); + + if (cv_mem == NULL) { /* We write to stderr */ + +#ifndef NO_FPRINTF_OUTPUT + fprintf(stderr, "\n[%s ERROR] %s\n ", module, fname); + fprintf(stderr, msg); + fprintf(stderr, "\n\n"); +#endif + + } else { /* We can call ehfun */ + + /* Call ehfun */ + + ehfun(error_code, module, fname, msg, eh_data); + + } + + /* Finalize argument processing */ + + va_end(ap); + + return; + +} + +/* + * cvErrHandler is the default error handling function. + * It sends the error message to the stream pointed to by cv_errfp + */ + +#define errfp (cv_mem->cv_errfp) + +void cvErrHandler(int error_code, const char *module, + const char *function, char *msg, void *data) +{ + CVodeMem cv_mem; + char err_type[10]; + + /* data points to cv_mem here */ + + cv_mem = (CVodeMem) data; + + if (error_code == CV_WARNING) + sprintf(err_type,"WARNING"); + else + sprintf(err_type,"ERROR"); + +#ifndef NO_FPRINTF_OUTPUT + if (errfp!=NULL) { + fprintf(errfp,"\n[%s %s] %s\n",module,err_type,function); + fprintf(errfp," %s\n\n",msg); + } +#endif + + return; +} diff --git a/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_band.c b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_band.c new file mode 100644 index 0000000..f9a9db2 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_band.c @@ -0,0 +1,458 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.13 $ + * $Date: 2009/02/17 02:42:29 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the CVSBAND linear solver. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include "cvodes_direct_impl.h" +#include "cvodes_impl.h" + +#include + +/* Constants */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) +#define TWO RCONST(2.0) + +/* CVSBAND linit, lsetup, lsolve, and lfree routines */ +static int cvBandInit(CVodeMem cv_mem); +static int cvBandSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, + N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1, + N_Vector vtemp2, N_Vector vtemp3); +static int cvBandSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector ycur, N_Vector fcur); +static void cvBandFree(CVodeMem cv_mem); + +/* CVSBAND lfreeB function */ +static void cvBandFreeB(CVodeBMem cvB_mem); + +/* + * ================================================================ + * + * PART I - forward problems + * + * ================================================================ + */ + + +/* Readability Replacements */ + +#define lmm (cv_mem->cv_lmm) +#define f (cv_mem->cv_f) +#define nst (cv_mem->cv_nst) +#define tn (cv_mem->cv_tn) +#define h (cv_mem->cv_h) +#define gamma (cv_mem->cv_gamma) +#define gammap (cv_mem->cv_gammap) +#define gamrat (cv_mem->cv_gamrat) +#define ewt (cv_mem->cv_ewt) +#define nfe (cv_mem->cv_nfe) +#define linit (cv_mem->cv_linit) +#define lsetup (cv_mem->cv_lsetup) +#define lsolve (cv_mem->cv_lsolve) +#define lfree (cv_mem->cv_lfree) +#define lmem (cv_mem->cv_lmem) +#define vec_tmpl (cv_mem->cv_tempv) +#define setupNonNull (cv_mem->cv_setupNonNull) + +#define mtype (cvdls_mem->d_type) +#define n (cvdls_mem->d_n) +#define jacDQ (cvdls_mem->d_jacDQ) +#define jac (cvdls_mem->d_bjac) +#define M (cvdls_mem->d_M) +#define mu (cvdls_mem->d_mu) +#define ml (cvdls_mem->d_ml) +#define smu (cvdls_mem->d_smu) +#define pivots (cvdls_mem->d_pivots) +#define savedJ (cvdls_mem->d_savedJ) +#define nstlj (cvdls_mem->d_nstlj) +#define nje (cvdls_mem->d_nje) +#define nfeDQ (cvdls_mem->d_nfeDQ) +#define J_data (cvdls_mem->d_J_data) +#define last_flag (cvdls_mem->d_last_flag) + +/* + * ----------------------------------------------------------------- + * CVBand + * ----------------------------------------------------------------- + * This routine initializes the memory record and sets various function + * fields specific to the band linear solver module. CVBand first calls + * the existing lfree routine if this is not NULL. It then sets the + * cv_linit, cv_lsetup, cv_lsolve, and cv_lfree fields in (*cvode_mem) + * to be cvBandInit, cvBandSetup, cvBandSolve, and cvBandFree, + * respectively. It allocates memory for a structure of type + * CVDlsMemRec and sets the cv_lmem field in (*cvode_mem) to the + * address of this structure. It sets setupNonNull in (*cvode_mem) to be + * TRUE, b_mu to be mupper, b_ml to be mlower, and the b_jac field to be + * CVBandDQJac. + * Finally, it allocates memory for M, savedJ, and pivot. The CVBand + * return value is SUCCESS = 0, LMEM_FAIL = -1, or LIN_ILL_INPUT = -2. + * + * NOTE: The band linear solver assumes a serial implementation + * of the NVECTOR package. Therefore, CVBand will first + * test for compatible a compatible N_Vector internal + * representation by checking that the function + * N_VGetArrayPointer exists. + * ----------------------------------------------------------------- + */ + +int CVBand(void *cvode_mem, int N, int mupper, int mlower) +{ + CVodeMem cv_mem; + CVDlsMem cvdls_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVDLS_MEM_NULL, "CVSBAND", "CVBand", MSGD_CVMEM_NULL); + return(CVDLS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Test if the NVECTOR package is compatible with the BAND solver */ + if (vec_tmpl->ops->nvgetarraypointer == NULL) { + cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSBAND", "CVBand", MSGD_BAD_NVECTOR); + return(CVDLS_ILL_INPUT); + } + + if (lfree != NULL) lfree(cv_mem); + + /* Set four main function fields in cv_mem */ + linit = cvBandInit; + lsetup = cvBandSetup; + lsolve = cvBandSolve; + lfree = cvBandFree; + + /* Get memory for CVDlsMemRec */ + cvdls_mem = NULL; + cvdls_mem = (CVDlsMem) malloc(sizeof(struct CVDlsMemRec)); + if (cvdls_mem == NULL) { + cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSBAND", "CVBand", MSGD_MEM_FAIL); + return(CVDLS_MEM_FAIL); + } + + /* Set matrix type */ + mtype = SUNDIALS_BAND; + + /* Initialize Jacobian-related data */ + jacDQ = TRUE; + jac = NULL; + J_data = NULL; + + last_flag = CVDLS_SUCCESS; + + setupNonNull = TRUE; + + /* Load problem dimension */ + n = N; + + /* Load half-bandwiths in cvdls_mem */ + ml = mlower; + mu = mupper; + + /* Test ml and mu for legality */ + if ((ml < 0) || (mu < 0) || (ml >= N) || (mu >= N)) { + cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSBAND", "CVBand", MSGD_BAD_SIZES); + return(CVDLS_ILL_INPUT); + } + + /* Set extended upper half-bandwith for M (required for pivoting) */ + smu = MIN(N-1, mu + ml); + + /* Allocate memory for M, savedJ, and pivot arrays */ + M = NULL; + M = NewBandMat(N, mu, ml, smu); + if (M == NULL) { + cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSBAND", "CVBand", MSGD_MEM_FAIL); + free(cvdls_mem); cvdls_mem = NULL; + return(CVDLS_MEM_FAIL); + } + savedJ = NULL; + savedJ = NewBandMat(N, mu, ml, mu); + if (savedJ == NULL) { + cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSBAND", "CVBand", MSGD_MEM_FAIL); + DestroyMat(M); + free(cvdls_mem); cvdls_mem = NULL; + return(CVDLS_MEM_FAIL); + } + pivots = NULL; + pivots = NewIntArray(N); + if (pivots == NULL) { + cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSBAND", "CVBand", MSGD_MEM_FAIL); + DestroyMat(M); + DestroyMat(savedJ); + free(cvdls_mem); cvdls_mem = NULL; + return(CVDLS_MEM_FAIL); + } + + /* Attach linear solver memory to integrator memory */ + lmem = cvdls_mem; + + return(CVDLS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * cvBandInit + * ----------------------------------------------------------------- + * This routine does remaining initializations specific to the band + * linear solver. + * ----------------------------------------------------------------- + */ + +static int cvBandInit(CVodeMem cv_mem) +{ + CVDlsMem cvdls_mem; + + cvdls_mem = (CVDlsMem) lmem; + + nje = 0; + nfeDQ = 0; + nstlj = 0; + + /* Set Jacobian function and data, depending on jacDQ */ + if (jacDQ) { + jac = cvDlsBandDQJac; + J_data = cv_mem; + } else { + J_data = cv_mem->cv_user_data; + } + + last_flag = CVDLS_SUCCESS; + return(0); +} + +/* + * ----------------------------------------------------------------- + * cvBandSetup + * ----------------------------------------------------------------- + * This routine does the setup operations for the band linear solver. + * It makes a decision whether or not to call the Jacobian evaluation + * routine based on various state variables, and if not it uses the + * saved copy. In any case, it constructs the Newton matrix + * M = I - gamma*J, updates counters, and calls the band LU + * factorization routine. + * ----------------------------------------------------------------- + */ + +static int cvBandSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, + N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1, + N_Vector vtemp2, N_Vector vtemp3) +{ + CVDlsMem cvdls_mem; + booleantype jbad, jok; + realtype dgamma; + int ier, retval; + + cvdls_mem = (CVDlsMem) lmem; + + /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */ + + dgamma = ABS((gamma/gammap) - ONE); + jbad = (nst == 0) || (nst > nstlj + CVD_MSBJ) || + ((convfail == CV_FAIL_BAD_J) && (dgamma < CVD_DGMAX)) || + (convfail == CV_FAIL_OTHER); + jok = !jbad; + + if (jok) { + + /* If jok = TRUE, use saved copy of J */ + *jcurPtr = FALSE; + BandCopy(savedJ, M, mu, ml); + + } else { + + /* If jok = FALSE, call jac routine for new J value */ + nje++; + nstlj = nst; + *jcurPtr = TRUE; + SetToZero(M); + + retval = jac(n, mu, ml, tn, ypred, fpred, M, J_data, vtemp1, vtemp2, vtemp3); + if (retval < 0) { + cvProcessError(cv_mem, CVDLS_JACFUNC_UNRECVR, "CVSBAND", "cvBandSetup", MSGD_JACFUNC_FAILED); + last_flag = CVDLS_JACFUNC_UNRECVR; + return(-1); + } + if (retval > 0) { + last_flag = CVDLS_JACFUNC_RECVR; + return(1); + } + + BandCopy(M, savedJ, mu, ml); + + } + + /* Scale and add I to get M = I - gamma*J */ + BandScale(-gamma, M); + AddIdentity(M); + + /* Do LU factorization of M */ + ier = BandGBTRF(M, pivots); + + /* Return 0 if the LU was complete; otherwise return 1 */ + if (ier > 0) { + last_flag = ier; + return(1); + } + last_flag = CVDLS_SUCCESS; + return(0); +} + +/* + * ----------------------------------------------------------------- + * cvBandSolve + * ----------------------------------------------------------------- + * This routine handles the solve operation for the band linear solver + * by calling the band backsolve routine. The return value is 0. + * ----------------------------------------------------------------- + */ + +static int cvBandSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector ycur, N_Vector fcur) +{ + CVDlsMem cvdls_mem; + realtype *bd; + + cvdls_mem = (CVDlsMem) lmem; + + bd = N_VGetArrayPointer(b); + + BandGBTRS(M, pivots, bd); + + /* If CV_BDF, scale the correction to account for change in gamma */ + if ((lmm == CV_BDF) && (gamrat != ONE)) { + N_VScale(TWO/(ONE + gamrat), b, b); + } + + last_flag = CVDLS_SUCCESS; + return(0); +} + +/* + * ----------------------------------------------------------------- + * cvBandFree + * ----------------------------------------------------------------- + * This routine frees memory specific to the band linear solver. + * ----------------------------------------------------------------- + */ + +static void cvBandFree(CVodeMem cv_mem) +{ + CVDlsMem cvdls_mem; + + cvdls_mem = (CVDlsMem) lmem; + + DestroyMat(M); + DestroyMat(savedJ); + DestroyArray(pivots); + free(cvdls_mem); cvdls_mem = NULL; +} + +/* + * ================================================================ + * + * PART II - backward problems + * + * ================================================================ + */ + +/* + * CVBandB is a wraper around CVBand. It attaches the CVSBAND linear solver + * to the backward problem memory block. + */ + +int CVBandB(void *cvode_mem, int which, + int nB, int mupperB, int mlowerB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + CVDlsMemB cvdlsB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVDLS_MEM_NULL, "CVSBAND", "CVBandB", MSGD_CVMEM_NULL); + return(CVDLS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CVDLS_NO_ADJ, "CVSBAND", "CVBandB", MSGD_NO_ADJ); + return(CVDLS_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= ca_mem->ca_nbckpbs ) { + cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSBAND", "CVBandB", MSGCV_BAD_WHICH); + return(CVDLS_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + /* Get memory for CVDlsMemRecB */ + cvdlsB_mem = (CVDlsMemB) malloc(sizeof(struct CVDlsMemRecB)); + if (cvdlsB_mem == NULL) { + cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSBAND", "CVBandB", MSGD_MEM_FAIL); + return(CVDLS_MEM_FAIL); + } + + /* set matrix type */ + cvdlsB_mem->d_typeB = SUNDIALS_BAND; + + /* initialize Jacobian function */ + cvdlsB_mem->d_bjacB = NULL; + + /* attach lmemB and lfreeB */ + cvB_mem->cv_lmem = cvdlsB_mem; + cvB_mem->cv_lfree = cvBandFreeB; + + flag = CVBand(cvodeB_mem, nB, mupperB, mlowerB); + + if (flag != CVDLS_SUCCESS) { + free(cvdlsB_mem); + cvdlsB_mem = NULL; + } + + return(flag); +} + +/* + * cvBandFreeB frees the memory associated with the CVSBAND linear + * solver for backward integration. + */ + +static void cvBandFreeB(CVodeBMem cvB_mem) +{ + CVDlsMemB cvdlsB_mem; + + cvdlsB_mem = (CVDlsMemB) (cvB_mem->cv_lmem); + + free(cvdlsB_mem); +} + diff --git a/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_bandpre.c b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_bandpre.c new file mode 100644 index 0000000..eb67265 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_bandpre.c @@ -0,0 +1,544 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.10 $ + * $Date: 2009/02/17 02:42:29 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This file contains implementations of the banded difference + * quotient Jacobian-based preconditioner and solver routines for + * use with the CVSPILS linear solvers. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "cvodes_impl.h" +#include "cvodes_bandpre_impl.h" +#include "cvodes_spils_impl.h" + +#include +#include +#include + +#include + +#define MIN_INC_MULT RCONST(1000.0) +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +/* Prototypes of cvBandPrecSetup and cvBandPrecSolve */ + +static int cvBandPrecSetup(realtype t, N_Vector y, N_Vector fy, + booleantype jok, booleantype *jcurPtr, + realtype gamma, void *bp_data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +static int cvBandPrecSolve(realtype t, N_Vector y, N_Vector fy, + N_Vector r, N_Vector z, + realtype gamma, realtype delta, + int lr, void *bp_data, N_Vector tmp); + +/* Prototype for cvBandPrecFree */ + +static void cvBandPrecFree(CVodeMem cv_mem); + +/* Prototype for difference quotient Jacobian calculation routine */ + +static int cvBandPrecDQJac(CVBandPrecData pdata, + realtype t, N_Vector y, N_Vector fy, + N_Vector ftemp, N_Vector ytemp); + +/* + * ================================================================ + * + * PART I - forward problems + * + * ================================================================ + */ + +/* Redability replacements */ + +#define vec_tmpl (cv_mem->cv_tempv) + +/* + * ----------------------------------------------------------------- + * Initialization, Free, and Get Functions + * NOTE: The band linear solver assumes a serial implementation + * of the NVECTOR package. Therefore, CVBandPrecInit will + * first test for a compatible N_Vector internal representation + * by checking that the function N_VGetArrayPointer exists. + * ----------------------------------------------------------------- + */ +int CVBandPrecInit(void *cvode_mem, int N, int mu, int ml) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + CVBandPrecData pdata; + int mup, mlp, storagemu; + int flag; + + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Test if one of the SPILS linear solvers has been attached */ + if (cv_mem->cv_lmem == NULL) { + cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBANDPRE", "CVBandPrecInit", MSGBP_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem; + + /* Test if the NVECTOR package is compatible with the BAND preconditioner */ + if(vec_tmpl->ops->nvgetarraypointer == NULL) { + cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVBANDPRE", "CVBandPrecInit", MSGBP_BAD_NVECTOR); + return(CVSPILS_ILL_INPUT); + } + + pdata = NULL; + pdata = (CVBandPrecData) malloc(sizeof *pdata); /* Allocate data memory */ + if (pdata == NULL) { + cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_FAIL); + return(CVSPILS_MEM_FAIL); + } + + /* Load pointers and bandwidths into pdata block. */ + pdata->cvode_mem = cvode_mem; + pdata->N = N; + pdata->mu = mup = MIN(N-1, MAX(0,mu)); + pdata->ml = mlp = MIN(N-1, MAX(0,ml)); + + /* Initialize nfeBP counter */ + pdata->nfeBP = 0; + + /* Allocate memory for saved banded Jacobian approximation. */ + pdata->savedJ = NULL; + pdata->savedJ = NewBandMat(N, mup, mlp, mup); + if (pdata->savedJ == NULL) { + free(pdata); pdata = NULL; + cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_FAIL); + return(CVSPILS_MEM_FAIL); + } + + + /* Allocate memory for banded preconditioner. */ + storagemu = MIN(N-1, mup+mlp); + pdata->savedP = NULL; + pdata->savedP = NewBandMat(N, mup, mlp, storagemu); + if (pdata->savedP == NULL) { + DestroyMat(pdata->savedJ); + free(pdata); pdata = NULL; + cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_FAIL); + return(CVSPILS_MEM_FAIL); + } + + /* Allocate memory for pivot array. */ + pdata->pivots = NULL; + pdata->pivots = NewIntArray(N); + if (pdata->savedJ == NULL) { + DestroyMat(pdata->savedP); + DestroyMat(pdata->savedJ); + free(pdata); pdata = NULL; + cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_FAIL); + return(CVSPILS_MEM_FAIL); + } + + /* Overwrite the P_data field in the SPILS memory */ + cvspils_mem->s_P_data = pdata; + + /* Attach the pfree function */ + cvspils_mem->s_pfree = cvBandPrecFree; + + /* Attach preconditioner solve and setup functions */ + flag = CVSpilsSetPreconditioner(cvode_mem, cvBandPrecSetup, cvBandPrecSolve); + + return(flag); +} + +int CVBandPrecGetWorkSpace(void *cvode_mem, long int *lenrwBP, long int *leniwBP) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + CVBandPrecData pdata; + int N, ml, mu, smu; + + + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBANDPRE", "CVBandPrecGetWorkSpace", MSGBP_MEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (cv_mem->cv_lmem == NULL) { + cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBANDPRE", "CVBandPrecGetWorkSpace", MSGBP_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem; + + if (cvspils_mem->s_P_data == NULL) { + cvProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVBANDPRE", "CVBandPrecGetWorkSpace", MSGBP_PMEM_NULL); + return(CVSPILS_PMEM_NULL); + } + pdata = (CVBandPrecData) cvspils_mem->s_P_data; + + N = pdata->N; + mu = pdata->mu; + ml = pdata->ml; + smu = MIN( N-1, mu + ml); + + *leniwBP = pdata->N; + *lenrwBP = N * ( 2*ml + smu + mu + 2 ); + + return(CVSPILS_SUCCESS); +} + +int CVBandPrecGetNumRhsEvals(void *cvode_mem, long int *nfevalsBP) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + CVBandPrecData pdata; + + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBANDPRE", "CVBandPrecGetNumRhsEvals", MSGBP_MEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (cv_mem->cv_lmem == NULL) { + cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBANDPRE", "CVBandPrecGetNumRhsEvals", MSGBP_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem; + + if (cvspils_mem->s_P_data == NULL) { + cvProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVBANDPRE", "CVBandPrecGetNumRhsEvals", MSGBP_PMEM_NULL); + return(CVSPILS_PMEM_NULL); + } + pdata = (CVBandPrecData) cvspils_mem->s_P_data; + + *nfevalsBP = pdata->nfeBP; + + return(CVSPILS_SUCCESS); +} + +/* Readability Replacements */ + +#define N (pdata->N) +#define mu (pdata->mu) +#define ml (pdata->ml) +#define pivots (pdata->pivots) +#define savedJ (pdata->savedJ) +#define savedP (pdata->savedP) +#define nfeBP (pdata->nfeBP) + +/* + * ----------------------------------------------------------------- + * cvBandPrecSetup + * ----------------------------------------------------------------- + * Together cvBandPrecSetup and cvBandPrecSolve use a banded + * difference quotient Jacobian to create a preconditioner. + * cvBandPrecSetup calculates a new J, if necessary, then + * calculates P = I - gamma*J, and does an LU factorization of P. + * + * The parameters of cvBandPrecSetup are as follows: + * + * t is the current value of the independent variable. + * + * y is the current value of the dependent variable vector, + * namely the predicted value of y(t). + * + * fy is the vector f(t,y). + * + * jok is an input flag indicating whether Jacobian-related + * data needs to be recomputed, as follows: + * jok == FALSE means recompute Jacobian-related data + * from scratch. + * jok == TRUE means that Jacobian data from the + * previous PrecSetup call will be reused + * (with the current value of gamma). + * A cvBandPrecSetup call with jok == TRUE should only + * occur after a call with jok == FALSE. + * + * *jcurPtr is a pointer to an output integer flag which is + * set by CVBandPrecond as follows: + * *jcurPtr = TRUE if Jacobian data was recomputed. + * *jcurPtr = FALSE if Jacobian data was not recomputed, + * but saved data was reused. + * + * gamma is the scalar appearing in the Newton matrix. + * + * bp_data is a pointer to preconditoner data (set by CVBandPrecInit) + * + * tmp1, tmp2, and tmp3 are pointers to memory allocated + * for vectors of length N for work space. This + * routine uses only tmp1 and tmp2. + * + * The value to be returned by the cvBandPrecSetup function is + * 0 if successful, or + * 1 if the band factorization failed. + * ----------------------------------------------------------------- + */ + +static int cvBandPrecSetup(realtype t, N_Vector y, N_Vector fy, + booleantype jok, booleantype *jcurPtr, + realtype gamma, void *bp_data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + CVBandPrecData pdata; + CVodeMem cv_mem; + int retval; + + /* Assume matrix and pivots have already been allocated. */ + pdata = (CVBandPrecData) bp_data; + + cv_mem = (CVodeMem) pdata->cvode_mem; + + if (jok) { + + /* If jok = TRUE, use saved copy of J. */ + *jcurPtr = FALSE; + BandCopy(savedJ, savedP, mu, ml); + + } else { + + /* If jok = FALSE, call cvBandPrecDQJac for new J value. */ + *jcurPtr = TRUE; + SetToZero(savedJ); + + retval = cvBandPrecDQJac(pdata, t, y, fy, tmp1, tmp2); + if (retval < 0) { + cvProcessError(cv_mem, -1, "CVBANDPRE", "cvBandPrecSetup", MSGBP_RHSFUNC_FAILED); + return(-1); + } + if (retval > 0) { + return(1); + } + + BandCopy(savedJ, savedP, mu, ml); + + } + + /* Scale and add I to get savedP = I - gamma*J. */ + BandScale(-gamma, savedP); + AddIdentity(savedP); + + /* Do LU factorization of matrix. */ + retval = BandGBTRF(savedP, pivots); + + /* Return 0 if the LU was complete; otherwise return 1. */ + if (retval > 0) return(1); + return(0); +} + +/* + * ----------------------------------------------------------------- + * cvBandPrecSolve + * ----------------------------------------------------------------- + * cvBandPrecSolve solves a linear system P z = r, where P is the + * matrix computed by CVBandPrecond. + * + * The parameters of cvBandPrecSolve used here are as follows: + * + * r is the right-hand side vector of the linear system. + * + * bp_data is a pointer to preconditoner data (set by CVBandPrecInit) + * + * z is the output vector computed by cvBandPrecSolve. + * + * The value returned by the cvBandPrecSolve function is always 0, + * indicating success. + * ----------------------------------------------------------------- + */ + +static int cvBandPrecSolve(realtype t, N_Vector y, N_Vector fy, + N_Vector r, N_Vector z, + realtype gamma, realtype delta, + int lr, void *bp_data, N_Vector tmp) +{ + CVBandPrecData pdata; + realtype *zd; + + /* Assume matrix and pivots have already been allocated. */ + pdata = (CVBandPrecData) bp_data; + + /* Copy r to z. */ + N_VScale(ONE, r, z); + + /* Do band backsolve on the vector z. */ + zd = N_VGetArrayPointer(z); + + BandGBTRS(savedP, pivots, zd); + + return(0); +} + + +static void cvBandPrecFree(CVodeMem cv_mem) +{ + CVSpilsMem cvspils_mem; + CVBandPrecData pdata; + + if (cv_mem->cv_lmem == NULL) return; + cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem; + + if (cvspils_mem->s_P_data == NULL) return; + pdata = (CVBandPrecData) cvspils_mem->s_P_data; + + DestroyMat(savedJ); + DestroyMat(savedP); + DestroyArray(pivots); + + free(pdata); + pdata = NULL; +} + + +#define ewt (cv_mem->cv_ewt) +#define uround (cv_mem->cv_uround) +#define h (cv_mem->cv_h) +#define f (cv_mem->cv_f) +#define user_data (cv_mem->cv_user_data) + +/* + * ----------------------------------------------------------------- + * cvBandPrecDQJac + * ----------------------------------------------------------------- + * This routine generates a banded difference quotient approximation to + * the Jacobian of f(t,y). It assumes that a band matrix of type + * BandMat is stored column-wise, and that elements within each column + * are contiguous. This makes it possible to get the address of a column + * of J via the macro BAND_COL and to write a simple for loop to set + * each of the elements of a column in succession. + * ----------------------------------------------------------------- + */ + +static int cvBandPrecDQJac(CVBandPrecData pdata, + realtype t, N_Vector y, N_Vector fy, + N_Vector ftemp, N_Vector ytemp) +{ + CVodeMem cv_mem; + realtype fnorm, minInc, inc, inc_inv, srur; + int group, i, j, width, ngroups, i1, i2; + realtype *col_j, *ewt_data, *fy_data, *ftemp_data, *y_data, *ytemp_data; + int retval; + + cv_mem = (CVodeMem) pdata->cvode_mem; + + /* Obtain pointers to the data for ewt, fy, ftemp, y, ytemp. */ + ewt_data = N_VGetArrayPointer(ewt); + fy_data = N_VGetArrayPointer(fy); + ftemp_data = N_VGetArrayPointer(ftemp); + y_data = N_VGetArrayPointer(y); + ytemp_data = N_VGetArrayPointer(ytemp); + + /* Load ytemp with y = predicted y vector. */ + N_VScale(ONE, y, ytemp); + + /* Set minimum increment based on uround and norm of f. */ + srur = RSqrt(uround); + fnorm = N_VWrmsNorm(fy, ewt); + minInc = (fnorm != ZERO) ? + (MIN_INC_MULT * ABS(h) * uround * N * fnorm) : ONE; + + /* Set bandwidth and number of column groups for band differencing. */ + width = ml + mu + 1; + ngroups = MIN(width, N); + + for (group = 1; group <= ngroups; group++) { + + /* Increment all y_j in group. */ + for(j = group-1; j < N; j += width) { + inc = MAX(srur*ABS(y_data[j]), minInc/ewt_data[j]); + ytemp_data[j] += inc; + } + + /* Evaluate f with incremented y. */ + + retval = f(t, ytemp, ftemp, user_data); + nfeBP++; + if (retval != 0) return(retval); + + /* Restore ytemp, then form and load difference quotients. */ + for (j = group-1; j < N; j += width) { + ytemp_data[j] = y_data[j]; + col_j = BAND_COL(savedJ,j); + inc = MAX(srur*ABS(y_data[j]), minInc/ewt_data[j]); + inc_inv = ONE/inc; + i1 = MAX(0, j-mu); + i2 = MIN(j+ml, N-1); + for (i=i1; i <= i2; i++) + BAND_COL_ELEM(col_j,i,j) = + inc_inv * (ftemp_data[i] - fy_data[i]); + } + } + + return(0); +} + +/* + * ================================================================ + * + * PART II - backward problems + * + * ================================================================ + */ + +/* + * CVBandPrecInitB, CVBPSp*B + * + * Wrappers for the backward phase around the corresponding + * CVODES functions + */ + +int CVBandPrecInitB(void *cvode_mem, int which, int nB, int muB, int mlB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBANDPRE", "CVBandPrecInitB", MSGBP_MEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVBANDPRE", "CVBandPrecInitB", MSGBP_NO_ADJ); + return(CVSPILS_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= ca_mem->ca_nbckpbs ) { + cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVBANDPRE", "CVBandPrecInitB", MSGBP_BAD_WHICH); + return(CVSPILS_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvB_mem->cv_pfree = NULL; + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + flag = CVBandPrecInit(cvodeB_mem, nB, muB, mlB); + + return(flag); +} + diff --git a/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_bandpre_impl.h b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_bandpre_impl.h new file mode 100644 index 0000000..6fd91c5 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_bandpre_impl.h @@ -0,0 +1,77 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.9 $ + * $Date: 2007/11/26 16:19:59 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Implementation header file for the CVBANDPRE module. + * ----------------------------------------------------------------- + */ + +#ifndef _CVSBANDPRE_IMPL_H +#define _CVSBANDPRE_IMPL_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include +#include + +/* + * ----------------------------------------------------------------- + * Type: CVBandPrecData + * ----------------------------------------------------------------- + */ + +typedef struct CVBandPrecDataRec { + + /* Data set by user in CVBandPrecInit */ + + int N; + int ml, mu; + + /* Data set by CVBandPrecSetup */ + + DlsMat savedJ; + DlsMat savedP; + int *pivots; + + /* Rhs calls */ + + long int nfeBP; + + /* Pointer to cvode_mem */ + + void *cvode_mem; + +} *CVBandPrecData; + +/* + * ----------------------------------------------------------------- + * CVBANDPRE error messages + * ----------------------------------------------------------------- + */ + +#define MSGBP_MEM_NULL "Integrator memory is NULL." +#define MSGBP_LMEM_NULL "Linear solver memory is NULL. One of the SPILS linear solvers must be attached." +#define MSGBP_MEM_FAIL "A memory request failed." +#define MSGBP_BAD_NVECTOR "A required vector operation is not implemented." +#define MSGBP_PMEM_NULL "Band preconditioner memory is NULL. CVBandPrecInit must be called." +#define MSGBP_RHSFUNC_FAILED "The right-hand side routine failed in an unrecoverable manner." + +#define MSGBP_NO_ADJ "Illegal attempt to call before calling CVodeAdjInit." +#define MSGBP_BAD_WHICH "Illegal value for parameter which." + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_bbdpre.c b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_bbdpre.c new file mode 100644 index 0000000..849d27d --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_bbdpre.c @@ -0,0 +1,784 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.13 $ + * $Date: 2009/02/17 02:42:29 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This file contains implementations of routines for a + * band-block-diagonal preconditioner, i.e. a block-diagonal + * matrix with banded blocks, for use with CVODE, a CVSPILS linear + * solver, and the parallel implementation of NVECTOR. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "cvodes_impl.h" +#include "cvodes_bbdpre_impl.h" +#include "cvodes_spils_impl.h" + +#include +#include +#include + +#include + +#define MIN_INC_MULT RCONST(1000.0) + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +/* Prototypes of functions cvBBDPrecSetup and cvBBDPrecSolve */ +static int cvBBDPrecSetup(realtype t, N_Vector y, N_Vector fy, + booleantype jok, booleantype *jcurPtr, + realtype gamma, void *bbd_data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); +static int cvBBDPrecSolve(realtype t, N_Vector y, N_Vector fy, + N_Vector r, N_Vector z, + realtype gamma, realtype delta, + int lr, void *bbd_data, N_Vector tmp); + +/* Prototype for cvBBDPrecFree */ +static void cvBBDPrecFree(CVodeMem cv_mem); + +/* Wrapper functions for adjoint code */ +static int cvGlocWrapper(int NlocalB, realtype t, N_Vector yB, N_Vector gB, + void *cvadj_mem); +static int cvCfnWrapper(int NlocalB, realtype t, N_Vector yB, void *cvadj_mem); + +/* Prototype for difference quotient Jacobian calculation routine */ +static int cvBBDDQJac(CVBBDPrecData pdata, realtype t, + N_Vector y, N_Vector gy, + N_Vector ytemp, N_Vector gtemp); + +/* Prototype for the pfree routine */ +static void CVBBDPrecFreeB(CVodeBMem cvB_mem); + +/* + * ================================================================ + * + * PART I - forward problems + * + * ================================================================ + */ + +/* Redability replacements */ + +#define uround (cv_mem->cv_uround) +#define vec_tmpl (cv_mem->cv_tempv) + +/* + * ----------------------------------------------------------------- + * User-Callable Functions: initialization, reinit and free + * ----------------------------------------------------------------- + */ + +int CVBBDPrecInit(void *cvode_mem, int Nlocal, + int mudq, int mldq, + int mukeep, int mlkeep, + realtype dqrely, + CVLocalFn gloc, CVCommFn cfn) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + CVBBDPrecData pdata; + int muk, mlk, storage_mu; + int flag; + + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Test if one of the SPILS linear solvers has been attached */ + if (cv_mem->cv_lmem == NULL) { + cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem; + + /* Test if the NVECTOR package is compatible with the BLOCK BAND preconditioner */ + if(vec_tmpl->ops->nvgetarraypointer == NULL) { + cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_BAD_NVECTOR); + return(CVSPILS_ILL_INPUT); + } + + /* Allocate data memory */ + pdata = NULL; + pdata = (CVBBDPrecData) malloc(sizeof *pdata); + if (pdata == NULL) { + cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_FAIL); + return(CVSPILS_MEM_FAIL); + } + + /* Set pointers to gloc and cfn; load half-bandwidths */ + pdata->cvode_mem = cvode_mem; + pdata->gloc = gloc; + pdata->cfn = cfn; + pdata->mudq = MIN(Nlocal-1, MAX(0,mudq)); + pdata->mldq = MIN(Nlocal-1, MAX(0,mldq)); + muk = MIN(Nlocal-1, MAX(0,mukeep)); + mlk = MIN(Nlocal-1, MAX(0,mlkeep)); + pdata->mukeep = muk; + pdata->mlkeep = mlk; + + /* Allocate memory for saved Jacobian */ + pdata->savedJ = NewBandMat(Nlocal, muk, mlk, muk); + if (pdata->savedJ == NULL) { + free(pdata); pdata = NULL; + cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_FAIL); + return(CVSPILS_MEM_FAIL); + } + + /* Allocate memory for preconditioner matrix */ + storage_mu = MIN(Nlocal-1, muk + mlk); + pdata->savedP = NULL; + pdata->savedP = NewBandMat(Nlocal, muk, mlk, storage_mu); + if (pdata->savedP == NULL) { + DestroyMat(pdata->savedJ); + free(pdata); pdata = NULL; + cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_FAIL); + return(CVSPILS_MEM_FAIL); + } + /* Allocate memory for pivots */ + pdata->pivots = NULL; + pdata->pivots = NewIntArray(Nlocal); + if (pdata->savedJ == NULL) { + DestroyMat(pdata->savedP); + DestroyMat(pdata->savedJ); + free(pdata); pdata = NULL; + cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_FAIL); + return(CVSPILS_MEM_FAIL); + } + + /* Set pdata->dqrely based on input dqrely (0 implies default). */ + pdata->dqrely = (dqrely > ZERO) ? dqrely : RSqrt(uround); + + /* Store Nlocal to be used in CVBBDPrecSetup */ + pdata->n_local = Nlocal; + + /* Set work space sizes and initialize nge */ + pdata->rpwsize = Nlocal*(muk + 2*mlk + storage_mu + 2); + pdata->ipwsize = Nlocal; + pdata->nge = 0; + + /* Overwrite the P_data field in the SPILS memory */ + cvspils_mem->s_P_data = pdata; + + /* Attach the pfree function */ + cvspils_mem->s_pfree = cvBBDPrecFree; + + /* Attach preconditioner solve and setup functions */ + flag = CVSpilsSetPreconditioner(cvode_mem, cvBBDPrecSetup, cvBBDPrecSolve); + + return(flag); +} + + +int CVBBDPrecReInit(void *cvode_mem, + int mudq, int mldq, + realtype dqrely) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + CVBBDPrecData pdata; + int Nlocal; + + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBBDPRE", "CVBBDPrecReInit", MSGBBD_MEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Test if one of the SPILS linear solvers has been attached */ + if (cv_mem->cv_lmem == NULL) { + cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBBDPRE", "CVBBDPrecReInit", MSGBBD_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem; + + /* Test if the preconditioner data is non-NULL */ + if (cvspils_mem->s_P_data == NULL) { + cvProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVBBDPRE", "CVBBDPrecReInit", MSGBBD_PMEM_NULL); + return(CVSPILS_PMEM_NULL); + } + pdata = (CVBBDPrecData) cvspils_mem->s_P_data; + + /* Load half-bandwidths */ + Nlocal = pdata->n_local; + pdata->mudq = MIN(Nlocal-1, MAX(0,mudq)); + pdata->mldq = MIN(Nlocal-1, MAX(0,mldq)); + + /* Set pdata->dqrely based on input dqrely (0 implies default). */ + pdata->dqrely = (dqrely > ZERO) ? dqrely : RSqrt(uround); + + /* Re-initialize nge */ + pdata->nge = 0; + + return(CVSPILS_SUCCESS); +} + +int CVBBDPrecGetWorkSpace(void *cvode_mem, long int *lenrwBBDP, long int *leniwBBDP) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + CVBBDPrecData pdata; + + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBBDPRE", "CVBBDPrecGetWorkSpace", MSGBBD_MEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (cv_mem->cv_lmem == NULL) { + cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBBDPRE", "CVBBDPrecGetWorkSpace", MSGBBD_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem; + + if (cvspils_mem->s_P_data == NULL) { + cvProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVBBDPRE", "CVBBDPrecGetWorkSpace", MSGBBD_PMEM_NULL); + return(CVSPILS_PMEM_NULL); + } + pdata = (CVBBDPrecData) cvspils_mem->s_P_data; + + *lenrwBBDP = pdata->rpwsize; + *leniwBBDP = pdata->ipwsize; + + return(CVSPILS_SUCCESS); +} + +int CVBBDPrecGetNumGfnEvals(void *cvode_mem, long int *ngevalsBBDP) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + CVBBDPrecData pdata; + + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBBDPRE", "CVBBDPrecGetNumGfnEvals", MSGBBD_MEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (cv_mem->cv_lmem == NULL) { + cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBBDPRE", "CVBBDPrecGetNumGfnEvals", MSGBBD_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem; + + if (cvspils_mem->s_P_data == NULL) { + cvProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVBBDPRE", "CVBBDPrecGetNumGfnEvals", MSGBBD_PMEM_NULL); + return(CVSPILS_PMEM_NULL); + } + pdata = (CVBBDPrecData) cvspils_mem->s_P_data; + + *ngevalsBBDP = pdata->nge; + + return(CVSPILS_SUCCESS); +} + +/* Readability Replacements */ + +#define Nlocal (pdata->n_local) +#define mudq (pdata->mudq) +#define mldq (pdata->mldq) +#define mukeep (pdata->mukeep) +#define mlkeep (pdata->mlkeep) +#define dqrely (pdata->dqrely) +#define gloc (pdata->gloc) +#define cfn (pdata->cfn) +#define savedJ (pdata->savedJ) +#define savedP (pdata->savedP) +#define pivots (pdata->pivots) +#define nge (pdata->nge) + +/* + * ----------------------------------------------------------------- + * Function : cvBBDPrecSetup + * ----------------------------------------------------------------- + * cvBBDPrecSetup generates and factors a banded block of the + * preconditioner matrix on each processor, via calls to the + * user-supplied gloc and cfn functions. It uses difference + * quotient approximations to the Jacobian elements. + * + * cvBBDPrecSetup calculates a new J,if necessary, then calculates + * P = I - gamma*J, and does an LU factorization of P. + * + * The parameters of cvBBDPrecSetup used here are as follows: + * + * t is the current value of the independent variable. + * + * y is the current value of the dependent variable vector, + * namely the predicted value of y(t). + * + * fy is the vector f(t,y). + * + * jok is an input flag indicating whether Jacobian-related + * data needs to be recomputed, as follows: + * jok == FALSE means recompute Jacobian-related data + * from scratch. + * jok == TRUE means that Jacobian data from the + * previous CVBBDPrecon call can be reused + * (with the current value of gamma). + * A CVBBDPrecon call with jok == TRUE should only occur + * after a call with jok == FALSE. + * + * jcurPtr is a pointer to an output integer flag which is + * set by CVBBDPrecon as follows: + * *jcurPtr = TRUE if Jacobian data was recomputed. + * *jcurPtr = FALSE if Jacobian data was not recomputed, + * but saved data was reused. + * + * gamma is the scalar appearing in the Newton matrix. + * + * bbd_data is a pointer to the preconditioner data set by + * CVBBDPrecInit + * + * tmp1, tmp2, and tmp3 are pointers to memory allocated + * for NVectors which are be used by cvBBDPrecSetup + * as temporary storage or work space. + * + * Return value: + * The value returned by this cvBBDPrecSetup function is the int + * 0 if successful, + * 1 for a recoverable error (step will be retried). + * ----------------------------------------------------------------- + */ + +static int cvBBDPrecSetup(realtype t, N_Vector y, N_Vector fy, + booleantype jok, booleantype *jcurPtr, + realtype gamma, void *bbd_data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + CVBBDPrecData pdata; + CVodeMem cv_mem; + int ier, retval; + + pdata = (CVBBDPrecData) bbd_data; + + cv_mem = (CVodeMem) pdata->cvode_mem; + + if (jok) { + + /* If jok = TRUE, use saved copy of J */ + *jcurPtr = FALSE; + BandCopy(savedJ, savedP, mukeep, mlkeep); + + } else { + + /* Otherwise call cvBBDDQJac for new J value */ + *jcurPtr = TRUE; + SetToZero(savedJ); + + retval = cvBBDDQJac(pdata, t, y, tmp1, tmp2, tmp3); + if (retval < 0) { + cvProcessError(cv_mem, -1, "CVBBDPRE", "cvBBDPrecSetup", MSGBBD_FUNC_FAILED); + return(-1); + } + if (retval > 0) { + return(1); + } + + BandCopy(savedJ, savedP, mukeep, mlkeep); + + } + + /* Scale and add I to get P = I - gamma*J */ + BandScale(-gamma, savedP); + AddIdentity(savedP); + + /* Do LU factorization of P in place */ + ier = BandGBTRF(savedP, pivots); + + /* Return 0 if the LU was complete; otherwise return 1 */ + if (ier > 0) return(1); + return(0); +} + +/* + * ----------------------------------------------------------------- + * Function : cvBBDPrecSolve + * ----------------------------------------------------------------- + * cvBBDPrecSolve solves a linear system P z = r, with the + * band-block-diagonal preconditioner matrix P generated and + * factored by cvBBDPrecSetup. + * + * The parameters of cvBBDPrecSolve used here are as follows: + * + * r is the right-hand side vector of the linear system. + * + * bbd_data is a pointer to the preconditioner data set by + * CVBBDPrecInit. + * + * z is the output vector computed by cvBBDPrecSolve. + * + * The value returned by the cvBBDPrecSolve function is always 0, + * indicating success. + * ----------------------------------------------------------------- + */ + +static int cvBBDPrecSolve(realtype t, N_Vector y, N_Vector fy, + N_Vector r, N_Vector z, + realtype gamma, realtype delta, + int lr, void *bbd_data, N_Vector tmp) +{ + CVBBDPrecData pdata; + realtype *zd; + + pdata = (CVBBDPrecData) bbd_data; + + /* Copy r to z, then do backsolve and return */ + N_VScale(ONE, r, z); + + zd = N_VGetArrayPointer(z); + + BandGBTRS(savedP, pivots, zd); + + return(0); +} + + +static void cvBBDPrecFree(CVodeMem cv_mem) +{ + CVSpilsMem cvspils_mem; + CVBBDPrecData pdata; + + if (cv_mem->cv_lmem == NULL) return; + cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem; + + if (cvspils_mem->s_P_data == NULL) return; + pdata = (CVBBDPrecData) cvspils_mem->s_P_data; + + DestroyMat(savedJ); + DestroyMat(savedP); + DestroyArray(pivots); + + free(pdata); + pdata = NULL; +} + + + +#define ewt (cv_mem->cv_ewt) +#define h (cv_mem->cv_h) +#define user_data (cv_mem->cv_user_data) + +/* + * ----------------------------------------------------------------- + * Function : cvBBDDQJac + * ----------------------------------------------------------------- + * This routine generates a banded difference quotient approximation + * to the local block of the Jacobian of g(t,y). It assumes that a + * band matrix of type BandMat is stored columnwise, and that elements + * within each column are contiguous. All matrix elements are generated + * as difference quotients, by way of calls to the user routine gloc. + * By virtue of the band structure, the number of these calls is + * bandwidth + 1, where bandwidth = mldq + mudq + 1. + * But the band matrix kept has bandwidth = mlkeep + mukeep + 1. + * This routine also assumes that the local elements of a vector are + * stored contiguously. + * ----------------------------------------------------------------- + */ + +static int cvBBDDQJac(CVBBDPrecData pdata, realtype t, + N_Vector y, N_Vector gy, + N_Vector ytemp, N_Vector gtemp) +{ + CVodeMem cv_mem; + realtype gnorm, minInc, inc, inc_inv; + int group, i, j, width, ngroups, i1, i2; + realtype *y_data, *ewt_data, *gy_data, *gtemp_data, *ytemp_data, *col_j; + int retval; + + cv_mem = (CVodeMem) pdata->cvode_mem; + + /* Load ytemp with y = predicted solution vector */ + N_VScale(ONE, y, ytemp); + + /* Call cfn and gloc to get base value of g(t,y) */ + if (cfn != NULL) { + retval = cfn(Nlocal, t, y, user_data); + if (retval != 0) return(retval); + } + + retval = gloc(Nlocal, t, ytemp, gy, user_data); + nge++; + if (retval != 0) return(retval); + + /* Obtain pointers to the data for various vectors */ + y_data = N_VGetArrayPointer(y); + gy_data = N_VGetArrayPointer(gy); + ewt_data = N_VGetArrayPointer(ewt); + ytemp_data = N_VGetArrayPointer(ytemp); + gtemp_data = N_VGetArrayPointer(gtemp); + + /* Set minimum increment based on uround and norm of g */ + gnorm = N_VWrmsNorm(gy, ewt); + minInc = (gnorm != ZERO) ? + (MIN_INC_MULT * ABS(h) * uround * Nlocal * gnorm) : ONE; + + /* Set bandwidth and number of column groups for band differencing */ + width = mldq + mudq + 1; + ngroups = MIN(width, Nlocal); + + /* Loop over groups */ + for (group=1; group <= ngroups; group++) { + + /* Increment all y_j in group */ + for(j=group-1; j < Nlocal; j+=width) { + inc = MAX(dqrely*ABS(y_data[j]), minInc/ewt_data[j]); + ytemp_data[j] += inc; + } + + /* Evaluate g with incremented y */ + retval = gloc(Nlocal, t, ytemp, gtemp, user_data); + nge++; + if (retval != 0) return(retval); + + /* Restore ytemp, then form and load difference quotients */ + for (j=group-1; j < Nlocal; j+=width) { + ytemp_data[j] = y_data[j]; + col_j = BAND_COL(savedJ,j); + inc = MAX(dqrely*ABS(y_data[j]), minInc/ewt_data[j]); + inc_inv = ONE/inc; + i1 = MAX(0, j-mukeep); + i2 = MIN(j+mlkeep, Nlocal-1); + for (i=i1; i <= i2; i++) + BAND_COL_ELEM(col_j,i,j) = + inc_inv * (gtemp_data[i] - gy_data[i]); + } + } + + return(0); +} + + +/* + * ================================================================ + * + * PART II - backward problems + * + * ================================================================ + */ + + +/* Additional readability replacements */ + +#define ytmp (ca_mem->ca_ytmp) +#define yStmp (ca_mem->ca_yStmp) +#define IMget (ca_mem->ca_IMget) + +#define gloc_B (cvbbdB_mem->glocB) +#define cfn_B (cvbbdB_mem->cfnB) + +/* + * CVBBDPrecInitB, CVBPSp*B + * + * Wrappers for the backward phase around the corresponding CVODES functions + */ + +int CVBBDPrecInitB(void *cvode_mem, int which, int NlocalB, + int mudqB, int mldqB, + int mukeepB, int mlkeepB, + realtype dqrelyB, + CVLocalFnB glocB, CVCommFnB cfnB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + CVBBDPrecDataB cvbbdB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBBDPRE", "CVBBDPrecInitB", MSGBBD_MEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVBBDPRE", "CVBBDPrecInitB", MSGBBD_NO_ADJ); + return(CVSPILS_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= ca_mem->ca_nbckpbs ) { + cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVBBDPRE", "CVBBDPrecInitB", MSGBBD_BAD_WHICH); + return(CVSPILS_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + /* Initialize the BBD preconditioner */ + flag = CVBBDPrecInit(cvodeB_mem, NlocalB, + mudqB, mldqB, + mukeepB, mlkeepB, + dqrelyB, + cvGlocWrapper, cvCfnWrapper); + + if (flag != CV_SUCCESS) return(flag); + + + /* Get memory for CVBBDPrecDataB to store the user-provided + * functions which will be called from the wrappers */ + cvbbdB_mem = NULL; + cvbbdB_mem = (CVBBDPrecDataB) malloc(sizeof(* cvbbdB_mem)); + if (cvbbdB_mem == NULL) { + cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInitB", MSGBBD_MEM_FAIL); + return(CVSPILS_MEM_FAIL); + } + + gloc_B = glocB; + cfn_B = cfnB; + + /* attach pmem and pfree */ + cvB_mem->cv_pmem = cvbbdB_mem; + cvB_mem->cv_pfree = CVBBDPrecFreeB; + + return(CVSPILS_SUCCESS); +} + +int CVBBDPrecReInitB(void *cvode_mem, int which, + int mudqB, int mldqB, + realtype dqrelyB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBBDPRE", "CVBBDPrecReInitB", MSGBBD_MEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVBBDPRE", "CVBBDPrecReInitB", MSGBBD_NO_ADJ); + return(CVSPILS_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= ca_mem->ca_nbckpbs ) { + cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVBBDPRE", "CVBBDPrecReInitB", MSGBBD_BAD_WHICH); + return(CVSPILS_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + flag = CVBBDPrecReInit(cvodeB_mem, mudqB, mldqB, dqrelyB); + + return(flag); +} + + +static void CVBBDPrecFreeB(CVodeBMem cvB_mem) +{ + free(cvB_mem->cv_pmem); + cvB_mem->cv_pmem = NULL; +} + + +/* + * cvGlocWrapper + * + * This routine interfaces to the CVLocalFnB routine + * provided by the user. + */ + +static int cvGlocWrapper(int NlocalB, realtype t, N_Vector yB, N_Vector gB, void *cvode_mem) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + CVBBDPrecDataB cvbbdB_mem; + int retval, flag; + + cv_mem = (CVodeMem) cvode_mem; + + ca_mem = cv_mem->cv_adj_mem; + + cvB_mem = ca_mem->ca_bckpbCrt; + + cvbbdB_mem = (CVBBDPrecDataB) (cvB_mem->cv_pmem); + + /* Forward solution from interpolation */ + flag = IMget(cv_mem, t, ytmp, NULL); + if (flag != CV_SUCCESS) { + cvProcessError(cv_mem, -1, "CVBBDPRE", "cvGlocWrapper", MSGBBD_BAD_TINTERP); + return(-1); + } + + /* Call user's adjoint glocB routine */ + retval = gloc_B(NlocalB, t, ytmp, yB, gB, cvB_mem->cv_user_data); + + return(retval); +} + +/* + * cvCfnWrapper + * + * This routine interfaces to the CVCommFnB routine + * provided by the user. + */ + +static int cvCfnWrapper(int NlocalB, realtype t, N_Vector yB, void *cvode_mem) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + CVBBDPrecDataB cvbbdB_mem; + int retval, flag; + + cv_mem = (CVodeMem) cvode_mem; + + ca_mem = cv_mem->cv_adj_mem; + + cvB_mem = ca_mem->ca_bckpbCrt; + + cvbbdB_mem = (CVBBDPrecDataB) (cvB_mem->cv_pmem); + + if (cfn_B == NULL) return(0); + + /* Forward solution from interpolation */ + flag = IMget(cv_mem, t, ytmp, NULL); + if (flag != CV_SUCCESS) { + cvProcessError(cv_mem, -1, "CVBBDPRE", "cvCfnWrapper", MSGBBD_BAD_TINTERP); + return(-1); + } + + /* Call user's adjoint cfnB routine */ + retval = cfn_B(NlocalB, t, ytmp, yB, cvB_mem->cv_user_data); + + return(retval); +} + diff --git a/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_bbdpre_impl.h b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_bbdpre_impl.h new file mode 100644 index 0000000..04ef61b --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_bbdpre_impl.h @@ -0,0 +1,102 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.7 $ + * $Date: 2007/04/30 17:41:06 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Implementation header file for the CVBBDPRE module. + * ----------------------------------------------------------------- + */ + +#ifndef _CVSBBDPRE_IMPL_H +#define _CVSBBDPRE_IMPL_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * Type: CVBBDPrecData + * ----------------------------------------------------------------- + */ + +typedef struct CVBBDPrecDataRec { + + /* passed by user to CVBBDPrecAlloc and used by PrecSetup/PrecSolve */ + + int mudq, mldq, mukeep, mlkeep; + realtype dqrely; + CVLocalFn gloc; + CVCommFn cfn; + + /* set by CVBBDPrecSetup and used by CVBBDPrecSolve */ + + DlsMat savedJ; + DlsMat savedP; + int *pivots; + + /* set by CVBBDPrecAlloc and used by CVBBDPrecSetup */ + + int n_local; + + /* available for optional output */ + + long int rpwsize; + long int ipwsize; + long int nge; + + /* pointer to cvode_mem */ + + void *cvode_mem; + +} *CVBBDPrecData; + + +/* + * ----------------------------------------------------------------- + * Type: CVBBDPrecDataB + * ----------------------------------------------------------------- + */ + +typedef struct CVBBDPrecDataRecB { + + /* BBD user functions (glocB and cfnB) for backward run */ + CVLocalFnB glocB; + CVCommFnB cfnB; + +} *CVBBDPrecDataB; + +/* + * ----------------------------------------------------------------- + * CVBBDPRE error messages + * ----------------------------------------------------------------- + */ + +#define MSGBBD_MEM_NULL "Integrator memory is NULL." +#define MSGBBD_LMEM_NULL "Linear solver memory is NULL. One of the SPILS linear solvers must be attached." +#define MSGBBD_MEM_FAIL "A memory request failed." +#define MSGBBD_BAD_NVECTOR "A required vector operation is not implemented." +#define MSGBBD_PMEM_NULL "BBD peconditioner memory is NULL. CVBBDPrecInit must be called." +#define MSGBBD_FUNC_FAILED "The gloc or cfn routine failed in an unrecoverable manner." + +#define MSGBBD_NO_ADJ "Illegal attempt to call before calling CVodeAdjInit." +#define MSGBBD_BAD_WHICH "Illegal value for the which parameter." +#define MSGBBD_PDATAB_NULL "BBD preconditioner memory is NULL for the backward integration." +#define MSGBBD_BAD_TINTERP "Bad t for interpolation." + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_dense.c b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_dense.c new file mode 100644 index 0000000..b7cbb6b --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_dense.c @@ -0,0 +1,438 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.13 $ + * $Date: 2009/02/17 02:42:29 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the CVSDENSE linear solver. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include "cvodes_direct_impl.h" +#include "cvodes_impl.h" + +#include + +/* Constants */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) +#define TWO RCONST(2.0) + +/* CVSDENSE linit, lsetup, lsolve, and lfree routines */ +static int cvDenseInit(CVodeMem cv_mem); +static int cvDenseSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, + N_Vector fpred, booleantype *jcurPtr, + N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3); +static int cvDenseSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector ycur, N_Vector fcur); +static void cvDenseFree(CVodeMem cv_mem); + +/* CVSDENSE lfreeB function */ +static void cvDenseFreeB(CVodeBMem cvb_mem); + +/* + * ================================================================ + * + * PART I - forward problems + * + * ================================================================ + */ + + +/* Readability Replacements */ + +#define lmm (cv_mem->cv_lmm) +#define f (cv_mem->cv_f) +#define nst (cv_mem->cv_nst) +#define tn (cv_mem->cv_tn) +#define h (cv_mem->cv_h) +#define gamma (cv_mem->cv_gamma) +#define gammap (cv_mem->cv_gammap) +#define gamrat (cv_mem->cv_gamrat) +#define ewt (cv_mem->cv_ewt) +#define linit (cv_mem->cv_linit) +#define lsetup (cv_mem->cv_lsetup) +#define lsolve (cv_mem->cv_lsolve) +#define lfree (cv_mem->cv_lfree) +#define lmem (cv_mem->cv_lmem) +#define vec_tmpl (cv_mem->cv_tempv) +#define setupNonNull (cv_mem->cv_setupNonNull) + +#define mtype (cvdls_mem->d_type) +#define n (cvdls_mem->d_n) +#define jacDQ (cvdls_mem->d_jacDQ) +#define jac (cvdls_mem->d_djac) +#define M (cvdls_mem->d_M) +#define pivots (cvdls_mem->d_pivots) +#define savedJ (cvdls_mem->d_savedJ) +#define nstlj (cvdls_mem->d_nstlj) +#define nje (cvdls_mem->d_nje) +#define nfeDQ (cvdls_mem->d_nfeDQ) +#define J_data (cvdls_mem->d_J_data) +#define last_flag (cvdls_mem->d_last_flag) + +/* + * ----------------------------------------------------------------- + * CVDense + * ----------------------------------------------------------------- + * This routine initializes the memory record and sets various function + * fields specific to the dense linear solver module. CVDense first + * calls the existing lfree routine if this is not NULL. Then it sets + * the cv_linit, cv_lsetup, cv_lsolve, cv_lfree fields in (*cvode_mem) + * to be cvDenseInit, cvDenseSetup, cvDenseSolve, and cvDenseFree, + * respectively. It allocates memory for a structure of type + * CVDlsMemRec and sets the cv_lmem field in (*cvode_mem) to the + * address of this structure. It sets setupNonNull in (*cvode_mem) to + * TRUE, and the d_jac field to the default CVDenseDQJac. + * Finally, it allocates memory for M, savedJ, and pivots. + * The return value is SUCCESS = 0, or LMEM_FAIL = -1. + * + * NOTE: The dense linear solver assumes a serial implementation + * of the NVECTOR package. Therefore, CVDense will first + * test for compatible a compatible N_Vector internal + * representation by checking that N_VGetArrayPointer and + * N_VSetArrayPointer exist. + * ----------------------------------------------------------------- + */ + +int CVDense(void *cvode_mem, int N) +{ + CVodeMem cv_mem; + CVDlsMem cvdls_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDENSE", "CVDense", MSGD_CVMEM_NULL); + return(CVDLS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Test if the NVECTOR package is compatible with the DENSE solver */ + if (vec_tmpl->ops->nvgetarraypointer == NULL || + vec_tmpl->ops->nvsetarraypointer == NULL) { + cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSDENSE", "CVDense", MSGD_BAD_NVECTOR); + return(CVDLS_ILL_INPUT); + } + + if (lfree !=NULL) lfree(cv_mem); + + /* Set four main function fields in cv_mem */ + linit = cvDenseInit; + lsetup = cvDenseSetup; + lsolve = cvDenseSolve; + lfree = cvDenseFree; + + /* Get memory for CVDlsMemRec */ + cvdls_mem = NULL; + cvdls_mem = (CVDlsMem) malloc(sizeof(struct CVDlsMemRec)); + if (cvdls_mem == NULL) { + cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSDENSE", "CVDense", MSGD_MEM_FAIL); + return(CVDLS_MEM_FAIL); + } + + /* Set matrix type */ + mtype = SUNDIALS_DENSE; + + /* Initialize Jacobian-related data */ + jacDQ = TRUE; + jac = NULL; + J_data = NULL; + + last_flag = CVDLS_SUCCESS; + + setupNonNull = TRUE; + + /* Set problem dimension */ + n = N; + + /* Allocate memory for M, savedJ, and pivot array */ + + M = NULL; + M = NewDenseMat(N, N); + if (M == NULL) { + cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSDENSE", "CVDense", MSGD_MEM_FAIL); + free(cvdls_mem); cvdls_mem = NULL; + return(CVDLS_MEM_FAIL); + } + savedJ = NULL; + savedJ = NewDenseMat(N, N); + if (savedJ == NULL) { + cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSDENSE", "CVDense", MSGD_MEM_FAIL); + DestroyMat(M); + free(cvdls_mem); cvdls_mem = NULL; + return(CVDLS_MEM_FAIL); + } + pivots = NULL; + pivots = NewIntArray(N); + if (pivots == NULL) { + cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSDENSE", "CVDense", MSGD_MEM_FAIL); + DestroyMat(M); + DestroyMat(savedJ); + free(cvdls_mem); cvdls_mem = NULL; + return(CVDLS_MEM_FAIL); + } + + /* Attach linear solver memory to integrator memory */ + lmem = cvdls_mem; + + return(CVDLS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * cvDenseInit + * ----------------------------------------------------------------- + * This routine does remaining initializations specific to the dense + * linear solver. + * ----------------------------------------------------------------- + */ + +static int cvDenseInit(CVodeMem cv_mem) +{ + CVDlsMem cvdls_mem; + + cvdls_mem = (CVDlsMem) lmem; + + nje = 0; + nfeDQ = 0; + nstlj = 0; + + /* Set Jacobian function and data, depending on jacDQ */ + if (jacDQ) { + jac = cvDlsDenseDQJac; + J_data = cv_mem; + } else { + J_data = cv_mem->cv_user_data; + } + + last_flag = CVDLS_SUCCESS; + return(0); +} + +/* + * ----------------------------------------------------------------- + * cvDenseSetup + * ----------------------------------------------------------------- + * This routine does the setup operations for the dense linear solver. + * It makes a decision whether or not to call the Jacobian evaluation + * routine based on various state variables, and if not it uses the + * saved copy. In any case, it constructs the Newton matrix + * M = I - gamma*J, updates counters, and calls the dense LU + * factorization routine. + * ----------------------------------------------------------------- + */ + +static int cvDenseSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, + N_Vector fpred, booleantype *jcurPtr, + N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3) +{ + CVDlsMem cvdls_mem; + booleantype jbad, jok; + realtype dgamma; + int ier, retval; + + cvdls_mem = (CVDlsMem) lmem; + + /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */ + + dgamma = ABS((gamma/gammap) - ONE); + jbad = (nst == 0) || (nst > nstlj + CVD_MSBJ) || + ((convfail == CV_FAIL_BAD_J) && (dgamma < CVD_DGMAX)) || + (convfail == CV_FAIL_OTHER); + jok = !jbad; + + if (jok) { + + /* If jok = TRUE, use saved copy of J */ + *jcurPtr = FALSE; + DenseCopy(savedJ, M); + + } else { + + /* If jok = FALSE, call jac routine for new J value */ + nje++; + nstlj = nst; + *jcurPtr = TRUE; + SetToZero(M); + + retval = jac(n, tn, ypred, fpred, M, J_data, vtemp1, vtemp2, vtemp3); + if (retval < 0) { + cvProcessError(cv_mem, CVDLS_JACFUNC_UNRECVR, "CVSDENSE", "cvDenseSetup", MSGD_JACFUNC_FAILED); + last_flag = CVDLS_JACFUNC_UNRECVR; + return(-1); + } + if (retval > 0) { + last_flag = CVDLS_JACFUNC_RECVR; + return(1); + } + + DenseCopy(M, savedJ); + + } + + /* Scale and add I to get M = I - gamma*J */ + DenseScale(-gamma, M); + AddIdentity(M); + + /* Do LU factorization of M */ + ier = DenseGETRF(M, pivots); + + /* Return 0 if the LU was complete; otherwise return 1 */ + last_flag = ier; + if (ier > 0) return(1); + return(0); +} + +/* + * ----------------------------------------------------------------- + * cvDenseSolve + * ----------------------------------------------------------------- + * This routine handles the solve operation for the dense linear solver + * by calling the dense backsolve routine. The returned value is 0. + * ----------------------------------------------------------------- + */ + +static int cvDenseSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector ycur, N_Vector fcur) +{ + CVDlsMem cvdls_mem; + realtype *bd; + + cvdls_mem = (CVDlsMem) lmem; + + bd = N_VGetArrayPointer(b); + + DenseGETRS(M, pivots, bd); + + /* If CV_BDF, scale the correction to account for change in gamma */ + if ((lmm == CV_BDF) && (gamrat != ONE)) { + N_VScale(TWO/(ONE + gamrat), b, b); + } + + last_flag = CVDLS_SUCCESS; + return(0); +} + +/* + * ----------------------------------------------------------------- + * cvDenseFree + * ----------------------------------------------------------------- + * This routine frees memory specific to the dense linear solver. + * ----------------------------------------------------------------- + */ + +static void cvDenseFree(CVodeMem cv_mem) +{ + CVDlsMem cvdls_mem; + + cvdls_mem = (CVDlsMem) lmem; + + DestroyMat(M); + DestroyMat(savedJ); + DestroyArray(pivots); + free(cvdls_mem); cvdls_mem = NULL; +} + +/* + * ================================================================ + * + * PART II - backward problems + * + * ================================================================ + */ + +/* + * CVDenseB is a wraper around CVDense. It attaches the CVSDENSE linear solver + * to the backward problem memory block. + */ + +int CVDenseB(void *cvode_mem, int which, int nB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + CVDlsMemB cvdlsB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDENSE", "CVDenseB", MSGD_CVMEM_NULL); + return(CVDLS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CVDLS_NO_ADJ, "CVSDENSE", "CVDenseB", MSGD_NO_ADJ); + return(CVDLS_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= ca_mem->ca_nbckpbs ) { + cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSDENSE", "CVDenseB", MSGD_BAD_WHICH); + return(CVDLS_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + /* Get memory for CVDlsMemRecB */ + cvdlsB_mem = (CVDlsMemB) malloc(sizeof(struct CVDlsMemRecB)); + if (cvdlsB_mem == NULL) { + cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSDENSE", "CVDenseB", MSGD_MEM_FAIL); + return(CVDLS_MEM_FAIL); + } + + /* set matrix type */ + cvdlsB_mem->d_typeB = SUNDIALS_DENSE; + + /* initialize Jacobian function */ + cvdlsB_mem->d_djacB = NULL; + + /* attach lmemB and lfreeB */ + cvB_mem->cv_lmem = cvdlsB_mem; + cvB_mem->cv_lfree = cvDenseFreeB; + + flag = CVDense(cvodeB_mem, nB); + + if (flag != CVDLS_SUCCESS) { + free(cvdlsB_mem); + cvdlsB_mem = NULL; + } + + return(flag); +} + +/* + * cvDenseFreeB frees the memory associated with the CVSDENSE linear + * solver for backward integration. + */ + +static void cvDenseFreeB(CVodeBMem cvB_mem) +{ + CVDlsMemB cvdlsB_mem; + + cvdlsB_mem = (CVDlsMemB) (cvB_mem->cv_lmem); + + free(cvdlsB_mem); +} + diff --git a/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_diag.c b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_diag.c new file mode 100644 index 0000000..f1fb320 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_diag.c @@ -0,0 +1,507 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.7 $ + * $Date: 2007/11/26 16:19:59 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the CVDIAG linear solver. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "cvodes_diag_impl.h" +#include "cvodes_impl.h" + +/* Other Constants */ + +#define FRACT RCONST(0.1) +#define ONE RCONST(1.0) + +/* CVDIAG linit, lsetup, lsolve, and lfree routines */ + +static int CVDiagInit(CVodeMem cv_mem); + +static int CVDiagSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, + N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1, + N_Vector vtemp2, N_Vector vtemp3); + +static int CVDiagSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector ycur, N_Vector fcur); + +static void CVDiagFree(CVodeMem cv_mem); + + +/* + * ================================================================ + * + * PART I - forward problems + * + * ================================================================ + */ + + +/* Readability Replacements */ + +#define lrw1 (cv_mem->cv_lrw1) +#define liw1 (cv_mem->cv_liw1) +#define f (cv_mem->cv_f) +#define uround (cv_mem->cv_uround) +#define tn (cv_mem->cv_tn) +#define h (cv_mem->cv_h) +#define rl1 (cv_mem->cv_rl1) +#define gamma (cv_mem->cv_gamma) +#define ewt (cv_mem->cv_ewt) +#define nfe (cv_mem->cv_nfe) +#define zn (cv_mem->cv_zn) +#define linit (cv_mem->cv_linit) +#define lsetup (cv_mem->cv_lsetup) +#define lsolve (cv_mem->cv_lsolve) +#define lfree (cv_mem->cv_lfree) +#define lmem (cv_mem->cv_lmem) +#define vec_tmpl (cv_mem->cv_tempv) +#define setupNonNull (cv_mem->cv_setupNonNull) + +#define gammasv (cvdiag_mem->di_gammasv) +#define M (cvdiag_mem->di_M) +#define bit (cvdiag_mem->di_bit) +#define bitcomp (cvdiag_mem->di_bitcomp) +#define nfeDI (cvdiag_mem->di_nfeDI) +#define last_flag (cvdiag_mem->di_last_flag) + + +/* + * ----------------------------------------------------------------- + * CVDiag + * ----------------------------------------------------------------- + * This routine initializes the memory record and sets various function + * fields specific to the diagonal linear solver module. CVDense first + * calls the existing lfree routine if this is not NULL. Then it sets + * the cv_linit, cv_lsetup, cv_lsolve, cv_lfree fields in (*cvode_mem) + * to be CVDiagInit, CVDiagSetup, CVDiagSolve, and CVDiagFree, + * respectively. It allocates memory for a structure of type + * CVDiagMemRec and sets the cv_lmem field in (*cvode_mem) to the + * address of this structure. It sets setupNonNull in (*cvode_mem) to + * TRUE. Finally, it allocates memory for M, bit, and bitcomp. + * The CVDiag return value is SUCCESS = 0, LMEM_FAIL = -1, or + * LIN_ILL_INPUT=-2. + * ----------------------------------------------------------------- + */ + +int CVDiag(void *cvode_mem) +{ + CVodeMem cv_mem; + CVDiagMem cvdiag_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVDIAG_MEM_NULL, "CVDIAG", "CVDiag", MSGDG_CVMEM_NULL); + return(CVDIAG_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Check if N_VCompare and N_VInvTest are present */ + if(vec_tmpl->ops->nvcompare == NULL || + vec_tmpl->ops->nvinvtest == NULL) { + cvProcessError(cv_mem, CVDIAG_ILL_INPUT, "CVDIAG", "CVDiag", MSGDG_BAD_NVECTOR); + return(CVDIAG_ILL_INPUT); + } + + if (lfree != NULL) lfree(cv_mem); + + /* Set four main function fields in cv_mem */ + linit = CVDiagInit; + lsetup = CVDiagSetup; + lsolve = CVDiagSolve; + lfree = CVDiagFree; + + /* Get memory for CVDiagMemRec */ + cvdiag_mem = NULL; + cvdiag_mem = (CVDiagMem) malloc(sizeof(CVDiagMemRec)); + if (cvdiag_mem == NULL) { + cvProcessError(cv_mem, CVDIAG_MEM_FAIL, "CVDIAG", "CVDiag", MSGDG_MEM_FAIL); + return(CVDIAG_MEM_FAIL); + } + + last_flag = CVDIAG_SUCCESS; + + /* Set flag setupNonNull = TRUE */ + setupNonNull = TRUE; + + /* Allocate memory for M, bit, and bitcomp */ + + M = N_VClone(vec_tmpl); + if (M == NULL) { + cvProcessError(cv_mem, CVDIAG_MEM_FAIL, "CVDIAG", "CVDiag", MSGDG_MEM_FAIL); + free(cvdiag_mem); cvdiag_mem = NULL; + return(CVDIAG_MEM_FAIL); + } + bit = N_VClone(vec_tmpl); + if (bit == NULL) { + cvProcessError(cv_mem, CVDIAG_MEM_FAIL, "CVDIAG", "CVDiag", MSGDG_MEM_FAIL); + N_VDestroy(M); + free(cvdiag_mem); cvdiag_mem = NULL; + return(CVDIAG_MEM_FAIL); + } + bitcomp = N_VClone(vec_tmpl); + if (bitcomp == NULL) { + cvProcessError(cv_mem, CVDIAG_MEM_FAIL, "CVDIAG", "CVDiag", MSGDG_MEM_FAIL); + N_VDestroy(M); + N_VDestroy(bit); + free(cvdiag_mem); cvdiag_mem = NULL; + return(CVDIAG_MEM_FAIL); + } + + /* Attach linear solver memory to integrator memory */ + lmem = cvdiag_mem; + + return(CVDIAG_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVDiagGetWorkSpace + * ----------------------------------------------------------------- + */ + +int CVDiagGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS) +{ + CVodeMem cv_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVDIAG_MEM_NULL, "CVDIAG", "CVDiagGetWorkSpace", MSGDG_CVMEM_NULL); + return(CVDIAG_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + *lenrwLS = 3*lrw1; + *leniwLS = 3*liw1; + + return(CVDIAG_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVDiagGetNumRhsEvals + * ----------------------------------------------------------------- + */ + +int CVDiagGetNumRhsEvals(void *cvode_mem, long int *nfevalsLS) +{ + CVodeMem cv_mem; + CVDiagMem cvdiag_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVDIAG_MEM_NULL, "CVDIAG", "CVDiagGetNumRhsEvals", MSGDG_CVMEM_NULL); + return(CVDIAG_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + cvProcessError(cv_mem, CVDIAG_LMEM_NULL, "CVDIAG", "CVDiagGetNumRhsEvals", MSGDG_LMEM_NULL); + return(CVDIAG_LMEM_NULL); + } + cvdiag_mem = (CVDiagMem) lmem; + + *nfevalsLS = nfeDI; + + return(CVDIAG_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVDiagGetLastFlag + * ----------------------------------------------------------------- + */ + +int CVDiagGetLastFlag(void *cvode_mem, int *flag) +{ + CVodeMem cv_mem; + CVDiagMem cvdiag_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVDIAG_MEM_NULL, "CVDIAG", "CVDiagGetLastFlag", MSGDG_CVMEM_NULL); + return(CVDIAG_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + cvProcessError(cv_mem, CVDIAG_LMEM_NULL, "CVDIAG", "CVDiagGetLastFlag", MSGDG_LMEM_NULL); + return(CVDIAG_LMEM_NULL); + } + cvdiag_mem = (CVDiagMem) lmem; + + *flag = last_flag; + + return(CVDIAG_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVDiagGetReturnFlagName + * ----------------------------------------------------------------- + */ + +char *CVDiagGetReturnFlagName(int flag) +{ + char *name; + + name = (char *)malloc(30*sizeof(char)); + + switch(flag) { + case CVDIAG_SUCCESS: + sprintf(name,"CVDIAG_SUCCESS"); + break; + case CVDIAG_MEM_NULL: + sprintf(name,"CVDIAG_MEM_NULL"); + break; + case CVDIAG_LMEM_NULL: + sprintf(name,"CVDIAG_LMEM_NULL"); + break; + case CVDIAG_ILL_INPUT: + sprintf(name,"CVDIAG_ILL_INPUT"); + break; + case CVDIAG_MEM_FAIL: + sprintf(name,"CVDIAG_MEM_FAIL"); + break; + case CVDIAG_INV_FAIL: + sprintf(name,"CVDIAG_INV_FAIL"); + break; + case CVDIAG_RHSFUNC_UNRECVR: + sprintf(name,"CVDIAG_RHSFUNC_UNRECVR"); + break; + case CVDIAG_RHSFUNC_RECVR: + sprintf(name,"CVDIAG_RHSFUNC_RECVR"); + break; + case CVDIAG_NO_ADJ: + sprintf(name,"CVDIAG_NO_ADJ"); + break; + default: + sprintf(name,"NONE"); + } + + return(name); +} + +/* + * ----------------------------------------------------------------- + * CVDiagInit + * ----------------------------------------------------------------- + * This routine does remaining initializations specific to the diagonal + * linear solver. + * ----------------------------------------------------------------- + */ + +static int CVDiagInit(CVodeMem cv_mem) +{ + CVDiagMem cvdiag_mem; + + cvdiag_mem = (CVDiagMem) lmem; + + nfeDI = 0; + + last_flag = CVDIAG_SUCCESS; + return(0); +} + +/* + * ----------------------------------------------------------------- + * CVDiagSetup + * ----------------------------------------------------------------- + * This routine does the setup operations for the diagonal linear + * solver. It constructs a diagonal approximation to the Newton matrix + * M = I - gamma*J, updates counters, and inverts M. + * ----------------------------------------------------------------- + */ + +static int CVDiagSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, + N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1, + N_Vector vtemp2, N_Vector vtemp3) +{ + realtype r; + N_Vector ftemp, y; + booleantype invOK; + CVDiagMem cvdiag_mem; + int retval; + + cvdiag_mem = (CVDiagMem) lmem; + + /* Rename work vectors for use as temporary values of y and f */ + ftemp = vtemp1; + y = vtemp2; + + /* Form y with perturbation = FRACT*(func. iter. correction) */ + r = FRACT * rl1; + N_VLinearSum(h, fpred, -ONE, zn[1], ftemp); + N_VLinearSum(r, ftemp, ONE, ypred, y); + + /* Evaluate f at perturbed y */ + retval = f(tn, y, M, cv_mem->cv_user_data); + nfeDI++; + if (retval < 0) { + cvProcessError(cv_mem, CVDIAG_RHSFUNC_UNRECVR, "CVDIAG", "CVDiagSetup", MSGDG_RHSFUNC_FAILED); + last_flag = CVDIAG_RHSFUNC_UNRECVR; + return(-1); + } + if (retval > 0) { + last_flag = CVDIAG_RHSFUNC_RECVR; + return(1); + } + + /* Construct M = I - gamma*J with J = diag(deltaf_i/deltay_i) */ + N_VLinearSum(ONE, M, -ONE, fpred, M); + N_VLinearSum(FRACT, ftemp, -h, M, M); + N_VProd(ftemp, ewt, y); + /* Protect against deltay_i being at roundoff level */ + N_VCompare(uround, y, bit); + N_VAddConst(bit, -ONE, bitcomp); + N_VProd(ftemp, bit, y); + N_VLinearSum(FRACT, y, -ONE, bitcomp, y); + N_VDiv(M, y, M); + N_VProd(M, bit, M); + N_VLinearSum(ONE, M, -ONE, bitcomp, M); + + /* Invert M with test for zero components */ + invOK = N_VInvTest(M, M); + if (!invOK) { + last_flag = CVDIAG_INV_FAIL; + return(1); + } + + /* Set jcur = TRUE, save gamma in gammasv, and return */ + *jcurPtr = TRUE; + gammasv = gamma; + last_flag = CVDIAG_SUCCESS; + return(0); +} + +/* + * ----------------------------------------------------------------- + * CVDiagSolve + * ----------------------------------------------------------------- + * This routine performs the solve operation for the diagonal linear + * solver. If necessary it first updates gamma in M = I - gamma*J. + * ----------------------------------------------------------------- + */ + +static int CVDiagSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector ycur, N_Vector fcur) +{ + booleantype invOK; + realtype r; + CVDiagMem cvdiag_mem; + + cvdiag_mem = (CVDiagMem) lmem; + + /* If gamma has changed, update factor in M, and save gamma value */ + + if (gammasv != gamma) { + r = gamma / gammasv; + N_VInv(M, M); + N_VAddConst(M, -ONE, M); + N_VScale(r, M, M); + N_VAddConst(M, ONE, M); + invOK = N_VInvTest(M, M); + if (!invOK) { + last_flag = CVDIAG_INV_FAIL; + return (1); + } + gammasv = gamma; + } + + /* Apply M-inverse to b */ + N_VProd(b, M, b); + + last_flag = CVDIAG_SUCCESS; + return(0); +} + +/* + * ----------------------------------------------------------------- + * CVDiagFree + * ----------------------------------------------------------------- + * This routine frees memory specific to the diagonal linear solver. + * ----------------------------------------------------------------- + */ + +static void CVDiagFree(CVodeMem cv_mem) +{ + CVDiagMem cvdiag_mem; + + cvdiag_mem = (CVDiagMem) lmem; + + N_VDestroy(M); + N_VDestroy(bit); + N_VDestroy(bitcomp); + free(cvdiag_mem); cvdiag_mem = NULL; +} + + +/* + * ================================================================ + * + * PART II - backward problems + * + * ================================================================ + */ + + +/* + * CVDiagB + * + * Wrappers for the backward phase around the corresponding + * CVODES functions + */ + +int CVDiagB(void *cvode_mem, int which) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVDIAG_MEM_NULL, "CVSDIAG", "CVDiagB", MSGDG_CVMEM_NULL); + return(CVDIAG_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CVDIAG_NO_ADJ, "CVSDIAG", "CVDiagB", MSGDG_NO_ADJ); + return(CVDIAG_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= ca_mem->ca_nbckpbs ) { + cvProcessError(cv_mem, CVDIAG_ILL_INPUT, "CVSDIAG", "CVDiagB", MSGDG_BAD_WHICH); + return(CVDIAG_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + flag = CVDiag(cvodeB_mem); + + return(flag); +} + diff --git a/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_diag_impl.h b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_diag_impl.h new file mode 100644 index 0000000..aa39e8d --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_diag_impl.h @@ -0,0 +1,68 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.4 $ + * $Date: 2007/03/22 18:05:51 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Implementation header file for the diagonal linear solver, CVDIAG. + * ----------------------------------------------------------------- + */ + +#ifndef _CVSDIAG_IMPL_H +#define _CVSDIAG_IMPL_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Types: CVDiagMemRec, CVDiagMem + * ----------------------------------------------------------------- + * The type CVDiagMem is pointer to a CVDiagMemRec. + * This structure contains CVDiag solver-specific data. + * ----------------------------------------------------------------- + */ + +typedef struct { + + realtype di_gammasv; /* gammasv = gamma at the last call to setup */ + /* or solve */ + + N_Vector di_M; /* M = (I - gamma J)^{-1} , gamma = h / l1 */ + + N_Vector di_bit; /* temporary storage vector */ + + N_Vector di_bitcomp; /* temporary storage vector */ + + long int di_nfeDI; /* no. of calls to f due to difference + quotient diagonal Jacobian approximation */ + + int di_last_flag; /* last error return flag */ + +} CVDiagMemRec, *CVDiagMem; + +/* Error Messages */ + +#define MSGDG_CVMEM_NULL "Integrator memory is NULL." +#define MSGDG_MEM_FAIL "A memory request failed." +#define MSGDG_BAD_NVECTOR "A required vector operation is not implemented." +#define MSGDG_LMEM_NULL "CVDIAG memory is NULL." +#define MSGDG_RHSFUNC_FAILED "The right-hand side routine failed in an unrecoverable manner." + +#define MSGDG_NO_ADJ "Illegal attempt to call before calling CVodeAdjMalloc." +#define MSGDG_BAD_WHICH "Illegal value for which." + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_direct.c b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_direct.c new file mode 100644 index 0000000..191c0b3 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_direct.c @@ -0,0 +1,711 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.9 $ + * $Date: 2008/04/18 19:42:40 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the CVSDLS linear solvers + * ----------------------------------------------------------------- + */ + +/* + * ================================================================= + * IMPORTED HEADER FILES + * ================================================================= + */ + +#include +#include + +#include "cvodes_impl.h" +#include "cvodes_direct_impl.h" +#include + +/* + * ================================================================= + * FUNCTION SPECIFIC CONSTANTS + * ================================================================= + */ + +/* Constant for DQ Jacobian approximation */ +#define MIN_INC_MULT RCONST(1000.0) + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) +#define TWO RCONST(2.0) + +/* + * ================================================================= + * PRIVATE FUNCTION PROTOTYPES + * ================================================================= + */ + +static int cvDlsDenseJacBWrapper(int nB, realtype t, + N_Vector yB, N_Vector fyB, + DlsMat JB, void *cvode_mem, + N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B); + +static int cvDlsBandJacBWrapper(int nB, int mupperB, int mlowerB, + realtype t, N_Vector yB, N_Vector fyB, + DlsMat Jac, void *cvode_mem, + N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B); + + +/* + * ================================================================= + * READIBILITY REPLACEMENTS + * ================================================================= + */ + +#define f (cv_mem->cv_f) +#define user_data (cv_mem->cv_user_data) +#define uround (cv_mem->cv_uround) +#define nst (cv_mem->cv_nst) +#define tn (cv_mem->cv_tn) +#define h (cv_mem->cv_h) +#define gamma (cv_mem->cv_gamma) +#define gammap (cv_mem->cv_gammap) +#define gamrat (cv_mem->cv_gamrat) +#define ewt (cv_mem->cv_ewt) + +#define lmem (cv_mem->cv_lmem) + +#define mtype (cvdls_mem->d_type) +#define n (cvdls_mem->d_n) +#define ml (cvdls_mem->d_ml) +#define mu (cvdls_mem->d_mu) +#define smu (cvdls_mem->d_smu) +#define jacDQ (cvdls_mem->d_jacDQ) +#define djac (cvdls_mem->d_djac) +#define bjac (cvdls_mem->d_bjac) +#define M (cvdls_mem->d_M) +#define savedJ (cvdls_mem->d_savedJ) +#define pivots (cvdls_mem->d_pivots) +#define nstlj (cvdls_mem->d_nstlj) +#define nje (cvdls_mem->d_nje) +#define nfeDQ (cvdls_mem->d_nfeDQ) +#define last_flag (cvdls_mem->d_last_flag) + +/* + * ================================================================= + * EXPORTED FUNCTIONS (FORWARD INTEGRATION) + * ================================================================= + */ + +/* + * CVDlsSetDenseJacFn specifies the dense Jacobian function. + */ +int CVDlsSetDenseJacFn(void *cvode_mem, CVDlsDenseJacFn jac) +{ + CVodeMem cv_mem; + CVDlsMem cvdls_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVDLS_MEM_NULL, "CVDLS", "CVDlsSetDenseJacFn", MSGD_CVMEM_NULL); + return(CVDLS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS", "CVDlsSetDenseJacFn", MSGD_LMEM_NULL); + return(CVDLS_LMEM_NULL); + } + cvdls_mem = (CVDlsMem) lmem; + + if (jac != NULL) { + jacDQ = FALSE; + djac = jac; + } else { + jacDQ = TRUE; + } + + return(CVDLS_SUCCESS); +} + +/* + * CVDlsSetBandJacFn specifies the band Jacobian function. + */ +int CVDlsSetBandJacFn(void *cvode_mem, CVDlsBandJacFn jac) +{ + CVodeMem cv_mem; + CVDlsMem cvdls_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVDLS_MEM_NULL, "CVDLS", "CVDlsSetBandJacFn", MSGD_CVMEM_NULL); + return(CVDLS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS", "CVDlsSetBandJacFn", MSGD_LMEM_NULL); + return(CVDLS_LMEM_NULL); + } + cvdls_mem = (CVDlsMem) lmem; + + if (jac != NULL) { + jacDQ = FALSE; + bjac = jac; + } else { + jacDQ = TRUE; + } + + return(CVDLS_SUCCESS); +} + +/* + * CVDlsGetWorkSpace returns the length of workspace allocated for the + * CVDLS linear solver. + */ +int CVDlsGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS) +{ + CVodeMem cv_mem; + CVDlsMem cvdls_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS", "CVDlsGetWorkSpace", MSGD_CVMEM_NULL); + return(CVDLS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVSDLS", "CVDlsGetWorkSpace", MSGD_LMEM_NULL); + return(CVDLS_LMEM_NULL); + } + cvdls_mem = (CVDlsMem) lmem; + + if (mtype == SUNDIALS_DENSE) { + *lenrwLS = 2*n*n; + *leniwLS = n; + } else if (mtype == SUNDIALS_BAND) { + *lenrwLS = n*(smu + mu + 2*ml + 2); + *leniwLS = n; + } + + return(CVDLS_SUCCESS); +} + +/* + * CVDlsGetNumJacEvals returns the number of Jacobian evaluations. + */ +int CVDlsGetNumJacEvals(void *cvode_mem, long int *njevals) +{ + CVodeMem cv_mem; + CVDlsMem cvdls_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS", "CVDlsGetNumJacEvals", MSGD_CVMEM_NULL); + return(CVDLS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVSDLS", "CVDlsGetNumJacEvals", MSGD_LMEM_NULL); + return(CVDLS_LMEM_NULL); + } + cvdls_mem = (CVDlsMem) lmem; + + *njevals = nje; + + return(CVDLS_SUCCESS); +} + +/* + * CVDlsGetNumRhsEvals returns the number of calls to the ODE function + * needed for the DQ Jacobian approximation. + */ +int CVDlsGetNumRhsEvals(void *cvode_mem, long int *nfevalsLS) +{ + CVodeMem cv_mem; + CVDlsMem cvdls_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS", "CVDlsGetNumRhsEvals", MSGD_CVMEM_NULL); + return(CVDLS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVSDLS", "CVDlsGetNumRhsEvals", MSGD_LMEM_NULL); + return(CVDLS_LMEM_NULL); + } + cvdls_mem = (CVDlsMem) lmem; + + *nfevalsLS = nfeDQ; + + return(CVDLS_SUCCESS); +} + +/* + * CVDlsGetReturnFlagName returns the name associated with a CVDLS + * return value. + */ +char *CVDlsGetReturnFlagName(int flag) +{ + char *name; + + name = (char *)malloc(30*sizeof(char)); + + switch(flag) { + case CVDLS_SUCCESS: + sprintf(name,"CVDLS_SUCCESS"); + break; + case CVDLS_MEM_NULL: + sprintf(name,"CVDLS_MEM_NULL"); + break; + case CVDLS_LMEM_NULL: + sprintf(name,"CVDLS_LMEM_NULL"); + break; + case CVDLS_ILL_INPUT: + sprintf(name,"CVDLS_ILL_INPUT"); + break; + case CVDLS_MEM_FAIL: + sprintf(name,"CVDLS_MEM_FAIL"); + break; + case CVDLS_JACFUNC_UNRECVR: + sprintf(name,"CVDLS_JACFUNC_UNRECVR"); + break; + case CVDLS_JACFUNC_RECVR: + sprintf(name,"CVDLS_JACFUNC_RECVR"); + break; + default: + sprintf(name,"NONE"); + } + + return(name); +} + +/* + * CVDlsGetLastFlag returns the last flag set in a CVDLS function. + */ +int CVDlsGetLastFlag(void *cvode_mem, int *flag) +{ + CVodeMem cv_mem; + CVDlsMem cvdls_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS", "CVDlsGetLastFlag", MSGD_CVMEM_NULL); + return(CVDLS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVSDLS", "CVDlsGetLastFlag", MSGD_LMEM_NULL); + return(CVDLS_LMEM_NULL); + } + cvdls_mem = (CVDlsMem) lmem; + + *flag = last_flag; + + return(CVDLS_SUCCESS); +} + +/* + * ================================================================= + * DQ JACOBIAN APPROXIMATIONS + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * cvDlsDenseDQJac + * ----------------------------------------------------------------- + * This routine generates a dense difference quotient approximation to + * the Jacobian of f(t,y). It assumes that a dense matrix of type + * DlsMat is stored column-wise, and that elements within each column + * are contiguous. The address of the jth column of J is obtained via + * the macro DENSE_COL and this pointer is associated with an N_Vector + * using the N_VGetArrayPointer/N_VSetArrayPointer functions. + * Finally, the actual computation of the jth column of the Jacobian is + * done with a call to N_VLinearSum. + * ----------------------------------------------------------------- + */ + +int cvDlsDenseDQJac(int N, realtype t, + N_Vector y, N_Vector fy, + DlsMat Jac, void *data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + realtype fnorm, minInc, inc, inc_inv, yjsaved, srur; + realtype *tmp2_data, *y_data, *ewt_data; + N_Vector ftemp, jthCol; + int j; + int retval = 0; + + CVodeMem cv_mem; + CVDlsMem cvdls_mem; + + /* data points to cvode_mem */ + cv_mem = (CVodeMem) data; + cvdls_mem = (CVDlsMem) lmem; + + /* Save pointer to the array in tmp2 */ + tmp2_data = N_VGetArrayPointer(tmp2); + + /* Rename work vectors for readibility */ + ftemp = tmp1; + jthCol = tmp2; + + /* Obtain pointers to the data for ewt, y */ + ewt_data = N_VGetArrayPointer(ewt); + y_data = N_VGetArrayPointer(y); + + /* Set minimum increment based on uround and norm of f */ + srur = RSqrt(uround); + fnorm = N_VWrmsNorm(fy, ewt); + minInc = (fnorm != ZERO) ? + (MIN_INC_MULT * ABS(h) * uround * N * fnorm) : ONE; + + for (j = 0; j < N; j++) { + + /* Generate the jth col of J(tn,y) */ + + N_VSetArrayPointer(DENSE_COL(Jac,j), jthCol); + + yjsaved = y_data[j]; + inc = MAX(srur*ABS(yjsaved), minInc/ewt_data[j]); + y_data[j] += inc; + + retval = f(t, y, ftemp, user_data); + nfeDQ++; + if (retval != 0) break; + + y_data[j] = yjsaved; + + inc_inv = ONE/inc; + N_VLinearSum(inc_inv, ftemp, -inc_inv, fy, jthCol); + + DENSE_COL(Jac,j) = N_VGetArrayPointer(jthCol); + } + + /* Restore original array pointer in tmp2 */ + N_VSetArrayPointer(tmp2_data, tmp2); + + return(retval); +} + +/* + * ----------------------------------------------------------------- + * cvDlsBandDQJac + * ----------------------------------------------------------------- + * This routine generates a banded difference quotient approximation to + * the Jacobian of f(t,y). It assumes that a band matrix of type + * DlsMat is stored column-wise, and that elements within each column + * are contiguous. This makes it possible to get the address of a column + * of J via the macro BAND_COL and to write a simple for loop to set + * each of the elements of a column in succession. + * ----------------------------------------------------------------- + */ + +int cvDlsBandDQJac(int N, int mupper, int mlower, + realtype t, N_Vector y, N_Vector fy, + DlsMat Jac, void *data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + N_Vector ftemp, ytemp; + realtype fnorm, minInc, inc, inc_inv, srur; + realtype *col_j, *ewt_data, *fy_data, *ftemp_data, *y_data, *ytemp_data; + int group, i, j, width, ngroups, i1, i2; + int retval = 0; + + CVodeMem cv_mem; + CVDlsMem cvdls_mem; + + /* data points to cvode_mem */ + cv_mem = (CVodeMem) data; + cvdls_mem = (CVDlsMem) lmem; + + /* Rename work vectors for use as temporary values of y and f */ + ftemp = tmp1; + ytemp = tmp2; + + /* Obtain pointers to the data for ewt, fy, ftemp, y, ytemp */ + ewt_data = N_VGetArrayPointer(ewt); + fy_data = N_VGetArrayPointer(fy); + ftemp_data = N_VGetArrayPointer(ftemp); + y_data = N_VGetArrayPointer(y); + ytemp_data = N_VGetArrayPointer(ytemp); + + /* Load ytemp with y = predicted y vector */ + N_VScale(ONE, y, ytemp); + + /* Set minimum increment based on uround and norm of f */ + srur = RSqrt(uround); + fnorm = N_VWrmsNorm(fy, ewt); + minInc = (fnorm != ZERO) ? + (MIN_INC_MULT * ABS(h) * uround * N * fnorm) : ONE; + + /* Set bandwidth and number of column groups for band differencing */ + width = mlower + mupper + 1; + ngroups = MIN(width, N); + + /* Loop over column groups. */ + for (group=1; group <= ngroups; group++) { + + /* Increment all y_j in group */ + for(j=group-1; j < N; j+=width) { + inc = MAX(srur*ABS(y_data[j]), minInc/ewt_data[j]); + ytemp_data[j] += inc; + } + + /* Evaluate f with incremented y */ + + retval = f(tn, ytemp, ftemp, user_data); + nfeDQ++; + if (retval != 0) break; + + /* Restore ytemp, then form and load difference quotients */ + for (j=group-1; j < N; j+=width) { + ytemp_data[j] = y_data[j]; + col_j = BAND_COL(Jac,j); + inc = MAX(srur*ABS(y_data[j]), minInc/ewt_data[j]); + inc_inv = ONE/inc; + i1 = MAX(0, j-mupper); + i2 = MIN(j+mlower, N-1); + for (i=i1; i <= i2; i++) + BAND_COL_ELEM(col_j,i,j) = inc_inv * (ftemp_data[i] - fy_data[i]); + } + } + + return(retval); +} + +/* + * ================================================================= + * BACKWARD INTEGRATION SUPPORT + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Additional readability replacements + * ----------------------------------------------------------------- + */ + +#define ytmp (ca_mem->ca_ytmp) +#define yStmp (ca_mem->ca_yStmp) +#define IMget (ca_mem->ca_IMget) + +#define mtypeB (cvdlsB_mem->d_typeB) +#define djacB (cvdlsB_mem->d_djacB) +#define bjacB (cvdlsB_mem->d_bjacB) + +/* + * ----------------------------------------------------------------- + * EXPORTED FUNCTIONS + * ----------------------------------------------------------------- + */ + +int CVDlsSetDenseJacFnB(void *cvode_mem, int which, CVDlsDenseJacFnB jacB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + CVDlsMemB cvdlsB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS", "CVDlsSetDenseJacFnB", MSGD_CVMEM_NULL); + return(CVDLS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CVDLS_NO_ADJ, "CVSDLS", "CVDlsSetDenseJacFnB", MSGD_NO_ADJ); + return(CVDLS_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= ca_mem->ca_nbckpbs ) { + cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSDLS", "CVDlsSetDenseJacFnB", MSGD_BAD_WHICH); + return(CVDLS_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + if (cvB_mem->cv_lmem == NULL) { + cvProcessError(cv_mem, CVDLS_LMEMB_NULL, "CVSDLS", "CVDlsSetDenseJacFnB", MSGD_LMEMB_NULL); + return(CVDLS_LMEMB_NULL); + } + cvdlsB_mem = (CVDlsMemB) (cvB_mem->cv_lmem); + + djacB = jacB; + + if (jacB != NULL) { + flag = CVDlsSetDenseJacFn(cvodeB_mem, cvDlsDenseJacBWrapper); + } else { + flag = CVDlsSetDenseJacFn(cvodeB_mem, NULL); + } + + return(flag); +} + +int CVDlsSetBandJacFnB(void *cvode_mem, int which, CVDlsBandJacFnB jacB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + CVDlsMemB cvdlsB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS", "CVDlsSetBandJacFnB", MSGD_CVMEM_NULL); + return(CVDLS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CVDLS_NO_ADJ, "CVSDLS", "CVDlsSetBandJacFnB", MSGD_NO_ADJ); + return(CVDLS_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= ca_mem->ca_nbckpbs ) { + cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSDLS", "CVDlsSetBandJacFnB", MSGD_BAD_WHICH); + return(CVDLS_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + if (cvB_mem->cv_lmem == NULL) { + cvProcessError(cv_mem, CVDLS_LMEMB_NULL, "CVSDLS", "CVDlsSetBandJacFnB", MSGD_LMEMB_NULL); + return(CVDLS_LMEMB_NULL); + } + cvdlsB_mem = (CVDlsMemB) (cvB_mem->cv_lmem); + + bjacB = jacB; + + if (jacB != NULL) { + flag = CVDlsSetBandJacFn(cvodeB_mem, cvDlsBandJacBWrapper); + } else { + flag = CVDlsSetBandJacFn(cvodeB_mem, NULL); + } + + return(flag); +} + + +/* + * ----------------------------------------------------------------- + * PRIVATE INTERFACE FUNCTIONS + * ----------------------------------------------------------------- + */ + +/* + * cvDlsDenseJacBWrapper + * + * This routine interfaces to the CVDlsDenseJacFnB routine provided + * by the user. cvDlsDenseJacBWrapper is of type CVDlsDenseJacFn. + * NOTE: data here contains cvode_mem + */ + + +static int cvDlsDenseJacBWrapper(int nB, realtype t, + N_Vector yB, N_Vector fyB, + DlsMat JB, void *cvode_mem, + N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + CVDlsMemB cvdlsB_mem; + int retval, flag; + + cv_mem = (CVodeMem) cvode_mem; + + ca_mem = cv_mem->cv_adj_mem; + + cvB_mem = ca_mem->ca_bckpbCrt; + + cvdlsB_mem = (CVDlsMemB) (cvB_mem->cv_lmem); + + /* Forward solution from interpolation */ + flag = IMget(cv_mem, t, ytmp, NULL); + if (flag != CV_SUCCESS) { + cvProcessError(cv_mem, -1, "CVSDLS", "cvDlsDenseJacBWrapper", MSGD_BAD_TINTERP); + return(-1); + } + + /* Call user's adjoint dense djacB routine (of type CVDlsDenseJacFnB) */ + retval = djacB(nB, t, ytmp, yB, fyB, JB, cvB_mem->cv_user_data, + tmp1B, tmp2B, tmp3B); + + return(retval); + +} + + +/* + * cvDlsBandJacBWrapper + * + * This routine interfaces to the CVBandJacFnB routine provided + * by the user. cvDlsBandJacBWrapper is of type CVDlsBandJacFn. + * NOTE: data here contains cvode_mem + */ + +static int cvDlsBandJacBWrapper(int nB, int mupperB, int mlowerB, + realtype t, N_Vector yB, N_Vector fyB, + DlsMat JB, void *cvode_mem, + N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + CVDlsMemB cvdlsB_mem; + int retval, flag; + + cv_mem = (CVodeMem) cvode_mem; + + ca_mem = cv_mem->cv_adj_mem; + + cvB_mem = ca_mem->ca_bckpbCrt; + + cvdlsB_mem = (CVDlsMemB) (cvB_mem->cv_lmem); + + /* Forward solution from interpolation */ + flag = IMget(cv_mem, t, ytmp, NULL); + if (flag != CV_SUCCESS) { + cvProcessError(cv_mem, -1, "CVSDLS", "cvDlsBandJacBWrapper", MSGD_BAD_TINTERP); + return(-1); + } + + /* Call user's adjoint band bjacB routine (of type CVDlsBandJacFnB) */ + retval = bjacB(nB, mupperB, mlowerB, t, ytmp, yB, fyB, JB, cvB_mem->cv_user_data, + tmp1B, tmp2B, tmp3B); + + return(retval); +} + diff --git a/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_direct_impl.h b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_direct_impl.h new file mode 100644 index 0000000..9ec60da --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_direct_impl.h @@ -0,0 +1,153 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.8 $ + * $Date: 2008/04/18 19:42:40 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Common implementation header file for the CVDLS linear solvers. + * ----------------------------------------------------------------- + */ + +#ifndef _CVSDLS_IMPL_H +#define _CVSDLS_IMPL_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ================================================================= + * C V S D I R E C T I N T E R N A L C O N S T A N T S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * CVDLS solver constants + * ----------------------------------------------------------------- + * CVD_MSBJ maximum number of steps between Jacobian evaluations + * CVD_DGMAX maximum change in gamma between Jacobian evaluations + * ----------------------------------------------------------------- + */ + +#define CVD_MSBJ 50 +#define CVD_DGMAX RCONST(0.2) + +/* + * ================================================================= + * PART I: F O R W A R D P R O B L E M S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Types: CVDlsMemRec, CVDlsMem + * ----------------------------------------------------------------- + * CVDlsMem is pointer to a CVDlsMemRec structure. + * ----------------------------------------------------------------- + */ + +typedef struct CVDlsMemRec { + + int d_type; /* SUNDIALS_DENSE or SUNDIALS_BAND */ + + int d_n; /* problem dimension */ + + int d_ml; /* lower bandwidth of Jacobian */ + int d_mu; /* upper bandwidth of Jacobian */ + int d_smu; /* upper bandwith of M = MIN(N-1,d_mu+d_ml) */ + + booleantype d_jacDQ; /* TRUE if using internal DQ Jacobian approx. */ + CVDlsDenseJacFn d_djac; /* dense Jacobian routine to be called */ + CVDlsBandJacFn d_bjac; /* band Jacobian routine to be called */ + void *d_J_data; /* data pointer passed to djac or bjac */ + + DlsMat d_M; /* M = I - gamma * df/dy */ + DlsMat d_savedJ; /* savedJ = old Jacobian */ + + int *d_pivots; /* pivots = pivot array for PM = LU */ + + long int d_nstlj; /* nstlj = nst at last Jacobian eval. */ + + long int d_nje; /* nje = no. of calls to jac */ + + long int d_nfeDQ; /* no. of calls to f due to DQ Jacobian approx. */ + + int d_last_flag; /* last error return flag */ + +} *CVDlsMem; + +/* + * ----------------------------------------------------------------- + * Prototypes of internal functions + * ----------------------------------------------------------------- + */ + +int cvDlsDenseDQJac(int N, realtype t, + N_Vector y, N_Vector fy, + DlsMat Jac, void *data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +int cvDlsBandDQJac(int N, int mupper, int mlower, + realtype t, N_Vector y, N_Vector fy, + DlsMat Jac, void *data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + + +/* + * ================================================================= + * PART II: B A C K W A R D P R O B L E M S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Types : CVDlsMemRecB, CVDlsMemB + * ----------------------------------------------------------------- + * A CVDLS linear solver's specification function attaches such + * a structure to the lmemB filed of CVodeBMem + * ----------------------------------------------------------------- + */ + +typedef struct CVDlsMemRecB { + + int d_typeB; + + CVDlsDenseJacFnB d_djacB; + CVDlsBandJacFnB d_bjacB; + +} *CVDlsMemB; + + +/* + * ================================================================= + * E R R O R M E S S A G E S + * ================================================================= + */ + +#define MSGD_CVMEM_NULL "Integrator memory is NULL." +#define MSGD_BAD_NVECTOR "A required vector operation is not implemented." +#define MSGD_BAD_SIZES "Illegal bandwidth parameter(s). Must have 0 <= ml, mu <= N-1." +#define MSGD_MEM_FAIL "A memory request failed." +#define MSGD_LMEM_NULL "Linear solver memory is NULL." +#define MSGD_JACFUNC_FAILED "The Jacobian routine failed in an unrecoverable manner." + + +#define MSGD_NO_ADJ "Illegal attempt to call before calling CVodeAdjMalloc." +#define MSGD_BAD_WHICH "Illegal value for which." +#define MSGD_LMEMB_NULL "Linear solver memory is NULL for the backward integration." +#define MSGD_BAD_TINTERP "Bad t for interpolation." + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_impl.h b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_impl.h new file mode 100644 index 0000000..0bb7173 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_impl.h @@ -0,0 +1,1089 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.21 $ + * $Date: 2007/11/26 16:19:59 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Implementation header file for the main CVODES integrator. + * ----------------------------------------------------------------- + */ + +#ifndef _CVODES_IMPL_H +#define _CVODES_IMPL_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +#include +#include +#include + +/* + * ================================================================= + * I N T E R N A L C V O D E S C O N S T A N T S + * ================================================================= + */ + +/* Basic CVODES constants */ + +#define ADAMS_Q_MAX 12 /* max value of q for lmm == ADAMS */ +#define BDF_Q_MAX 5 /* max value of q for lmm == BDF */ +#define Q_MAX ADAMS_Q_MAX /* max value of q for either lmm */ +#define L_MAX (Q_MAX+1) /* max value of L for either lmm */ +#define NUM_TESTS 5 /* number of error test quantities */ + +#define HMIN_DEFAULT RCONST(0.0) /* hmin default value */ +#define HMAX_INV_DEFAULT RCONST(0.0) /* hmax_inv default value */ +#define MXHNIL_DEFAULT 10 /* mxhnil default value */ +#define MXSTEP_DEFAULT 500 /* mxstep default value */ + +/* + * ================================================================= + * F O R W A R D P O I N T E R R E F E R E N C E S + * ================================================================= + */ + +typedef struct CVadjMemRec *CVadjMem; +typedef struct CkpntMemRec *CkpntMem; +typedef struct DtpntMemRec *DtpntMem; +typedef struct CVodeBMemRec *CVodeBMem; + +/* + * ================================================================= + * M A I N I N T E G R A T O R M E M O R Y B L O C K + * ================================================================= + */ + + +/* + * ----------------------------------------------------------------- + * Types: struct CVodeMemRec, CVodeMem + * ----------------------------------------------------------------- + * The type CVodeMem is type pointer to struct CVodeMemRec. + * This structure contains fields to keep track of problem state. + * ----------------------------------------------------------------- + */ + +typedef struct CVodeMemRec { + + realtype cv_uround; /* machine unit roundoff */ + + /*-------------------------- + Problem Specification Data + --------------------------*/ + + CVRhsFn cv_f; /* y' = f(t,y(t)) */ + void *cv_user_data; /* user pointer passed to f */ + + int cv_lmm; /* lmm = ADAMS or BDF */ + int cv_iter; /* iter = FUNCTIONAL or NEWTON */ + + int cv_itol; /* itol = CV_SS, CV_SV, or CV_WF, or CV_NN */ + realtype cv_reltol; /* relative tolerance */ + realtype cv_Sabstol; /* scalar absolute tolerance */ + N_Vector cv_Vabstol; /* vector absolute tolerance */ + booleantype cv_user_efun; /* TRUE if user sets efun */ + CVEwtFn cv_efun; /* function to set ewt */ + void *cv_e_data; /* user pointer passed to efun */ + double tMax; /* Maximum integration time, Added by Joep Vanlier */ + + /*----------------------- + Quadrature Related Data + -----------------------*/ + + booleantype cv_quadr; /* TRUE if integrating quadratures */ + + CVQuadRhsFn cv_fQ; /* q' = fQ(t, y(t)) */ + + booleantype cv_errconQ; /* TRUE if quadrs. are included in error test */ + + int cv_itolQ; /* itolQ = CV_SS or CV_SV */ + realtype cv_reltolQ; /* relative tolerance for quadratures */ + realtype cv_SabstolQ; /* scalar absolute tolerance for quadratures */ + N_Vector cv_VabstolQ; /* vector absolute tolerance for quadratures */ + + /*------------------------ + Sensitivity Related Data + ------------------------*/ + + booleantype cv_sensi; /* TRUE if computing sensitivities */ + + int cv_Ns; /* Number of sensitivities */ + + int cv_ism; /* ism = SIMULTANEOUS or STAGGERED */ + + CVSensRhsFn cv_fS; /* fS = (df/dy)*yS + (df/dp) */ + CVSensRhs1Fn cv_fS1; /* fS1 = (df/dy)*yS_i + (df/dp) */ + void *cv_fS_data; /* data pointer passed to fS */ + booleantype cv_fSDQ; /* TRUE if using internal DQ functions */ + int cv_ifS; /* ifS = ALLSENS or ONESENS */ + + realtype *cv_p; /* parameters in f(t,y,p) */ + realtype *cv_pbar; /* scale factors for parameters */ + int *cv_plist; /* list of sensitivities */ + int cv_DQtype; /* central/forward finite differences */ + realtype cv_DQrhomax; /* cut-off value for separate/simultaneous FD */ + + booleantype cv_errconS; /* TRUE if yS are considered in err. control */ + + int cv_itolS; + realtype cv_reltolS; /* relative tolerance for sensitivities */ + realtype *cv_SabstolS; /* scalar absolute tolerances for sensi. */ + N_Vector *cv_VabstolS; /* vector absolute tolerances for sensi. */ + + /*----------------------------------- + Quadrature Sensitivity Related Data + -----------------------------------*/ + + booleantype cv_quadr_sensi; /* TRUE if computing sensitivties of quadrs. */ + + CVQuadSensRhsFn cv_fQS; /* fQS = (dfQ/dy)*yS + (dfQ/dp) */ + void *cv_fQS_data; /* data pointer passed to fQS */ + booleantype cv_fQSDQ; /* TRUE if using internal DQ functions */ + + booleantype cv_errconQS; /* TRUE if yQS are considered in err. con. */ + + int cv_itolQS; + realtype cv_reltolQS; /* relative tolerance for yQS */ + realtype *cv_SabstolQS; /* scalar absolute tolerances for yQS */ + N_Vector *cv_VabstolQS; /* vector absolute tolerances for yQS */ + + /*----------------------- + Nordsieck History Array + -----------------------*/ + + N_Vector cv_zn[L_MAX]; /* Nordsieck array, of size N x (q+1). + zn[j] is a vector of length N (j=0,...,q) + zn[j] = [1/factorial(j)] * h^j * + (jth derivative of the interpolating poly.) */ + + /*------------------- + Vectors of length N + -------------------*/ + + N_Vector cv_ewt; /* error weight vector */ + N_Vector cv_y; /* y is used as temporary storage by the solver. + The memory is provided by the user to CVode + where the vector is named yout. */ + N_Vector cv_acor; /* In the context of the solution of the + nonlinear equation, acor = y_n(m) - y_n(0). + On return, this vector is scaled to give + the estimated local error in y. */ + N_Vector cv_tempv; /* temporary storage vector */ + N_Vector cv_ftemp; /* temporary storage vector */ + + /*-------------------------- + Quadrature Related Vectors + --------------------------*/ + + N_Vector cv_znQ[L_MAX]; /* Nordsieck arrays for quadratures */ + N_Vector cv_ewtQ; /* error weight vector for quadratures */ + N_Vector cv_yQ; /* Unlike y, yQ is not allocated by the user */ + N_Vector cv_acorQ; /* acorQ = yQ_n(m) - yQ_n(0) */ + N_Vector cv_tempvQ; /* temporary storage vector (~ tempv) */ + + /*--------------------------- + Sensitivity Related Vectors + ---------------------------*/ + + N_Vector *cv_znS[L_MAX]; /* Nordsieck arrays for sensitivities */ + N_Vector *cv_ewtS; /* error weight vectors for sensitivities */ + N_Vector *cv_yS; /* yS=yS0 (allocated by the user) */ + N_Vector *cv_acorS; /* acorS = yS_n(m) - yS_n(0) */ + N_Vector *cv_tempvS; /* temporary storage vector (~ tempv) */ + N_Vector *cv_ftempS; /* temporary storage vector (~ ftemp) */ + + booleantype cv_stgr1alloc; /* Did we allocate ncfS1, ncfnS1, and nniS1? */ + + /*-------------------------------------- + Quadrature Sensitivity Related Vectors + --------------------------------------*/ + + N_Vector *cv_znQS[L_MAX]; /* Nordsieck arrays for quadr. sensitivities */ + N_Vector *cv_ewtQS; /* error weight vectors for sensitivities */ + N_Vector *cv_yQS; /* Unlike yS, yQS is not allocated by the user */ + N_Vector *cv_acorQS; /* acorQS = yQS_n(m) - yQS_n(0) */ + N_Vector *cv_tempvQS; /* temporary storage vector (~ tempv) */ + N_Vector cv_ftempQ; /* temporary storage vector (~ ftemp) */ + + /*----------------- + Tstop information + -----------------*/ + + booleantype cv_tstopset; + realtype cv_tstop; + + /*--------- + Step Data + ---------*/ + + int cv_q; /* current order */ + int cv_qprime; /* order to be used on the next step + * qprime = q-1, q, or q+1 */ + int cv_next_q; /* order to be used on the next step */ + int cv_qwait; /* number of internal steps to wait before + * considering a change in q */ + int cv_L; /* L = q + 1 */ + + realtype cv_hin; + realtype cv_h; /* current step size */ + realtype cv_hprime; /* step size to be used on the next step */ + realtype cv_next_h; /* step size to be used on the next step */ + realtype cv_eta; /* eta = hprime / h */ + realtype cv_hscale; /* value of h used in zn */ + realtype cv_tn; /* current internal value of t */ + realtype cv_tretlast; /* last value of t returned */ + + realtype cv_tau[L_MAX+1]; /* array of previous q+1 successful step + * sizes indexed from 1 to q+1 */ + realtype cv_tq[NUM_TESTS+1]; /* array of test quantities indexed from + * 1 to NUM_TESTS(=5) */ + realtype cv_l[L_MAX]; /* coefficients of l(x) (degree q poly) */ + + realtype cv_rl1; /* the scalar 1/l[1] */ + realtype cv_gamma; /* gamma = h * rl1 */ + realtype cv_gammap; /* gamma at the last setup call */ + realtype cv_gamrat; /* gamma / gammap */ + + realtype cv_crate; /* est. corrector conv. rate in Nls */ + realtype cv_crateS; /* est. corrector conv. rate in NlsStgr */ + realtype cv_acnrm; /* | acor | */ + realtype cv_acnrmQ; /* | acorQ | */ + realtype cv_acnrmS; /* | acorS | */ + realtype cv_acnrmQS; /* | acorQS | */ + realtype cv_nlscoef; /* coeficient in nonlinear convergence test */ + int cv_mnewt; /* Newton iteration counter */ + int *cv_ncfS1; /* Array of Ns local counters for conv. + * failures (used in CVStep for STAGGERED1) */ + + /*------ + Limits + ------*/ + + int cv_qmax; /* q <= qmax */ + long int cv_mxstep; /* maximum number of internal steps for one + user call */ + int cv_maxcor; /* maximum number of corrector iterations for + the solution of the nonlinear equation */ + int cv_maxcorS; + int cv_mxhnil; /* max. number of warning messages issued to the + user that t + h == t for the next internal step */ + int cv_maxnef; /* maximum number of error test failures */ + int cv_maxncf; /* maximum number of nonlinear conv. failures */ + + realtype cv_hmin; /* |h| >= hmin */ + realtype cv_hmax_inv; /* |h| <= 1/hmax_inv */ + realtype cv_etamax; /* eta <= etamax */ + + /*---------- + Counters + ----------*/ + + long int cv_nst; /* number of internal steps taken */ + + long int cv_nfe; /* number of f calls */ + long int cv_nfQe; /* number of fQ calls */ + long int cv_nfSe; /* number of fS calls */ + long int cv_nfeS; /* number of f calls from sensi DQ */ + long int cv_nfQSe; /* number of fQS calls */ + long int cv_nfQeS; /* number of fQ calls from sensi DQ */ + + + long int cv_ncfn; /* number of corrector convergence failures */ + long int cv_ncfnS; /* number of total sensi. corr. conv. failures */ + long int *cv_ncfnS1; /* number of sensi. corrector conv. failures */ + + long int cv_nni; /* number of nonlinear iterations performed */ + long int cv_nniS; /* number of total sensi. nonlinear iterations */ + long int *cv_nniS1; /* number of sensi. nonlinear iterations */ + + long int cv_netf; /* number of error test failures */ + long int cv_netfQ; /* number of quadr. error test failures */ + long int cv_netfS; /* number of sensi. error test failures */ + long int cv_netfQS; /* number of quadr. sensi. error test failures */ + + long int cv_nsetups; /* number of setup calls */ + long int cv_nsetupsS; /* number of setup calls due to sensitivities */ + + int cv_nhnil; /* number of messages issued to the user that + t + h == t for the next iternal step */ + + /*----------------------------- + Space requirements for CVODES + -----------------------------*/ + + long int cv_lrw1; /* no. of realtype words in 1 N_Vector y */ + long int cv_liw1; /* no. of integer words in 1 N_Vector y */ + long int cv_lrw1Q; /* no. of realtype words in 1 N_Vector yQ */ + long int cv_liw1Q; /* no. of integer words in 1 N_Vector yQ */ + long int cv_lrw; /* no. of realtype words in CVODES work vectors */ + long int cv_liw; /* no. of integer words in CVODES work vectors */ + + /*---------------- + Step size ratios + ----------------*/ + + realtype cv_etaqm1; /* ratio of new to old h for order q-1 */ + realtype cv_etaq; /* ratio of new to old h for order q */ + realtype cv_etaqp1; /* ratio of new to old h for order q+1 */ + + /*------------------ + Linear Solver Data + ------------------*/ + + /* Linear Solver functions to be called */ + + int (*cv_linit)(struct CVodeMemRec *cv_mem); + + int (*cv_lsetup)(struct CVodeMemRec *cv_mem, int convfail, + N_Vector ypred, N_Vector fpred, booleantype *jcurPtr, + N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3); + + int (*cv_lsolve)(struct CVodeMemRec *cv_mem, N_Vector b, N_Vector weight, + N_Vector ycur, N_Vector fcur); + + void (*cv_lfree)(struct CVodeMemRec *cv_mem); + + /* Linear Solver specific memory */ + + void *cv_lmem; + + /* Flag to request a call to the setup routine */ + + booleantype cv_forceSetup; + + /*------------ + Saved Values + ------------*/ + + int cv_qu; /* last successful q value used */ + long int cv_nstlp; /* step number of last setup call */ + realtype cv_h0u; /* actual initial stepsize */ + realtype cv_hu; /* last successful h value used */ + realtype cv_saved_tq5; /* saved value of tq[5] */ + booleantype cv_jcur; /* is Jacobian info for linear solver current? */ + realtype cv_tolsf; /* tolerance scale factor */ + int cv_qmax_alloc; /* qmax used when allocating mem */ + int cv_qmax_allocQ; /* qmax used when allocating quad. mem */ + int cv_qmax_allocS; /* qmax used when allocating sensi. mem */ + int cv_qmax_allocQS; /* qmax used when allocating quad. sensi. mem */ + int cv_indx_acor; /* index of zn vector in which acor is saved */ + booleantype cv_setupNonNull; /* Does setup do something? */ + + /*-------------------------------------------------------------------- + Flags turned ON by CVodeInit, CVodeSensMalloc, and CVodeQuadMalloc + and read by CVodeReInit, CVodeSensReInit, and CVodeQuadReInit + --------------------------------------------------------------------*/ + + booleantype cv_VabstolMallocDone; + booleantype cv_MallocDone; + + booleantype cv_VabstolQMallocDone; + booleantype cv_QuadMallocDone; + + booleantype cv_VabstolSMallocDone; + booleantype cv_SabstolSMallocDone; + booleantype cv_SensMallocDone; + + booleantype cv_VabstolQSMallocDone; + booleantype cv_SabstolQSMallocDone; + booleantype cv_QuadSensMallocDone; + + /*------------------------------------------- + Error handler function and error ouput file + -------------------------------------------*/ + + CVErrHandlerFn cv_ehfun; /* Error messages are handled by ehfun */ + void *cv_eh_data; /* dats pointer passed to ehfun */ + FILE *cv_errfp; /* CVODES error messages are sent to errfp */ + + /*------------------------- + Stability Limit Detection + -------------------------*/ + + booleantype cv_sldeton; /* Is Stability Limit Detection on? */ + realtype cv_ssdat[6][4]; /* scaled data array for STALD */ + int cv_nscon; /* counter for STALD method */ + long int cv_nor; /* counter for number of order reductions */ + + /*---------------- + Rootfinding Data + ----------------*/ + + CVRootFn cv_gfun; /* Function g for roots sought */ + int cv_nrtfn; /* number of components of g */ + int *cv_iroots; /* array for root information */ + int *cv_rootdir; /* array specifying direction of zero-crossing */ + realtype cv_tlo; /* nearest endpoint of interval in root search */ + realtype cv_thi; /* farthest endpoint of interval in root search */ + realtype cv_trout; /* t value returned by rootfinding routine */ + realtype *cv_glo; /* saved array of g values at t = tlo */ + realtype *cv_ghi; /* saved array of g values at t = thi */ + realtype *cv_grout; /* array of g values at t = trout */ + realtype cv_toutc; /* copy of tout (if NORMAL mode) */ + realtype cv_ttol; /* tolerance on root location trout */ + int cv_taskc; /* copy of parameter itask */ + int cv_irfnd; /* flag showing whether last step had a root */ + long int cv_nge; /* counter for g evaluations */ + booleantype *cv_gactive; /* array with active/inactive event functions */ + int cv_mxgnull; /* number of warning messages about possible g==0 */ + + /*------------------------ + Adjoint sensitivity data + ------------------------*/ + + booleantype cv_adj; /* TRUE if performing ASA */ + + struct CVadjMemRec *cv_adj_mem; /* Pointer to adjoint memory structure */ + + booleantype cv_adjMallocDone; + +} *CVodeMem; + + +/* + * ================================================================= + * A D J O I N T M O D U L E M E M O R Y B L O C K + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Types : struct CkpntMemRec, CkpntMem + * ----------------------------------------------------------------- + * The type CkpntMem is type pointer to struct CkpntMemRec. + * This structure contains fields to store all information at a + * check point that is needed to 'hot' start cvodes. + * ----------------------------------------------------------------- + */ + +struct CkpntMemRec { + + /* Integration limits */ + realtype ck_t0; + realtype ck_t1; + + /* Nordsieck History Array */ + N_Vector ck_zn[L_MAX]; + + /* Do we need to carry quadratures? */ + booleantype ck_quadr; + + /* Nordsieck History Array for quadratures */ + N_Vector ck_znQ[L_MAX]; + + /* Do we need to carry sensitivities? */ + booleantype ck_sensi; + + /* number of sensitivities */ + int ck_Ns; + + /* Nordsieck History Array for sensitivities */ + N_Vector *ck_znS[L_MAX]; + + /* Do we need to carry quadrature sensitivities? */ + booleantype ck_quadr_sensi; + + /* Nordsieck History Array for quadrature sensitivities */ + N_Vector *ck_znQS[L_MAX]; + + /* Was ck_zn[qmax] allocated? + ck_zqm = 0 - no + ck_zqm = qmax - yes */ + int ck_zqm; + + /* Step data */ + long int ck_nst; + realtype ck_tretlast; + int ck_q; + int ck_qprime; + int ck_qwait; + int ck_L; + realtype ck_gammap; + realtype ck_h; + realtype ck_hprime; + realtype ck_hscale; + realtype ck_eta; + realtype ck_etamax; + realtype ck_tau[L_MAX+1]; + realtype ck_tq[NUM_TESTS+1]; + realtype ck_l[L_MAX]; + + /* Saved values */ + realtype ck_saved_tq5; + + /* Pointer to next structure in list */ + struct CkpntMemRec *ck_next; + +}; + +/* + * ----------------------------------------------------------------- + * Types for functions provided by an interpolation module + * ----------------------------------------------------------------- + * cvaIMMallocFn: Type for a function that initializes the content + * field of the structures in the dt array + * cvaIMFreeFn: Type for a function that deallocates the content + * field of the structures in the dt array + * cvaIMGetYFn: Type for a function that returns the + * interpolated forward solution. + * cvaIMStorePnt: Type for a function that stores a new + * point in the structure d + * ----------------------------------------------------------------- + */ + +typedef booleantype (*cvaIMMallocFn)(CVodeMem cv_mem); +typedef void (*cvaIMFreeFn)(CVodeMem cv_mem); +typedef int (*cvaIMGetYFn)(CVodeMem cv_mem, realtype t, N_Vector y, N_Vector *yS); +typedef int (*cvaIMStorePntFn)(CVodeMem cv_mem, DtpntMem d); + +/* + * ----------------------------------------------------------------- + * Type : struct DtpntMemRec + * ----------------------------------------------------------------- + * This structure contains fields to store all information at a + * data point that is needed to interpolate solution of forward + * simulations. Its content field depends on IMtype. + * ----------------------------------------------------------------- + */ + +struct DtpntMemRec { + realtype t; /* time */ + void *content; /* IMtype-dependent content */ +}; + +/* Data for cubic Hermite interpolation */ +typedef struct HermiteDataMemRec { + N_Vector y; + N_Vector yd; + N_Vector *yS; + N_Vector *ySd; +} *HermiteDataMem; + +/* Data for polynomial interpolation */ +typedef struct PolynomialDataMemRec { + N_Vector y; + N_Vector *yS; + int order; +} *PolynomialDataMem; + + +/* + * ----------------------------------------------------------------- + * Type : struct CVodeBMemRec + * ----------------------------------------------------------------- + * The type CVodeBMem is a pointer to a structure which stores all + * information for ONE backward problem. + * The CVadjMem structure contains a linked list of CVodeBMem pointers + * ----------------------------------------------------------------- + */ + +struct CVodeBMemRec { + + /* Index of this backward problem */ + int cv_index; + + /* Time at which the backward problem is intialized */ + realtype cv_t0; + + /* CVODES memory for this backward problem */ + CVodeMem cv_mem; + + /* Flags to indicate that this backward problem's RHS or quad RHS + * require forward sensitivities */ + booleantype cv_f_withSensi; + booleantype cv_fQ_withSensi; + + /* Right hand side function for backward run */ + CVRhsFnB cv_f; + CVRhsFnBS cv_fs; + + /* Right hand side quadrature function for backward run */ + CVQuadRhsFnB cv_fQ; + CVQuadRhsFnBS cv_fQs; + + /* User user_data */ + void *cv_user_data; + + /* Memory block for a linear solver's interface to CVODEA */ + void *cv_lmem; + + /* Function to free any memory allocated by the linear solver */ + void (*cv_lfree)(CVodeBMem cvB_mem); + + /* Memory block for a preconditioner's module interface to CVODEA */ + void *cv_pmem; + + /* Function to free any memory allocated by the preconditioner module */ + void (*cv_pfree)(CVodeBMem cvB_mem); + + /* Time at which to extract solution / quadratures */ + realtype cv_tout; + + /* Workspace Nvector */ + N_Vector cv_y; + + /* Pointer to next structure in list */ + struct CVodeBMemRec *cv_next; + +}; + +/* + * ----------------------------------------------------------------- + * Type : struct CVadjMemRec + * ----------------------------------------------------------------- + * The type CVadjMem is type pointer to struct CVadjMemRec. + * This structure contins fields to store all information + * necessary for adjoint sensitivity analysis. + * ----------------------------------------------------------------- + */ + +struct CVadjMemRec { + + /* -------------------- + * Forward problem data + * -------------------- */ + + /* Integration interval */ + realtype ca_tinitial, ca_tfinal; + + /* Flag for first call to CVodeF */ + booleantype ca_firstCVodeFcall; + + /* Flag if CVodeF was called with TSTOP */ + booleantype ca_tstopCVodeFcall; + realtype ca_tstopCVodeF; + + /* ---------------------- + * Backward problems data + * ---------------------- */ + + /* Storage for backward problems */ + struct CVodeBMemRec *cvB_mem; + + /* Number of backward problems */ + int ca_nbckpbs; + + /* Address of current backward problem */ + struct CVodeBMemRec *ca_bckpbCrt; + + /* Flag for first call to CVodeB */ + booleantype ca_firstCVodeBcall; + + /* ---------------- + * Check point data + * ---------------- */ + + /* Storage for check point information */ + struct CkpntMemRec *ck_mem; + + /* Number of check points */ + int ca_nckpnts; + + /* address of the check point structure for which data is available */ + struct CkpntMemRec *ca_ckpntData; + + /* ------------------ + * Interpolation data + * ------------------ */ + + /* Number of steps between 2 check points */ + long int ca_nsteps; + + /* Storage for data from forward runs */ + struct DtpntMemRec **dt_mem; + + /* Actual number of data points in dt_mem (typically np=nsteps+1) */ + long int ca_np; + + /* Interpolation type */ + int ca_IMtype; + + /* Functions set by the interpolation module */ + cvaIMMallocFn ca_IMmalloc; + cvaIMFreeFn ca_IMfree; + cvaIMStorePntFn ca_IMstore; /* store a new interpolation point */ + cvaIMGetYFn ca_IMget; /* interpolate forward solution */ + + /* Flags controlling the interpolation module */ + booleantype ca_IMmallocDone; /* IM initialized? */ + booleantype ca_IMnewData; /* new data available in dt_mem?*/ + booleantype ca_IMstoreSensi; /* store sensitivities? */ + booleantype ca_IMinterpSensi; /* interpolate sensitivities? */ + + /* Workspace for the interpolation module */ + N_Vector ca_Y[L_MAX]; /* pointers to zn[i] */ + N_Vector *ca_YS[L_MAX]; /* pointers to znS[i] */ + realtype ca_T[L_MAX]; + + /* ------------------------------- + * Workspace for wrapper functions + * ------------------------------- */ + + N_Vector ca_ytmp; + + N_Vector *ca_yStmp; + +}; + + +/* + * ================================================================= + * I N T E R F A C E T O L I N E A R S O L V E R S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Communication between CVODE and a CVODE Linear Solver + * ----------------------------------------------------------------- + * convfail (input to cv_lsetup) + * + * CV_NO_FAILURES : Either this is the first cv_setup call for this + * step, or the local error test failed on the + * previous attempt at this step (but the Newton + * iteration converged). + * + * CV_FAIL_BAD_J : This value is passed to cv_lsetup if + * + * (a) The previous Newton corrector iteration + * did not converge and the linear solver's + * setup routine indicated that its Jacobian- + * related data is not current + * or + * (b) During the previous Newton corrector + * iteration, the linear solver's solve routine + * failed in a recoverable manner and the + * linear solver's setup routine indicated that + * its Jacobian-related data is not current. + * + * CV_FAIL_OTHER : During the current internal step try, the + * previous Newton iteration failed to converge + * even though the linear solver was using current + * Jacobian-related data. + * ----------------------------------------------------------------- + */ + +/* Constants for convfail (input to cv_lsetup) */ + +#define CV_NO_FAILURES 0 +#define CV_FAIL_BAD_J 1 +#define CV_FAIL_OTHER 2 + +/* + * ----------------------------------------------------------------- + * int (*cv_linit)(CVodeMem cv_mem); + * ----------------------------------------------------------------- + * The purpose of cv_linit is to complete initializations for a + * specific linear solver, such as counters and statistics. + * An LInitFn should return 0 if it has successfully initialized the + * CVODE linear solver and a negative value otherwise. + * If an error does occur, an appropriate message should be sent to + * the error handler function. + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * int (*cv_lsetup)(CVodeMem cv_mem, int convfail, N_Vector ypred, + * N_Vector fpred, booleantype *jcurPtr, + * N_Vector vtemp1, N_Vector vtemp2, + * N_Vector vtemp3); + * ----------------------------------------------------------------- + * The job of cv_lsetup is to prepare the linear solver for + * subsequent calls to cv_lsolve. It may recompute Jacobian- + * related data is it deems necessary. Its parameters are as + * follows: + * + * cv_mem - problem memory pointer of type CVodeMem. See the + * typedef earlier in this file. + * + * convfail - a flag to indicate any problem that occurred during + * the solution of the nonlinear equation on the + * current time step for which the linear solver is + * being used. This flag can be used to help decide + * whether the Jacobian data kept by a CVODE linear + * solver needs to be updated or not. + * Its possible values have been documented above. + * + * ypred - the predicted y vector for the current CVODE internal + * step. + * + * fpred - f(tn, ypred). + * + * jcurPtr - a pointer to a boolean to be filled in by cv_lsetup. + * The function should set *jcurPtr=TRUE if its Jacobian + * data is current after the call and should set + * *jcurPtr=FALSE if its Jacobian data is not current. + * Note: If cv_lsetup calls for re-evaluation of + * Jacobian data (based on convfail and CVODE state + * data), it should return *jcurPtr=TRUE always; + * otherwise an infinite loop can result. + * + * vtemp1 - temporary N_Vector provided for use by cv_lsetup. + * + * vtemp3 - temporary N_Vector provided for use by cv_lsetup. + * + * vtemp3 - temporary N_Vector provided for use by cv_lsetup. + * + * The cv_lsetup routine should return 0 if successful, a positive + * value for a recoverable error, and a negative value for an + * unrecoverable error. + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * int (*cv_lsolve)(CVodeMem cv_mem, N_Vector b, N_Vector weight, + * N_Vector ycur, N_Vector fcur); + * ----------------------------------------------------------------- + * cv_lsolve must solve the linear equation P x = b, where + * P is some approximation to (I - gamma J), J = (df/dy)(tn,ycur) + * and the RHS vector b is input. The N-vector ycur contains + * the solver's current approximation to y(tn) and the vector + * fcur contains the N_Vector f(tn,ycur). The solution is to be + * returned in the vector b. cv_lsolve returns a positive value + * for a recoverable error and a negative value for an + * unrecoverable error. Success is indicated by a 0 return value. + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * void (*cv_lfree)(CVodeMem cv_mem); + * ----------------------------------------------------------------- + * cv_lfree should free up any memory allocated by the linear + * solver. This routine is called once a problem has been + * completed and the linear solver is no longer needed. + * ----------------------------------------------------------------- + */ + +/* + * ================================================================= + * C V O D E S I N T E R N A L F U N C T I O N S + * ================================================================= + */ + +/* Prototype of internal ewtSet function */ + +int cvEwtSet(N_Vector ycur, N_Vector weight, void *data); + +/* High level error handler */ + +void cvProcessError(CVodeMem cv_mem, + int error_code, const char *module, const char *fname, + const char *msgfmt, ...); + +/* Prototype of internal errHandler function */ + +void cvErrHandler(int error_code, const char *module, const char *function, + char *msg, void *data); + +/* Prototypes for internal sensitivity rhs wrappers */ + +int cvSensRhsWrapper(CVodeMem cv_mem, realtype time, + N_Vector ycur, N_Vector fcur, + N_Vector *yScur, N_Vector *fScur, + N_Vector temp1, N_Vector temp2); + +int cvSensRhs1Wrapper(CVodeMem cv_mem, realtype time, + N_Vector ycur, N_Vector fcur, + int is, N_Vector yScur, N_Vector fScur, + N_Vector temp1, N_Vector temp2); + +/* Prototypes for internal sensitivity rhs DQ functions */ + +int cvSensRhsInternalDQ(int Ns, realtype t, + N_Vector y, N_Vector ydot, + N_Vector *yS, N_Vector *ySdot, + void *fS_data, + N_Vector tempv, N_Vector ftemp); + +int cvSensRhs1InternalDQ(int Ns, realtype t, + N_Vector y, N_Vector ydot, + int is, N_Vector yS, N_Vector ySdot, + void *fS_data, + N_Vector tempv, N_Vector ftemp); + +/* + * ================================================================= + * C V O D E S E R R O R M E S S A G E S + * ================================================================= + */ + +#if defined(SUNDIALS_EXTENDED_PRECISION) + +#define MSG_TIME "t = %Lg" +#define MSG_TIME_H "t = %Lg and h = %Lg" +#define MSG_TIME_INT "t = %Lg is not between tcur - hu = %Lg and tcur = %Lg." +#define MSG_TIME_TOUT "tout = %Lg" +#define MSG_TIME_TSTOP "tstop = %Lg" + +#elif defined(SUNDIALS_DOUBLE_PRECISION) + +#define MSG_TIME "t = %lg" +#define MSG_TIME_H "t = %lg and h = %lg" +#define MSG_TIME_INT "t = %lg is not between tcur - hu = %lg and tcur = %lg." +#define MSG_TIME_TOUT "tout = %lg" +#define MSG_TIME_TSTOP "tstop = %lg" + +#else + +#define MSG_TIME "t = %g" +#define MSG_TIME_H "t = %g and h = %g" +#define MSG_TIME_INT "t = %g is not between tcur - hu = %g and tcur = %g." +#define MSG_TIME_TOUT "tout = %g" +#define MSG_TIME_TSTOP "tstop = %g" + +#endif + + +/* Initialization and I/O error messages */ + +#define MSGCV_NO_MEM "cvode_mem = NULL illegal." +#define MSGCV_CVMEM_FAIL "Allocation of cvode_mem failed." +#define MSGCV_MEM_FAIL "A memory request failed." +#define MSGCV_BAD_LMM "Illegal value for lmm. The legal values are CV_ADAMS and CV_BDF." +#define MSGCV_BAD_ITER "Illegal value for iter. The legal values are CV_FUNCTIONAL and CV_NEWTON." +#define MSGCV_NO_MALLOC "Attempt to call before CVodeInit." +#define MSGCV_NEG_MAXORD "maxord <= 0 illegal." +#define MSGCV_BAD_MAXORD "Illegal attempt to increase maximum method order." +#define MSGCV_SET_SLDET "Attempt to use stability limit detection with the CV_ADAMS method illegal." +#define MSGCV_NEG_HMIN "hmin < 0 illegal." +#define MSGCV_NEG_HMAX "hmax < 0 illegal." +#define MSGCV_BAD_HMIN_HMAX "Inconsistent step size limits: hmin > hmax." +#define MSGCV_BAD_RELTOL "reltol < 0 illegal." +#define MSGCV_BAD_ABSTOL "abstol has negative component(s) (illegal)." +#define MSGCV_NULL_ABSTOL "abstol = NULL illegal." +#define MSGCV_NULL_Y0 "y0 = NULL illegal." +#define MSGCV_NULL_F "f = NULL illegal." +#define MSGCV_NULL_G "g = NULL illegal." +#define MSGCV_BAD_NVECTOR "A required vector operation is not implemented." +#define MSGCV_BAD_K "Illegal value for k." +#define MSGCV_NULL_DKY "dky = NULL illegal." +#define MSGCV_BAD_T "Illegal value for t." MSG_TIME_INT +#define MSGCV_NO_ROOT "Rootfinding was not initialized." + +#define MSGCV_NO_QUAD "Quadrature integration not activated." +#define MSGCV_BAD_ITOLQ "Illegal value for itolQ. The legal values are CV_SS and CV_SV." +#define MSGCV_NULL_ABSTOLQ "abstolQ = NULL illegal." +#define MSGCV_BAD_RELTOLQ "reltolQ < 0 illegal." +#define MSGCV_BAD_ABSTOLQ "abstolQ has negative component(s) (illegal)." + +#define MSGCV_SENSINIT_2 "Sensitivity analysis already initialized." +#define MSGCV_NO_SENSI "Forward sensitivity analysis not activated." +#define MSGCV_BAD_ITOLS "Illegal value for itolS. The legal values are CV_SS, CV_SV, and CV_EE." +#define MSGCV_NULL_ABSTOLS "abstolS = NULL illegal." +#define MSGCV_BAD_RELTOLS "reltolS < 0 illegal." +#define MSGCV_BAD_ABSTOLS "abstolS has negative component(s) (illegal)." +#define MSGCV_BAD_PBAR "pbar has zero component(s) (illegal)." +#define MSGCV_BAD_PLIST "plist has negative component(s) (illegal)." +#define MSGCV_BAD_NS "NS <= 0 illegal." +#define MSGCV_NULL_YS0 "yS0 = NULL illegal." +#define MSGCV_BAD_ISM "Illegal value for ism. Legal values are: CV_SIMULTANEOUS, CV_STAGGERED and CV_STAGGERED1." +#define MSGCV_BAD_IFS "Illegal value for ifS. Legal values are: CV_ALLSENS and CV_ONESENS." +#define MSGCV_BAD_ISM_IFS "Illegal ism = CV_STAGGERED1 for CVodeSensInit." +#define MSGCV_BAD_IS "Illegal value for is." +#define MSGCV_NULL_DKYA "dkyA = NULL illegal." +#define MSGCV_BAD_DQTYPE "Illegal value for DQtype. Legal values are: CV_CENTERED and CV_FORWARD." +#define MSGCV_BAD_DQRHO "DQrhomax < 0 illegal." + +#define MSGCV_BAD_ITOLQS "Illegal value for itolQS. The legal values are CV_SS, CV_SV, and CV_EE." +#define MSGCV_NULL_ABSTOLQS "abstolQS = NULL illegal." +#define MSGCV_BAD_RELTOLQS "reltolQS < 0 illegal." +#define MSGCV_BAD_ABSTOLQS "abstolQS has negative component(s) (illegal)." +#define MSGCV_NO_QUADSENSI "Forward sensitivity analysis for quadrature variables not activated." +#define MSGCV_NULL_YQS0 "yQS0 = NULL illegal." + +/* CVode Error Messages */ + +#define MSGCV_NO_TOL "No integration tolerances have been specified." +#define MSGCV_LSOLVE_NULL "The linear solver's solve routine is NULL." +#define MSGCV_YOUT_NULL "yout = NULL illegal." +#define MSGCV_TRET_NULL "tret = NULL illegal." +#define MSGCV_BAD_EWT "Initial ewt has component(s) equal to zero (illegal)." +#define MSGCV_EWT_NOW_BAD "At " MSG_TIME ", a component of ewt has become <= 0." +#define MSGCV_BAD_ITASK "Illegal value for itask." +#define MSGCV_BAD_H0 "h0 and tout - t0 inconsistent." +#define MSGCV_BAD_TOUT "Trouble interpolating at " MSG_TIME_TOUT ". tout too far back in direction of integration" +#define MSGCV_EWT_FAIL "The user-provide EwtSet function failed." +#define MSGCV_EWT_NOW_FAIL "At " MSG_TIME ", the user-provide EwtSet function failed." +#define MSGCV_LINIT_FAIL "The linear solver's init routine failed." +#define MSGCV_HNIL_DONE "The above warning has been issued mxhnil times and will not be issued again for this problem." +#define MSGCV_TOO_CLOSE "tout too close to t0 to start integration." +#define MSGCV_MAX_STEPS "At " MSG_TIME ", mxstep steps taken before reaching tout." +#define MSGCV_TOO_MUCH_ACC "At " MSG_TIME ", too much accuracy requested." +#define MSGCV_HNIL "Internal " MSG_TIME_H " are such that t + h = t on the next step. The solver will continue anyway." +#define MSGCV_ERR_FAILS "At " MSG_TIME_H ", the error test failed repeatedly or with |h| = hmin." +#define MSGCV_CONV_FAILS "At " MSG_TIME_H ", the corrector convergence test failed repeatedly or with |h| = hmin." +#define MSGCV_SETUP_FAILED "At " MSG_TIME ", the setup routine failed in an unrecoverable manner." +#define MSGCV_SOLVE_FAILED "At " MSG_TIME ", the solve routine failed in an unrecoverable manner." +#define MSGCV_RHSFUNC_FAILED "At " MSG_TIME ", the right-hand side routine failed in an unrecoverable manner." +#define MSGCV_RHSFUNC_UNREC "At " MSG_TIME ", the right-hand side failed in a recoverable manner, but no recovery is possible." +#define MSGCV_RHSFUNC_REPTD "At " MSG_TIME " repeated recoverable right-hand side function errors." +#define MSGCV_RHSFUNC_FIRST "The right-hand side routine failed at the first call." +#define MSGCV_RTFUNC_FAILED "At " MSG_TIME ", the rootfinding routine failed in an unrecoverable manner." +#define MSGCV_CLOSE_ROOTS "Root found at and very near " MSG_TIME "." +#define MSGCV_BAD_TSTOP "The value " MSG_TIME_TSTOP " is behind current " MSG_TIME " in the direction of integration." +#define MSGCV_INACTIVE_ROOTS "At the end of the first step, there are still some root functions identically 0. This warning will not be issued again." + +#define MSGCV_NO_TOLQ "No integration tolerances for quadrature variables have been specified." +#define MSGCV_BAD_EWTQ "Initial ewtQ has component(s) equal to zero (illegal)." +#define MSGCV_EWTQ_NOW_BAD "At " MSG_TIME ", a component of ewtQ has become <= 0." +#define MSGCV_QRHSFUNC_FAILED "At " MSG_TIME ", the quadrature right-hand side routine failed in an unrecoverable manner." +#define MSGCV_QRHSFUNC_UNREC "At " MSG_TIME ", the quadrature right-hand side failed in a recoverable manner, but no recovery is possible." +#define MSGCV_QRHSFUNC_REPTD "At " MSG_TIME " repeated recoverable quadrature right-hand side function errors." +#define MSGCV_QRHSFUNC_FIRST "The quadrature right-hand side routine failed at the first call." + +#define MSGCV_NO_TOLS "No integration tolerances for sensitivity variables have been specified." +#define MSGCV_NULL_P "p = NULL when using internal DQ for sensitivity RHS illegal." +#define MSGCV_BAD_EWTS "Initial ewtS has component(s) equal to zero (illegal)." +#define MSGCV_EWTS_NOW_BAD "At " MSG_TIME ", a component of ewtS has become <= 0." +#define MSGCV_SRHSFUNC_FAILED "At " MSG_TIME ", the sensitivity right-hand side routine failed in an unrecoverable manner." +#define MSGCV_SRHSFUNC_UNREC "At " MSG_TIME ", the sensitivity right-hand side failed in a recoverable manner, but no recovery is possible." +#define MSGCV_SRHSFUNC_REPTD "At " MSG_TIME " repeated recoverable sensitivity right-hand side function errors." +#define MSGCV_SRHSFUNC_FIRST "The sensitivity right-hand side routine failed at the first call." + +#define MSGCV_NULL_FQ "CVODES is expected to use DQ to evaluate the RHS of quad. sensi., but quadratures were not initialized." +#define MSGCV_NO_TOLQS "No integration tolerances for quadrature sensitivity variables have been specified." +#define MSGCV_BAD_EWTQS "Initial ewtQS has component(s) equal to zero (illegal)." +#define MSGCV_EWTQS_NOW_BAD "At " MSG_TIME ", a component of ewtQS has become <= 0." +#define MSGCV_QSRHSFUNC_FAILED "At " MSG_TIME ", the quadrature sensitivity right-hand side routine failed in an unrecoverable manner." +#define MSGCV_QSRHSFUNC_UNREC "At " MSG_TIME ", the quadrature sensitivity right-hand side failed in a recoverable manner, but no recovery is possible." +#define MSGCV_QSRHSFUNC_REPTD "At " MSG_TIME " repeated recoverable quadrature sensitivity right-hand side function errors." +#define MSGCV_QSRHSFUNC_FIRST "The quadrature sensitivity right-hand side routine failed at the first call." + +/* + * ================================================================= + * C V O D E A E R R O R M E S S A G E S + * ================================================================= + */ + +#define MSGCV_NO_ADJ "Illegal attempt to call before calling CVodeAdjMalloc." +#define MSGCV_BAD_STEPS "Steps nonpositive illegal." +#define MSGCV_BAD_INTERP "Illegal value for interp." +#define MSGCV_BAD_WHICH "Illegal value for which." +#define MSGCV_NO_BCK "No backward problems have been defined yet." +#define MSGCV_NO_FWD "Illegal attempt to call before calling CVodeF." +#define MSGCV_BAD_TB0 "The initial time tB0 for problem %d is outside the interval over which the forward problem was solved." +#define MSGCV_BAD_SENSI "At least one backward problem requires sensitivities, but they were not stored for interpolation." +#define MSGCV_BAD_ITASKB "Illegal value for itaskB. Legal values are CV_NORMAL and CV_ONE_STEP." +#define MSGCV_BAD_TBOUT "The final time tBout is outside the interval over which the forward problem was solved." +#define MSGCV_BACK_ERROR "Error occured while integrating backward problem # %d" +#define MSGCV_BAD_TINTERP "Bad t = %g for interpolation." +#define MSGCV_WRONG_INTERP "This function cannot be called for the specified interp type." + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_io.c b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_io.c new file mode 100644 index 0000000..12e616a --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_io.c @@ -0,0 +1,1877 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.18 $ + * $Date: 2008/04/15 16:35:33 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the optional input and output + * functions for the CVODES solver. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "cvodes_impl.h" + +#include +#include + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +/* + * ================================================================= + * CVODES optional input functions + * ================================================================= + */ + +/* + * CVodeSetErrHandlerFn + * + * Specifies the error handler function + */ + +int CVodeSetErrHandlerFn(void *cvode_mem, CVErrHandlerFn ehfun, void *eh_data) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetErrHandlerFn", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + cv_mem->cv_ehfun = ehfun; + cv_mem->cv_eh_data = eh_data; + + return(CV_SUCCESS); +} + +/* + * CVodeSetErrFile + * + * Specifies the FILE pointer for output (NULL means no messages) + */ + +int CVodeSetErrFile(void *cvode_mem, FILE *errfp) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetErrFile", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + cv_mem->cv_errfp = errfp; + + return(CV_SUCCESS); +} + +/* + * CVodeSetIterType + * + * Specifies the iteration type (CV_FUNCTIONAL or CV_NEWTON) + */ + +int CVodeSetIterType(void *cvode_mem, int iter) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetIterType", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + if ((iter != CV_FUNCTIONAL) && (iter != CV_NEWTON)) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSetIterType", MSGCV_BAD_ITER); + return (CV_ILL_INPUT); + } + + cv_mem->cv_iter = iter; + + return(CV_SUCCESS); +} + +/* + * CVodeSetUserData + * + * Specifies the user data pointer for f + */ + +int CVodeSetUserData(void *cvode_mem, void *user_data) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetUserData", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + cv_mem->cv_user_data = user_data; + + return(CV_SUCCESS); +} + +/* + * CVodeSetMaxOrd + * + * Specifies the maximum method order + */ + +int CVodeSetMaxOrd(void *cvode_mem, int maxord) +{ + CVodeMem cv_mem; + int qmax_alloc; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetMaxOrd", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + if (maxord <= 0) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSetMaxOrd", MSGCV_NEG_MAXORD); + return(CV_ILL_INPUT); + } + + /* Cannot increase maximum order beyond the value that + was used when allocating memory */ + qmax_alloc = cv_mem->cv_qmax_alloc; + qmax_alloc = MIN(qmax_alloc, cv_mem->cv_qmax_allocQ); + qmax_alloc = MIN(qmax_alloc, cv_mem->cv_qmax_allocS); + + if (maxord > qmax_alloc) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSetMaxOrd", MSGCV_BAD_MAXORD); + return(CV_ILL_INPUT); + } + + cv_mem->cv_qmax = maxord; + + return(CV_SUCCESS); +} + +/* + * CVodeSetMaxNumSteps + * + * Specifies the maximum number of integration steps + */ + +int CVodeSetMaxNumSteps(void *cvode_mem, long int mxsteps) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetMaxNumSteps", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + /* Passing mxsteps=0 sets the default. Passing mxsteps<0 disables the test. */ + if (mxsteps == 0) + cv_mem->cv_mxstep = MXSTEP_DEFAULT; + else + cv_mem->cv_mxstep = mxsteps; + + return(CV_SUCCESS); +} + +/* + * CVodeSetMaxHnilWarns + * + * Specifies the maximum number of warnings for small h + */ + +int CVodeSetMaxHnilWarns(void *cvode_mem, int mxhnil) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetMaxHnilWarns", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + cv_mem->cv_mxhnil = mxhnil; + + return(CV_SUCCESS); +} + +/* + *CVodeSetStabLimDet + * + * Turns on/off the stability limit detection algorithm + */ + +int CVodeSetStabLimDet(void *cvode_mem, booleantype sldet) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetStabLimDet", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + if( sldet && (cv_mem->cv_lmm != CV_BDF) ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSetStabLimDet", MSGCV_SET_SLDET); + return(CV_ILL_INPUT); + } + + cv_mem->cv_sldeton = sldet; + + return(CV_SUCCESS); +} + +/* + * CVodeSetInitStep + * + * Specifies the initial step size + */ + +int CVodeSetInitStep(void *cvode_mem, realtype hin) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetInitStep", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + cv_mem->cv_hin = hin; + + return(CV_SUCCESS); +} + +/* + * CVodeSetMinStep + * + * Specifies the minimum step size + */ + +int CVodeSetMinStep(void *cvode_mem, realtype hmin) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetMinStep", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + if (hmin<0) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSetMinStep", MSGCV_NEG_HMIN); + return(CV_ILL_INPUT); + } + + /* Passing 0 sets hmin = zero */ + if (hmin == ZERO) { + cv_mem->cv_hmin = HMIN_DEFAULT; + return(CV_SUCCESS); + } + + if (hmin * cv_mem->cv_hmax_inv > ONE) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSetMinStep", MSGCV_BAD_HMIN_HMAX); + return(CV_ILL_INPUT); + } + + cv_mem->cv_hmin = hmin; + + return(CV_SUCCESS); +} + +/* + * CVodeSetMaxStep + * + * Specifies the maximum step size + */ + +int CVodeSetMaxStep(void *cvode_mem, realtype hmax) +{ + realtype hmax_inv; + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetMaxStep", MSGCV_NO_MEM); + return (CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + if (hmax < 0) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSetMaxStep", MSGCV_NEG_HMAX); + return(CV_ILL_INPUT); + } + + /* Passing 0 sets hmax = infinity */ + if (hmax == ZERO) { + cv_mem->cv_hmax_inv = HMAX_INV_DEFAULT; + return(CV_SUCCESS); + } + + hmax_inv = ONE/hmax; + if (hmax_inv * cv_mem->cv_hmin > ONE) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSetMaxStep", MSGCV_BAD_HMIN_HMAX); + return(CV_ILL_INPUT); + } + + cv_mem->cv_hmax_inv = hmax_inv; + + return(CV_SUCCESS); +} + +/* + * CVodeSetStopTime + * + * Specifies the time beyond which the integration is not to proceed. + */ + +int CVodeSetStopTime(void *cvode_mem, realtype tstop) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetStopTime", MSGCV_NO_MEM); + return (CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* If CVode was called at least once, test if tstop is legal + * (i.e. if it was not already passed). + * If CVodeSetStopTime is called before the first call to CVode, + * tstop will be checked in CVode. */ + if (cv_mem->cv_nst > 0) { + + if ( (tstop - cv_mem->cv_tn) * cv_mem->cv_h < ZERO ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSetStopTime", MSGCV_BAD_TSTOP, cv_mem->cv_tn); + return(CV_ILL_INPUT); + } + + } + + cv_mem->cv_tstop = tstop; + cv_mem->cv_tstopset = TRUE; + + return(CV_SUCCESS); +} + +/* + * CVodeSetMaxErrTestFails + * + * Specifies the maximum number of error test failures during one + * step try. + */ + +int CVodeSetMaxErrTestFails(void *cvode_mem, int maxnef) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetMaxErrTestFails", MSGCV_NO_MEM); + return (CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + cv_mem->cv_maxnef = maxnef; + + return(CV_SUCCESS); +} + +/* + * CVodeSetMaxConvFails + * + * Specifies the maximum number of nonlinear convergence failures + * during one step try. + */ + +int CVodeSetMaxConvFails(void *cvode_mem, int maxncf) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetMaxConvFails", MSGCV_NO_MEM); + return (CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + cv_mem->cv_maxncf = maxncf; + + return(CV_SUCCESS); +} + +/* + * CVodeSetMaxNonlinIters + * + * Specifies the maximum number of nonlinear iterations during + * one solve. + */ + +int CVodeSetMaxNonlinIters(void *cvode_mem, int maxcor) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetMaxNonlinIters", MSGCV_NO_MEM); + return (CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + cv_mem->cv_maxcor = maxcor; + + return(CV_SUCCESS); +} + +/* + * CVodeSetNonlinConvCoef + * + * Specifies the coeficient in the nonlinear solver convergence + * test + */ + +int CVodeSetNonlinConvCoef(void *cvode_mem, realtype nlscoef) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetNonlinConvCoef", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + cv_mem->cv_nlscoef = nlscoef; + + return(CV_SUCCESS); +} + +/* + * CVodeSetRootDirection + * + * Specifies the direction of zero-crossings to be monitored. + * The default is to monitor both crossings. + */ + +int CVodeSetRootDirection(void *cvode_mem, int *rootdir) +{ + CVodeMem cv_mem; + int i, nrt; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetRootDirection", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + nrt = cv_mem->cv_nrtfn; + if (nrt==0) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSetRootDirection", MSGCV_NO_ROOT); + return(CV_ILL_INPUT); + } + + for(i=0; icv_rootdir[i] = rootdir[i]; + + return(CV_SUCCESS); +} + + +/* + * CVodeSetNoInactiveRootWarn + * + * Disables issuing a warning if some root function appears + * to be identically zero at the beginning of the integration + */ + +int CVodeSetNoInactiveRootWarn(void *cvode_mem) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetNoInactiveRootWarn", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + cv_mem->cv_mxgnull = 0; + + return(CV_SUCCESS); +} + +/* + * ================================================================= + * Quadrature optional input functions + * ================================================================= + */ + +int CVodeSetQuadErrCon(void *cvode_mem, booleantype errconQ) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetQuadErrCon", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + cv_mem->cv_errconQ = errconQ; + + return(CV_SUCCESS); +} + +/* + * ================================================================= + * FSA optional input functions + * ================================================================= + */ + +int CVodeSetSensDQMethod(void *cvode_mem, int DQtype, realtype DQrhomax) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetSensDQMethod", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + if ( (DQtype != CV_CENTERED) && (DQtype != CV_FORWARD) ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSetSensDQMethod", MSGCV_BAD_DQTYPE); + return(CV_ILL_INPUT); + } + + if (DQrhomax < ZERO ) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSetSensDQMethod", MSGCV_BAD_DQRHO); + return(CV_ILL_INPUT); + } + + cv_mem->cv_DQtype = DQtype; + cv_mem->cv_DQrhomax = DQrhomax; + + return(CV_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int CVodeSetSensErrCon(void *cvode_mem, booleantype errconS) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetSensErrCon", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + cv_mem->cv_errconS = errconS; + + return(CV_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int CVodeSetSensMaxNonlinIters(void *cvode_mem, int maxcorS) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetSensMaxNonlinIters", MSGCV_NO_MEM); + return (CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + cv_mem->cv_maxcorS = maxcorS; + + return(CV_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int CVodeSetSensParams(void *cvode_mem, realtype *p, realtype *pbar, int *plist) +{ + CVodeMem cv_mem; + int is, Ns; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetSensParams", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + /* Was sensitivity initialized? */ + + if (cv_mem->cv_SensMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeSetSensParams", MSGCV_NO_SENSI); + return(CV_NO_SENS); + } + + Ns = cv_mem->cv_Ns; + + /* Parameters */ + + cv_mem->cv_p = p; + + /* pbar */ + + if (pbar != NULL) + for (is=0; iscv_pbar[is] = ABS(pbar[is]); + } + else + for (is=0; iscv_pbar[is] = ONE; + + /* plist */ + + if (plist != NULL) + for (is=0; iscv_plist[is] = plist[is]; + } + else + for (is=0; iscv_plist[is] = is; + + return(CV_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int CVodeSetQuadSensErrCon(void *cvode_mem, booleantype errconQS) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSetQuadSensErrCon", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was sensitivity initialized? */ + + if (cv_mem->cv_SensMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeSetQuadSensTolerances", MSGCV_NO_SENSI); + return(CV_NO_SENS); + } + + /* Ckeck if quadrature sensitivity was initialized? */ + + if (cv_mem->cv_QuadSensMallocDone == FALSE) { + cvProcessError(cv_mem, CV_NO_QUADSENS, "CVODES", "CVodeSetQuadSensErrCon", MSGCV_NO_QUADSENSI); + return(CV_NO_QUAD); + } + + cv_mem->cv_errconQS = errconQS; + + return(CV_SUCCESS); +} + +/* + * ================================================================= + * CVODES optional output functions + * ================================================================= + */ + +/* + * Readability constants + */ + +#define nst (cv_mem->cv_nst) +#define nfe (cv_mem->cv_nfe) +#define ncfn (cv_mem->cv_ncfn) +#define netf (cv_mem->cv_netf) +#define nni (cv_mem->cv_nni) +#define nsetups (cv_mem->cv_nsetups) +#define qu (cv_mem->cv_qu) +#define next_q (cv_mem->cv_next_q) +#define ewt (cv_mem->cv_ewt) +#define hu (cv_mem->cv_hu) +#define next_h (cv_mem->cv_next_h) +#define h0u (cv_mem->cv_h0u) +#define tolsf (cv_mem->cv_tolsf) +#define acor (cv_mem->cv_acor) +#define lrw (cv_mem->cv_lrw) +#define liw (cv_mem->cv_liw) +#define nge (cv_mem->cv_nge) +#define iroots (cv_mem->cv_iroots) +#define nor (cv_mem->cv_nor) +#define sldeton (cv_mem->cv_sldeton) +#define tn (cv_mem->cv_tn) +#define efun (cv_mem->cv_efun) + +/* + * CVodeGetNumSteps + * + * Returns the current number of integration steps + */ + +int CVodeGetNumSteps(void *cvode_mem, long int *nsteps) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetNumSteps", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *nsteps = nst; + + return(CV_SUCCESS); +} + +/* + * CVodeGetNumRhsEvals + * + * Returns the current number of calls to f + */ + +int CVodeGetNumRhsEvals(void *cvode_mem, long int *nfevals) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetNumRhsEvals", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *nfevals = nfe; + + return(CV_SUCCESS); +} + +/* + * CVodeGetNumLinSolvSetups + * + * Returns the current number of calls to the linear solver setup routine + */ + +int CVodeGetNumLinSolvSetups(void *cvode_mem, long int *nlinsetups) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetNumLinSolvSetups", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *nlinsetups = nsetups; + + return(CV_SUCCESS); +} + +/* + * CVodeGetNumErrTestFails + * + * Returns the current number of error test failures + */ + +int CVodeGetNumErrTestFails(void *cvode_mem, long int *netfails) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetNumErrTestFails", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *netfails = netf; + + return(CV_SUCCESS); +} + +/* + * CVodeGetLastOrder + * + * Returns the order on the last succesful step + */ + +int CVodeGetLastOrder(void *cvode_mem, int *qlast) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetLastOrder", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *qlast = qu; + + return(CV_SUCCESS); +} + +/* + * CVodeGetCurrentOrder + * + * Returns the order to be attempted on the next step + */ + +int CVodeGetCurrentOrder(void *cvode_mem, int *qcur) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetCurrentOrder", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *qcur = next_q; + + return(CV_SUCCESS); +} + +/* + * CVodeGetNumStabLimOrderReds + * + * Returns the number of order reductions triggered by the stability + * limit detection algorithm + */ + +int CVodeGetNumStabLimOrderReds(void *cvode_mem, long int *nslred) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetNumStabLimOrderReds", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + if (sldeton==FALSE) + *nslred = 0; + else + *nslred = nor; + + return(CV_SUCCESS); +} + +/* + * CVodeGetActualInitStep + * + * Returns the step size used on the first step + */ + +int CVodeGetActualInitStep(void *cvode_mem, realtype *hinused) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetActualInitStep", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *hinused = h0u; + + return(CV_SUCCESS); +} + +/* + * CVodeGetLastStep + * + * Returns the step size used on the last successful step + */ + +int CVodeGetLastStep(void *cvode_mem, realtype *hlast) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetLastStep", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *hlast = hu; + + return(CV_SUCCESS); +} + +/* + * CVodeGetCurrentStep + * + * Returns the step size to be attempted on the next step + */ + +int CVodeGetCurrentStep(void *cvode_mem, realtype *hcur) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetCurrentStep", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *hcur = next_h; + + return(CV_SUCCESS); +} + +/* + * CVodeGetCurrentTime + * + * Returns the current value of the independent variable + */ + +int CVodeGetCurrentTime(void *cvode_mem, realtype *tcur) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetCurrentTime", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *tcur = tn; + + return(CV_SUCCESS); +} + +/* + * CVodeGetTolScaleFactor + * + * Returns a suggested factor for scaling tolerances + */ + +int CVodeGetTolScaleFactor(void *cvode_mem, realtype *tolsfact) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetTolScaleFactor", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *tolsfact = tolsf; + + return(CV_SUCCESS); +} + +/* + * CVodeGetErrWeights + * + * This routine returns the current weight vector. + */ + +int CVodeGetErrWeights(void *cvode_mem, N_Vector eweight) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetErrWeights", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + N_VScale(ONE, ewt, eweight); + + return(CV_SUCCESS); +} + +/* + * CVodeGetEstLocalErrors + * + * Returns an estimate of the local error + */ + +int CVodeGetEstLocalErrors(void *cvode_mem, N_Vector ele) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetEstLocalErrors", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + N_VScale(ONE, acor, ele); + + return(CV_SUCCESS); +} + +/* + * CVodeGetWorkSpace + * + * Returns integrator work space requirements + */ + +int CVodeGetWorkSpace(void *cvode_mem, long int *lenrw, long int *leniw) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetWorkSpace", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *leniw = liw; + *lenrw = lrw; + + return(CV_SUCCESS); +} + +/* + * CVodeGetIntegratorStats + * + * Returns integrator statistics + */ + +int CVodeGetIntegratorStats(void *cvode_mem, long int *nsteps, long int *nfevals, + long int *nlinsetups, long int *netfails, int *qlast, + int *qcur, realtype *hinused, realtype *hlast, + realtype *hcur, realtype *tcur) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetIntegratorStats", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *nsteps = nst; + *nfevals = nfe; + *nlinsetups = nsetups; + *netfails = netf; + *qlast = qu; + *qcur = next_q; + *hinused = h0u; + *hlast = hu; + *hcur = next_h; + *tcur = tn; + + return(CV_SUCCESS); +} + +/* + * CVodeGetNumGEvals + * + * Returns the current number of calls to g (for rootfinding) + */ + +int CVodeGetNumGEvals(void *cvode_mem, long int *ngevals) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetNumGEvals", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *ngevals = nge; + + return(CV_SUCCESS); +} + +/* + * CVodeGetRootInfo + * + * Returns pointer to array rootsfound showing roots found + */ + +int CVodeGetRootInfo(void *cvode_mem, int *rootsfound) +{ + CVodeMem cv_mem; + int i, nrt; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetRootInfo", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + nrt = cv_mem->cv_nrtfn; + + for (i=0; icv_quadr) +#define nfQe (cv_mem->cv_nfQe) +#define netfQ (cv_mem->cv_netfQ) +#define ewtQ (cv_mem->cv_ewtQ) +#define errconQ (cv_mem->cv_errconQ) + +/*-----------------------------------------------------------------*/ + +int CVodeGetQuadNumRhsEvals(void *cvode_mem, long int *nfQevals) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadNumRhsEvals", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + if (quadr==FALSE) { + cvProcessError(cv_mem, CV_NO_QUAD, "CVODES", "CVodeGetQuadNumRhsEvals", MSGCV_NO_QUAD); + return(CV_NO_QUAD); + } + + *nfQevals = nfQe; + + return(CV_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int CVodeGetQuadNumErrTestFails(void *cvode_mem, long int *nQetfails) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadNumErrTestFails", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + if (quadr==FALSE) { + cvProcessError(cv_mem, CV_NO_QUAD, "CVODES", "CVodeGetQuadNumErrTestFails", MSGCV_NO_QUAD); + return(CV_NO_QUAD); + } + + *nQetfails = netfQ; + + return(CV_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int CVodeGetQuadErrWeights(void *cvode_mem, N_Vector eQweight) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadErrWeights", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + if (quadr==FALSE) { + cvProcessError(cv_mem, CV_NO_QUAD, "CVODES", "CVodeGetQuadErrWeights", MSGCV_NO_QUAD); + return(CV_NO_QUAD); + } + + if(errconQ) N_VScale(ONE, ewtQ, eQweight); + + return(CV_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int CVodeGetQuadStats(void *cvode_mem, long int *nfQevals, long int *nQetfails) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadStats", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + if (quadr==FALSE) { + cvProcessError(cv_mem, CV_NO_QUAD, "CVODES", "CVodeGetQuadStats", MSGCV_NO_QUAD); + return(CV_NO_QUAD); + } + + *nfQevals = nfQe; + *nQetfails = netfQ; + + return(CV_SUCCESS); +} + +/* + * ================================================================= + * Quadrature FSA optional output functions + * ================================================================= + */ + +/* + * Readability constants + */ + +#define quadr_sensi (cv_mem->cv_quadr_sensi) +#define nfQSe (cv_mem->cv_nfQSe) +#define netfQS (cv_mem->cv_netfQS) +#define ewtQS (cv_mem->cv_ewtQS) +#define errconQS (cv_mem->cv_errconQS) + +/*-----------------------------------------------------------------*/ + +int CVodeGetQuadSensNumRhsEvals(void *cvode_mem, long int *nfQSevals) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadSensNumRhsEvals", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + if (quadr_sensi == FALSE) { + cvProcessError(cv_mem, CV_NO_QUADSENS, "CVODES", "CVodeGetQuadSensNumRhsEvals", MSGCV_NO_QUADSENSI); + return(CV_NO_QUADSENS); + } + + *nfQSevals = nfQSe; + + return(CV_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int CVodeGetQuadSensNumErrTestFails(void *cvode_mem, long int *nQSetfails) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadSensNumErrTestFails", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + if (quadr_sensi == FALSE) { + cvProcessError(cv_mem, CV_NO_QUADSENS, "CVODES", "CVodeGetQuadSensNumErrTestFails", MSGCV_NO_QUADSENSI); + return(CV_NO_QUADSENS); + } + + *nQSetfails = netfQS; + + return(CV_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int CVodeGetQuadSensErrWeights(void *cvode_mem, N_Vector *eQSweight) +{ + CVodeMem cv_mem; + int is, Ns; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadSensErrWeights", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + if (quadr_sensi == FALSE) { + cvProcessError(cv_mem, CV_NO_QUADSENS, "CVODES", "CVodeGetQuadSensErrWeights", MSGCV_NO_QUADSENSI); + return(CV_NO_QUADSENS); + } + Ns = cv_mem->cv_Ns; + + if (errconQS) + for (is=0; iscv_sensi) +#define ism (cv_mem->cv_ism) +#define ewtS (cv_mem->cv_ewtS) +#define nfSe (cv_mem->cv_nfSe) +#define nfeS (cv_mem->cv_nfeS) +#define nniS (cv_mem->cv_nniS) +#define ncfnS (cv_mem->cv_ncfnS) +#define netfS (cv_mem->cv_netfS) +#define nsetupsS (cv_mem->cv_nsetupsS) +#define nniS1 (cv_mem->cv_nniS1) +#define ncfnS1 (cv_mem->cv_ncfnS1) +#define ncfS1 (cv_mem->cv_ncfS1) + +/*-----------------------------------------------------------------*/ + +int CVodeGetSensNumRhsEvals(void *cvode_mem, long int *nfSevals) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetSensNumRhsEvals", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + if (sensi==FALSE) { + cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetSensNumRhsEvals", MSGCV_NO_SENSI); + return(CV_NO_SENS); + } + + *nfSevals = nfSe; + + return(CV_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int CVodeGetNumRhsEvalsSens(void *cvode_mem, long int *nfevalsS) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetNumRhsEvalsSens", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + if (sensi==FALSE) { + cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetNumRhsEvalsSens", MSGCV_NO_SENSI); + return(CV_NO_SENS); + } + + *nfevalsS = nfeS; + + return(CV_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int CVodeGetSensNumErrTestFails(void *cvode_mem, long int *nSetfails) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetSensNumErrTestFails", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + if (sensi==FALSE) { + cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetSensNumErrTestFails", MSGCV_NO_SENSI); + return(CV_NO_SENS); + } + + *nSetfails = netfS; + + return(CV_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int CVodeGetSensNumLinSolvSetups(void *cvode_mem, long int *nlinsetupsS) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetSensNumLinSolvSetups", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + if (sensi==FALSE) { + cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetSensNumLinSolvSetups", MSGCV_NO_SENSI); + return(CV_NO_SENS); + } + + *nlinsetupsS = nsetupsS; + + return(CV_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int CVodeGetSensErrWeights(void *cvode_mem, N_Vector *eSweight) +{ + CVodeMem cv_mem; + int is, Ns; + + if (cvode_mem==NULL) { + cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetSensErrWeights", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + if (sensi==FALSE) { + cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetSensErrWeights", MSGCV_NO_SENSI); + return(CV_NO_SENS); + } + + Ns = cv_mem->cv_Ns; + + for (is=0; iscv_Ns; + + if (sensi==FALSE) { + cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetStgrSensNumNonlinSolvIters", MSGCV_NO_SENSI); + return(CV_NO_SENS); + } + + if(ism==CV_STAGGERED1) + for(is=0; iscv_Ns; + + if (sensi==FALSE) { + cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetStgrSensNumNonlinSolvConvFails", MSGCV_NO_SENSI); + return(CV_NO_SENS); + } + + if(ism==CV_STAGGERED1) + for(is=0; is +#include + +#include +#include "cvodes_direct_impl.h" +#include "cvodes_impl.h" + +#include + +/* Constants */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) +#define TWO RCONST(2.0) + +/* + * ================================================================= + * PROTOTYPES FOR PRIVATE FUNCTIONS + * ================================================================= + */ + +/* CVSLAPACK DENSE linit, lsetup, lsolve, and lfree routines */ +static int cvLapackDenseInit(CVodeMem cv_mem); +static int cvLapackDenseSetup(CVodeMem cv_mem, int convfail, + N_Vector yP, N_Vector fctP, + booleantype *jcurPtr, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); +static int cvLapackDenseSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector yC, N_Vector fctC); +static void cvLapackDenseFree(CVodeMem cv_mem); + +/* CVSLAPACK BAND linit, lsetup, lsolve, and lfree routines */ +static int cvLapackBandInit(CVodeMem cv_mem); +static int cvLapackBandSetup(CVodeMem cv_mem, int convfail, + N_Vector yP, N_Vector fctP, + booleantype *jcurPtr, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); +static int cvLapackBandSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector yC, N_Vector fctC); +static void cvLapackBandFree(CVodeMem cv_mem); + +/* CVSLAPACK lfreeB functions */ +static void cvLapackDenseFreeB(CVodeBMem cvB_mem); +static void cvLapackBandFreeB(CVodeBMem cvB_mem); + +/* + * ================================================================ + * + * PART I - forward problems + * + * ================================================================ + */ + +/* Readability Replacements */ + +#define lmm (cv_mem->cv_lmm) +#define f (cv_mem->cv_f) +#define uround (cv_mem->cv_uround) +#define nst (cv_mem->cv_nst) +#define tn (cv_mem->cv_tn) +#define h (cv_mem->cv_h) +#define gamma (cv_mem->cv_gamma) +#define gammap (cv_mem->cv_gammap) +#define gamrat (cv_mem->cv_gamrat) +#define ewt (cv_mem->cv_ewt) + +#define linit (cv_mem->cv_linit) +#define lsetup (cv_mem->cv_lsetup) +#define lsolve (cv_mem->cv_lsolve) +#define lfree (cv_mem->cv_lfree) +#define lmem (cv_mem->cv_lmem) +#define tempv (cv_mem->cv_tempv) +#define setupNonNull (cv_mem->cv_setupNonNull) + +#define mtype (cvdls_mem->d_type) +#define n (cvdls_mem->d_n) +#define jacDQ (cvdls_mem->d_jacDQ) +#define djac (cvdls_mem->d_djac) +#define bjac (cvdls_mem->d_bjac) +#define M (cvdls_mem->d_M) +#define mu (cvdls_mem->d_mu) +#define ml (cvdls_mem->d_ml) +#define smu (cvdls_mem->d_smu) +#define pivots (cvdls_mem->d_pivots) +#define savedJ (cvdls_mem->d_savedJ) +#define nstlj (cvdls_mem->d_nstlj) +#define nje (cvdls_mem->d_nje) +#define nfeDQ (cvdls_mem->d_nfeDQ) +#define J_data (cvdls_mem->d_J_data) +#define last_flag (cvdls_mem->d_last_flag) + +/* + * ----------------------------------------------------------------- + * CVLapackDense + * ----------------------------------------------------------------- + * This routine initializes the memory record and sets various function + * fields specific to the linear solver module. CVLapackDense first + * calls the existing lfree routine if this is not NULL. Then it sets + * the cv_linit, cv_lsetup, cv_lsolve, cv_lfree fields in (*cvode_mem) + * to be cvLapackDenseInit, cvLapackDenseSetup, cvLapackDenseSolve, + * and cvLapackDenseFree, respectively. It allocates memory for a + * structure of type CVDlsMemRec and sets the cv_lmem field in + * (*cvode_mem) to the address of this structure. It sets setupNonNull + * in (*cvode_mem) to TRUE, and the d_jac field to the default + * cvDlsDenseDQJac. Finally, it allocates memory for M, pivots, and + * (if needed) savedJ. + * The return value is SUCCESS = 0, or LMEM_FAIL = -1. + * + * NOTE: The dense linear solver assumes a serial implementation + * of the NVECTOR package. Therefore, CVLapackDense will first + * test for a compatible N_Vector internal representation + * by checking that N_VGetArrayPointer and N_VSetArrayPointer + * exist. + * ----------------------------------------------------------------- + */ +int CVLapackDense(void *cvode_mem, int N) +{ + CVodeMem cv_mem; + CVDlsMem cvdls_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVDLS_MEM_NULL, "CVSLAPACK", "CVLapackDense", MSGD_CVMEM_NULL); + return(CVDLS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Test if the NVECTOR package is compatible with the CVSLAPACK solver */ + if (tempv->ops->nvgetarraypointer == NULL || + tempv->ops->nvsetarraypointer == NULL) { + cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSLAPACK", "CVLapackDense", MSGD_BAD_NVECTOR); + return(CVDLS_ILL_INPUT); + } + + if (lfree !=NULL) lfree(cv_mem); + + /* Set four main function fields in cv_mem */ + linit = cvLapackDenseInit; + lsetup = cvLapackDenseSetup; + lsolve = cvLapackDenseSolve; + lfree = cvLapackDenseFree; + + /* Get memory for CVDlsMemRec */ + cvdls_mem = NULL; + cvdls_mem = (CVDlsMem) malloc(sizeof(struct CVDlsMemRec)); + if (cvdls_mem == NULL) { + cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSLAPACK", "CVLapackDense", MSGD_MEM_FAIL); + return(CVDLS_MEM_FAIL); + } + + /* Set matrix type */ + mtype = SUNDIALS_DENSE; + + /* Initialize Jacobian-related data */ + jacDQ = TRUE; + djac = NULL; + J_data = NULL; + + last_flag = CVDLS_SUCCESS; + setupNonNull = TRUE; + + /* Set problem dimension */ + n = N; + + /* Allocate memory for M, pivot array, and (if needed) savedJ */ + M = NULL; + pivots = NULL; + savedJ = NULL; + + M = NewDenseMat(N, N); + if (M == NULL) { + cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSLAPACK", "CVLapackDense", MSGD_MEM_FAIL); + free(cvdls_mem); + return(CVDLS_MEM_FAIL); + } + pivots = NewIntArray(N); + if (pivots == NULL) { + cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSLAPACK", "CVLapackDense", MSGD_MEM_FAIL); + DestroyMat(M); + free(cvdls_mem); + return(CVDLS_MEM_FAIL); + } + savedJ = NewDenseMat(N, N); + if (savedJ == NULL) { + cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSLAPACK", "CVLapackDense", MSGD_MEM_FAIL); + DestroyMat(M); + DestroyArray(pivots); + free(cvdls_mem); + return(CVDLS_MEM_FAIL); + } + + /* Attach linear solver memory to integrator memory */ + lmem = cvdls_mem; + + return(CVDLS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVLapackBand + * ----------------------------------------------------------------- + * This routine initializes the memory record and sets various function + * fields specific to the band linear solver module. It first calls + * the existing lfree routine if this is not NULL. It then sets the + * cv_linit, cv_lsetup, cv_lsolve, and cv_lfree fields in (*cvode_mem) + * to be cvLapackBandInit, cvLapackBandSetup, cvLapackBandSolve, + * and cvLapackBandFree, respectively. It allocates memory for a + * structure of type CVLapackBandMemRec and sets the cv_lmem field in + * (*cvode_mem) to the address of this structure. It sets setupNonNull + * in (*cvode_mem) to be TRUE, mu to be mupper, ml to be mlower, and + * the jacE and jacI field to NULL. + * Finally, it allocates memory for M, pivots, and (if needed) savedJ. + * The CVLapackBand return value is CVDLS_SUCCESS = 0, + * CVDLS_MEM_FAIL = -1, or CVDLS_ILL_INPUT = -2. + * + * NOTE: The CVSLAPACK linear solver assumes a serial implementation + * of the NVECTOR package. Therefore, CVLapackBand will first + * test for compatible a compatible N_Vector internal + * representation by checking that the function + * N_VGetArrayPointer exists. + * ----------------------------------------------------------------- + */ +int CVLapackBand(void *cvode_mem, int N, int mupper, int mlower) +{ + CVodeMem cv_mem; + CVDlsMem cvdls_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVDLS_MEM_NULL, "CVSLAPACK", "CVLapackBand", MSGD_CVMEM_NULL); + return(CVDLS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Test if the NVECTOR package is compatible with the BAND solver */ + if (tempv->ops->nvgetarraypointer == NULL) { + cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSLAPACK", "CVLapackBand", MSGD_BAD_NVECTOR); + return(CVDLS_ILL_INPUT); + } + + if (lfree != NULL) lfree(cv_mem); + + /* Set four main function fields in cv_mem */ + linit = cvLapackBandInit; + lsetup = cvLapackBandSetup; + lsolve = cvLapackBandSolve; + lfree = cvLapackBandFree; + + /* Get memory for CVDlsMemRec */ + cvdls_mem = NULL; + cvdls_mem = (CVDlsMem) malloc(sizeof(struct CVDlsMemRec)); + if (cvdls_mem == NULL) { + cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSLAPACK", "CVLapackBand", MSGD_MEM_FAIL); + return(CVDLS_MEM_FAIL); + } + + /* Set matrix type */ + mtype = SUNDIALS_BAND; + + /* Initialize Jacobian-related data */ + jacDQ = TRUE; + bjac = NULL; + J_data = NULL; + + last_flag = CVDLS_SUCCESS; + setupNonNull = TRUE; + + /* Load problem dimension */ + n = N; + + /* Load half-bandwiths in cvdls_mem */ + ml = mlower; + mu = mupper; + + /* Test ml and mu for legality */ + if ((ml < 0) || (mu < 0) || (ml >= N) || (mu >= N)) { + cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSLAPACK", "CVLapackBand", MSGD_BAD_SIZES); + return(CVDLS_ILL_INPUT); + } + + /* Set extended upper half-bandwith for M (required for pivoting) */ + smu = MIN(N-1, mu + ml); + + /* Allocate memory for M, savedJ, and pivot arrays */ + M = NULL; + pivots = NULL; + savedJ = NULL; + + M = NewBandMat(N, mu, ml, smu); + if (M == NULL) { + cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSLAPACK", "CVLapackBand", MSGD_MEM_FAIL); + free(cvdls_mem); + return(CVDLS_MEM_FAIL); + } + pivots = NewIntArray(N); + if (pivots == NULL) { + cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSLAPACK", "CVLapackBand", MSGD_MEM_FAIL); + DestroyMat(M); + free(cvdls_mem); + return(CVDLS_MEM_FAIL); + } + savedJ = NewBandMat(N, mu, ml, smu); + if (savedJ == NULL) { + cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSLAPACK", "CVLapackBand", MSGD_MEM_FAIL); + DestroyMat(M); + DestroyArray(pivots); + free(cvdls_mem); + return(CVDLS_MEM_FAIL); + } + + /* Attach linear solver memory to integrator memory */ + lmem = cvdls_mem; + + return(CVDLS_SUCCESS); +} + +/* + * ================================================================= + * PRIVATE FUNCTIONS FOR IMPLICIT INTEGRATION WITH DENSE JACOBIANS + * ================================================================= + */ + +/* + * cvLapackDenseInit does remaining initializations specific to the dense + * linear solver. + */ +static int cvLapackDenseInit(CVodeMem cv_mem) +{ + CVDlsMem cvdls_mem; + + cvdls_mem = (CVDlsMem) lmem; + + nje = 0; + nfeDQ = 0; + nstlj = 0; + + /* Set Jacobian function and data, depending on jacDQ */ + if (jacDQ) { + djac = cvDlsDenseDQJac; + J_data = cv_mem; + } else { + J_data = cv_mem->cv_user_data; + } + + last_flag = CVDLS_SUCCESS; + return(0); +} + +/* + * cvLapackDenseSetup does the setup operations for the dense linear solver. + * It makes a decision whether or not to call the Jacobian evaluation + * routine based on various state variables, and if not it uses the + * saved copy. In any case, it constructs the Newton matrix M = I - gamma*J + * updates counters, and calls the dense LU factorization routine. + */ +static int cvLapackDenseSetup(CVodeMem cv_mem, int convfail, + N_Vector yP, N_Vector fctP, + booleantype *jcurPtr, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + CVDlsMem cvdls_mem; + realtype dgamma, fact; + booleantype jbad, jok; + int ier, retval, one = 1; + + cvdls_mem = (CVDlsMem) lmem; + + /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */ + dgamma = ABS((gamma/gammap) - ONE); + jbad = (nst == 0) || (nst > nstlj + CVD_MSBJ) || + ((convfail == CV_FAIL_BAD_J) && (dgamma < CVD_DGMAX)) || + (convfail == CV_FAIL_OTHER); + jok = !jbad; + + if (jok) { + + /* If jok = TRUE, use saved copy of J */ + *jcurPtr = FALSE; + dcopy_f77(&(savedJ->ldata), savedJ->data, &one, M->data, &one); + + } else { + + /* If jok = FALSE, call jac routine for new J value */ + nje++; + nstlj = nst; + *jcurPtr = TRUE; + SetToZero(M); + + retval = djac(n, tn, yP, fctP, M, J_data, tmp1, tmp2, tmp3); + if (retval == 0) { + dcopy_f77(&(M->ldata), M->data, &one, savedJ->data, &one); + } else if (retval < 0) { + cvProcessError(cv_mem, CVDLS_JACFUNC_UNRECVR, "CVSLAPACK", "cvLapackDenseSetup", MSGD_JACFUNC_FAILED); + last_flag = CVDLS_JACFUNC_UNRECVR; + return(-1); + } else if (retval > 0) { + last_flag = CVDLS_JACFUNC_RECVR; + return(1); + } + + } + + /* Scale J by - gamma */ + fact = -gamma; + dscal_f77(&(M->ldata), &fact, M->data, &one); + + /* Add identity to get M = I - gamma*J*/ + AddIdentity(M); + + /* Do LU factorization of M */ + dgetrf_f77(&n, &n, M->data, &(M->ldim), pivots, &ier); + + /* Return 0 if the LU was complete; otherwise return 1 */ + last_flag = ier; + if (ier > 0) return(1); + return(0); +} + +/* + * cvLapackDenseSolve handles the solve operation for the dense linear solver + * by calling the dense backsolve routine. + */ +static int cvLapackDenseSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector yC, N_Vector fctC) +{ + CVDlsMem cvdls_mem; + realtype *bd, fact; + int ier, one = 1; + + cvdls_mem = (CVDlsMem) lmem; + + bd = N_VGetArrayPointer(b); + + dgetrs_f77("N", &n, &one, M->data, &(M->ldim), pivots, bd, &n, &ier, 1); + if (ier > 0) return(1); + + /* For BDF, scale the correction to account for change in gamma */ + if ((lmm == CV_BDF) && (gamrat != ONE)) { + fact = TWO/(ONE + gamrat); + dscal_f77(&n, &fact, bd, &one); + } + + last_flag = CVDLS_SUCCESS; + return(0); +} + +/* + * cvLapackDenseFree frees memory specific to the dense linear solver. + */ +static void cvLapackDenseFree(CVodeMem cv_mem) +{ + CVDlsMem cvdls_mem; + + cvdls_mem = (CVDlsMem) lmem; + + DestroyMat(M); + DestroyArray(pivots); + DestroyMat(savedJ); + free(cvdls_mem); + cvdls_mem = NULL; +} + +/* + * ================================================================= + * PRIVATE FUNCTIONS FOR IMPLICIT INTEGRATION WITH BAND JACOBIANS + * ================================================================= + */ + +/* + * cvLapackBandInit does remaining initializations specific to the band + * linear solver. + */ +static int cvLapackBandInit(CVodeMem cv_mem) +{ + CVDlsMem cvdls_mem; + + cvdls_mem = (CVDlsMem) lmem; + + nje = 0; + nfeDQ = 0; + nstlj = 0; + + /* Set Jacobian function and data, depending on jacDQ */ + if (jacDQ) { + bjac = cvDlsBandDQJac; + J_data = cv_mem; + } else { + J_data = cv_mem->cv_user_data; + } + + last_flag = CVDLS_SUCCESS; + return(0); +} + +/* + * cvLapackBandSetup does the setup operations for the band linear solver. + * It makes a decision whether or not to call the Jacobian evaluation + * routine based on various state variables, and if not it uses the + * saved copy. In any case, it constructs the Newton matrix M = I - gamma*J, + * updates counters, and calls the band LU factorization routine. + */ +static int cvLapackBandSetup(CVodeMem cv_mem, int convfail, + N_Vector yP, N_Vector fctP, + booleantype *jcurPtr, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + CVDlsMem cvdls_mem; + realtype dgamma, fact; + booleantype jbad, jok; + int ier, retval, one = 1; + + cvdls_mem = (CVDlsMem) lmem; + + /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */ + dgamma = ABS((gamma/gammap) - ONE); + jbad = (nst == 0) || (nst > nstlj + CVD_MSBJ) || + ((convfail == CV_FAIL_BAD_J) && (dgamma < CVD_DGMAX)) || + (convfail == CV_FAIL_OTHER); + jok = !jbad; + + if (jok) { + + /* If jok = TRUE, use saved copy of J */ + *jcurPtr = FALSE; + dcopy_f77(&(savedJ->ldata), savedJ->data, &one, M->data, &one); + + } else { + + /* If jok = FALSE, call jac routine for new J value */ + nje++; + nstlj = nst; + *jcurPtr = TRUE; + SetToZero(M); + + retval = bjac(n, mu, ml, tn, yP, fctP, M, J_data, tmp1, tmp2, tmp3); + if (retval == 0) { + dcopy_f77(&(M->ldata), M->data, &one, savedJ->data, &one); + } else if (retval < 0) { + cvProcessError(cv_mem, CVDLS_JACFUNC_UNRECVR, "CVSLAPACK", "cvLapackBandSetup", MSGD_JACFUNC_FAILED); + last_flag = CVDLS_JACFUNC_UNRECVR; + return(-1); + } else if (retval > 0) { + last_flag = CVDLS_JACFUNC_RECVR; + return(1); + } + + } + + /* Scale J by - gamma */ + fact = -gamma; + dscal_f77(&(M->ldata), &fact, M->data, &one); + + /* Add identity to get M = I - gamma*J*/ + AddIdentity(M); + + /* Do LU factorization of M */ + dgbtrf_f77(&n, &n, &ml, &mu, M->data, &(M->ldim), pivots, &ier); + + /* Return 0 if the LU was complete; otherwise return 1 */ + last_flag = ier; + if (ier > 0) return(1); + return(0); + +} + +/* + * cvLapackBandSolve handles the solve operation for the band linear solver + * by calling the band backsolve routine. + */ +static int cvLapackBandSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector yC, N_Vector fctC) +{ + CVDlsMem cvdls_mem; + realtype *bd, fact; + int ier, one = 1; + + cvdls_mem = (CVDlsMem) lmem; + + bd = N_VGetArrayPointer(b); + + dgbtrs_f77("N", &n, &ml, &mu, &one, M->data, &(M->ldim), pivots, bd, &n, &ier, 1); + if (ier > 0) return(1); + + /* For BDF, scale the correction to account for change in gamma */ + if ((lmm == CV_BDF) && (gamrat != ONE)) { + fact = TWO/(ONE + gamrat); + dscal_f77(&n, &fact, bd, &one); + } + + last_flag = CVDLS_SUCCESS; + return(0); +} + +/* + * cvLapackBandFree frees memory specific to the band linear solver. + */ +static void cvLapackBandFree(CVodeMem cv_mem) +{ + CVDlsMem cvdls_mem; + + cvdls_mem = (CVDlsMem) lmem; + + DestroyMat(M); + DestroyArray(pivots); + DestroyMat(savedJ); + free(cvdls_mem); + cvdls_mem = NULL; +} + +/* + * ================================================================ + * + * PART II - backward problems + * + * ================================================================ + */ + +/* + * CVLapackDenseB is a wraper around CVLapackDense. It attaches the + * dense CVSLAPACK linear solver to the backward problem memory block. + */ + +int CVLapackDenseB(void *cvode_mem, int which, int nB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + CVDlsMemB cvdlsB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVDLS_MEM_NULL, "CVSLAPACK", "CVLapackDenseB", MSGD_CVMEM_NULL); + return(CVDLS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CVDLS_NO_ADJ, "CVSLAPACK", "CVLapackDenseB", MSGD_NO_ADJ); + return(CVDLS_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= ca_mem->ca_nbckpbs ) { + cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSLAPACK", "CVLapackDenseB", MSGCV_BAD_WHICH); + return(CVDLS_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + /* Get memory for CVDlsMemRecB */ + cvdlsB_mem = (CVDlsMemB) malloc(sizeof(struct CVDlsMemRecB)); + if (cvdlsB_mem == NULL) { + cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSLAPACK", "CVLapackDenseB", MSGD_MEM_FAIL); + return(CVDLS_MEM_FAIL); + } + + /* set matrix type */ + cvdlsB_mem->d_typeB = SUNDIALS_DENSE; + + /* initialize Jacobian function */ + cvdlsB_mem->d_djacB = NULL; + + /* attach lmemB and lfreeB */ + cvB_mem->cv_lmem = cvdlsB_mem; + cvB_mem->cv_lfree = cvLapackDenseFreeB; + + flag = CVLapackDense(cvodeB_mem, nB); + + if (flag != CVDLS_SUCCESS) { + free(cvdlsB_mem); + cvdlsB_mem = NULL; + } + + return(flag); +} + +/* + * cvLapackDenseFreeB frees the memory associated with the dense CVSLAPACK + * linear solver for backward integration. + */ + +static void cvLapackDenseFreeB(CVodeBMem cvB_mem) +{ + CVDlsMemB cvdlsB_mem; + + cvdlsB_mem = (CVDlsMemB) (cvB_mem->cv_lmem); + + free(cvdlsB_mem); +} + +/* + * CVLapackBandB is a wraper around CVLapackBand. It attaches the band + * CVSLAPACK linear solver to the backward problem memory block. + */ + +int CVLapackBandB(void *cvode_mem, int which, + int nB, int mupperB, int mlowerB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + CVDlsMemB cvdlsB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVDLS_MEM_NULL, "CVSLAPACK", "CVLapackBandB", MSGD_CVMEM_NULL); + return(CVDLS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CVDLS_NO_ADJ, "CVSLAPACK", "CVLapackBandB", MSGD_NO_ADJ); + return(CVDLS_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= ca_mem->ca_nbckpbs ) { + cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSLAPACK", "CVLapackBandB", MSGCV_BAD_WHICH); + return(CVDLS_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + /* Get memory for CVDlsMemRecB */ + cvdlsB_mem = (CVDlsMemB) malloc(sizeof(struct CVDlsMemRecB)); + if (cvdlsB_mem == NULL) { + cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSLAPACK", "CVLapackBandB", MSGD_MEM_FAIL); + return(CVDLS_MEM_FAIL); + } + + /* set matrix type */ + cvdlsB_mem->d_typeB = SUNDIALS_BAND; + + /* initialize Jacobian function */ + cvdlsB_mem->d_bjacB = NULL; + + /* attach lmemB and lfreeB */ + cvB_mem->cv_lmem = cvdlsB_mem; + cvB_mem->cv_lfree = cvLapackBandFreeB; + + flag = CVLapackBand(cvodeB_mem, nB, mupperB, mlowerB); + + if (flag != CVDLS_SUCCESS) { + free(cvdlsB_mem); + cvdlsB_mem = NULL; + } + + return(flag); +} + +/* + * cvLapackBandFreeB frees the memory associated with the band CVSLAPACK + * linear solver for backward integration. + */ + +static void cvLapackBandFreeB(CVodeBMem cvB_mem) +{ + CVDlsMemB cvdlsB_mem; + + cvdlsB_mem = (CVDlsMemB) (cvB_mem->cv_lmem); + + free(cvdlsB_mem); +} diff --git a/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_spbcgs.c b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_spbcgs.c new file mode 100644 index 0000000..31fda60 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_spbcgs.c @@ -0,0 +1,571 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.11 $ + * $Date: 2008/09/03 20:26:21 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the CVSPBCG linear solver. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include "cvodes_spils_impl.h" +#include "cvodes_impl.h" + +#include +#include + +/* Constants */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +/* CVSPBCG linit, lsetup, lsolve, and lfree routines */ + +static int CVSpbcgInit(CVodeMem cv_mem); + +static int CVSpbcgSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, + N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1, + N_Vector vtemp2, N_Vector vtemp3); + +static int CVSpbcgSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector ynow, N_Vector fnow); + +static void CVSpbcgFree(CVodeMem cv_mem); + +/* CVSPBCG lfreeB function */ + +static void CVSpbcgFreeB(CVodeBMem cvB_mem); + +/* + * ================================================================ + * + * PART I - forward problems + * + * ================================================================ + */ + +/* Readability Replacements */ + +#define tq (cv_mem->cv_tq) +#define nst (cv_mem->cv_nst) +#define tn (cv_mem->cv_tn) +#define gamma (cv_mem->cv_gamma) +#define gammap (cv_mem->cv_gammap) +#define f (cv_mem->cv_f) +#define user_data (cv_mem->cv_user_data) +#define ewt (cv_mem->cv_ewt) +#define errfp (cv_mem->cv_errfp) +#define mnewt (cv_mem->cv_mnewt) +#define linit (cv_mem->cv_linit) +#define lsetup (cv_mem->cv_lsetup) +#define lsolve (cv_mem->cv_lsolve) +#define lfree (cv_mem->cv_lfree) +#define lmem (cv_mem->cv_lmem) +#define vec_tmpl (cv_mem->cv_tempv) +#define setupNonNull (cv_mem->cv_setupNonNull) + +#define sqrtN (cvspils_mem->s_sqrtN) +#define ytemp (cvspils_mem->s_ytemp) +#define x (cvspils_mem->s_x) +#define ycur (cvspils_mem->s_ycur) +#define fcur (cvspils_mem->s_fcur) +#define delta (cvspils_mem->s_delta) +#define deltar (cvspils_mem->s_deltar) +#define npe (cvspils_mem->s_npe) +#define nli (cvspils_mem->s_nli) +#define nps (cvspils_mem->s_nps) +#define ncfl (cvspils_mem->s_ncfl) +#define nstlpre (cvspils_mem->s_nstlpre) +#define njtimes (cvspils_mem->s_njtimes) +#define nfes (cvspils_mem->s_nfes) +#define spils_mem (cvspils_mem->s_spils_mem) + +#define jtimesDQ (cvspils_mem->s_jtimesDQ) +#define jtimes (cvspils_mem->s_jtimes) +#define j_data (cvspils_mem->s_j_data) + +#define last_flag (cvspils_mem->s_last_flag) + +/* + * ----------------------------------------------------------------- + * Function : CVSpbcg + * ----------------------------------------------------------------- + * This routine initializes the memory record and sets various function + * fields specific to the Spbcg linear solver module. CVSpbcg first + * calls the existing lfree routine if this is not NULL. It then sets + * the cv_linit, cv_lsetup, cv_lsolve, cv_lfree fields in (*cvode_mem) + * to be CVSpbcgInit, CVSpbcgSetup, CVSpbcgSolve, and CVSpbcgFree, + * respectively. It allocates memory for a structure of type + * CVSpilsMemRec and sets the cv_lmem field in (*cvode_mem) to the + * address of this structure. It sets setupNonNull in (*cvode_mem), + * and sets various fields in the CVSpilsMemRec structure. + * Finally, CVSpbcg allocates memory for ytemp and x, and calls + * SpbcgMalloc to allocate memory for the Spbcg solver. + * ----------------------------------------------------------------- + */ + +int CVSpbcg(void *cvode_mem, int pretype, int maxl) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + SpbcgMem spbcg_mem; + int mxl; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPBCG", "CVSpbcg", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Check if N_VDotProd is present */ + if (vec_tmpl->ops->nvdotprod == NULL) { + cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPBCG", "CVSpbcg", MSGS_BAD_NVECTOR); + return(CVSPILS_ILL_INPUT); + } + + if (lfree != NULL) lfree(cv_mem); + + /* Set four main function fields in cv_mem */ + linit = CVSpbcgInit; + lsetup = CVSpbcgSetup; + lsolve = CVSpbcgSolve; + lfree = CVSpbcgFree; + + /* Get memory for CVSpilsMemRec */ + cvspils_mem = NULL; + cvspils_mem = (CVSpilsMem) malloc(sizeof(struct CVSpilsMemRec)); + if (cvspils_mem == NULL) { + cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPBCG", "CVSpbcg", MSGS_MEM_FAIL); + return(CVSPILS_MEM_FAIL); + } + + /* Set ILS type */ + cvspils_mem->s_type = SPILS_SPBCG; + + /* Set Spbcg parameters that have been passed in call sequence */ + cvspils_mem->s_pretype = pretype; + mxl = cvspils_mem->s_maxl = (maxl <= 0) ? CVSPILS_MAXL : maxl; + + /* Set defaults for Jacobian-related fileds */ + jtimesDQ = TRUE; + jtimes = NULL; + j_data = NULL; + + /* Set defaults for preconditioner-related fields */ + cvspils_mem->s_pset = NULL; + cvspils_mem->s_psolve = NULL; + cvspils_mem->s_pfree = NULL; + cvspils_mem->s_P_data = cv_mem->cv_user_data; + + /* Set default values for the rest of the Spbcg parameters */ + cvspils_mem->s_eplifac = CVSPILS_EPLIN; + + cvspils_mem->s_last_flag = CVSPILS_SUCCESS; + + setupNonNull = FALSE; + + /* Check for legal pretype */ + if ((pretype != PREC_NONE) && (pretype != PREC_LEFT) && + (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) { + cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPBCG", "CVSpbcg", MSGS_BAD_PRETYPE); + return(CVSPILS_ILL_INPUT); + } + + /* Allocate memory for ytemp and x */ + ytemp = N_VClone(vec_tmpl); + if (ytemp == NULL) { + cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPBCG", "CVSpbcg", MSGS_MEM_FAIL); + free(cvspils_mem); cvspils_mem = NULL; + return(CVSPILS_MEM_FAIL); + } + x = N_VClone(vec_tmpl); + if (x == NULL) { + cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPBCG", "CVSpbcg", MSGS_MEM_FAIL); + N_VDestroy(ytemp); + free(cvspils_mem); cvspils_mem = NULL; + return(CVSPILS_MEM_FAIL); + } + + /* Compute sqrtN from a dot product */ + N_VConst(ONE, ytemp); + sqrtN = RSqrt(N_VDotProd(ytemp, ytemp)); + + /* Call SpbcgMalloc to allocate workspace for Spbcg */ + spbcg_mem = NULL; + spbcg_mem = SpbcgMalloc(mxl, vec_tmpl); + if (spbcg_mem == NULL) { + cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPBCG", "CVSpbcg", MSGS_MEM_FAIL); + N_VDestroy(ytemp); + N_VDestroy(x); + free(cvspils_mem); cvspils_mem = NULL; + return(CVSPILS_MEM_FAIL); + } + + /* Attach SPBCG memory to spils memory structure */ + spils_mem = (void *) spbcg_mem; + + /* Attach linear solver memory to integrator memory */ + lmem = cvspils_mem; + + return(CVSPILS_SUCCESS); +} + + + +/* Additional readability replacements */ + +#define pretype (cvspils_mem->s_pretype) +#define eplifac (cvspils_mem->s_eplifac) +#define maxl (cvspils_mem->s_maxl) +#define psolve (cvspils_mem->s_psolve) +#define pset (cvspils_mem->s_pset) +#define P_data (cvspils_mem->s_P_data) + +/* + * ----------------------------------------------------------------- + * Function : CVSpbcgInit + * ----------------------------------------------------------------- + * This routine does remaining initializations specific to the Spbcg + * linear solver. + * ----------------------------------------------------------------- + */ + +static int CVSpbcgInit(CVodeMem cv_mem) +{ + CVSpilsMem cvspils_mem; + SpbcgMem spbcg_mem; + + cvspils_mem = (CVSpilsMem) lmem; + spbcg_mem = (SpbcgMem) spils_mem; + + + /* Initialize counters */ + npe = nli = nps = ncfl = nstlpre = 0; + njtimes = nfes = 0; + + /* Check for legal combination pretype - psolve */ + if ((pretype != PREC_NONE) && (psolve == NULL)) { + cvProcessError(cv_mem, -1, "CVSPBCG", "CVSpbcgInit", MSGS_PSOLVE_REQ); + last_flag = CVSPILS_ILL_INPUT; + return(-1); + } + + /* Set setupNonNull = TRUE iff there is preconditioning + (pretype != PREC_NONE) and there is a preconditioning + setup phase (pset != NULL) */ + setupNonNull = (pretype != PREC_NONE) && (pset != NULL); + + /* Set Jacobian-related fields, based on jtimesDQ */ + if (jtimesDQ) { + jtimes = CVSpilsDQJtimes; + j_data = cv_mem; + } else { + j_data = user_data; + } + + /* Set maxl in the SPBCG memory in case it was changed by the user */ + spbcg_mem->l_max = maxl; + + last_flag = CVSPILS_SUCCESS; + return(0); +} + +/* + * ----------------------------------------------------------------- + * Function : CVSpbcgSetup + * ----------------------------------------------------------------- + * This routine does the setup operations for the Spbcg linear solver. + * It makes a decision as to whether or not to signal for reevaluation + * of Jacobian data in the pset routine, based on various state + * variables, then it calls pset. If we signal for reevaluation, + * then we reset jcur = *jcurPtr to TRUE, regardless of the pset output. + * In any case, if jcur == TRUE, we increment npe and save nst in nstlpre. + * ----------------------------------------------------------------- + */ + +static int CVSpbcgSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, + N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1, + N_Vector vtemp2, N_Vector vtemp3) +{ + booleantype jbad, jok; + realtype dgamma; + int retval; + CVSpilsMem cvspils_mem; + + cvspils_mem = (CVSpilsMem) lmem; + + /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */ + dgamma = ABS((gamma/gammap) - ONE); + jbad = (nst == 0) || (nst > nstlpre + CVSPILS_MSBPRE) || + ((convfail == CV_FAIL_BAD_J) && (dgamma < CVSPILS_DGMAX)) || + (convfail == CV_FAIL_OTHER); + *jcurPtr = jbad; + jok = !jbad; + + /* Call pset routine and possibly reset jcur */ + retval = pset(tn, ypred, fpred, jok, jcurPtr, gamma, P_data, + vtemp1, vtemp2, vtemp3); + if (retval < 0) { + cvProcessError(cv_mem, SPBCG_PSET_FAIL_UNREC, "CVSPBCG", "CVSpbcgSetup", MSGS_PSET_FAILED); + last_flag = SPBCG_PSET_FAIL_UNREC; + } + if (retval > 0) { + last_flag = SPBCG_PSET_FAIL_REC; + } + + if (jbad) *jcurPtr = TRUE; + + /* If jcur = TRUE, increment npe and save nst value */ + if (*jcurPtr) { + npe++; + nstlpre = nst; + } + + last_flag = SPBCG_SUCCESS; + + /* Return the same value that pset returned */ + return(retval); +} + +/* + * ----------------------------------------------------------------- + * Function : CVSpbcgSolve + * ----------------------------------------------------------------- + * This routine handles the call to the generic solver SpbcgSolve + * for the solution of the linear system Ax = b with the SPBCG method. + * The solution x is returned in the vector b. + * + * If the WRMS norm of b is small, we return x = b (if this is the first + * Newton iteration) or x = 0 (if a later Newton iteration). + * + * Otherwise, we set the tolerance parameter and initial guess (x = 0), + * call SpbcgSolve, and copy the solution x into b. The x-scaling and + * b-scaling arrays are both equal to weight. + * + * The counters nli, nps, and ncfl are incremented, and the return value + * is set according to the success of SpbcgSolve. The success flag is + * returned if SpbcgSolve converged, or if this is the first Newton + * iteration and the residual norm was reduced below its initial value. + * ----------------------------------------------------------------- + */ + +static int CVSpbcgSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector ynow, N_Vector fnow) +{ + realtype bnorm, res_norm; + CVSpilsMem cvspils_mem; + SpbcgMem spbcg_mem; + int nli_inc, nps_inc, retval; + + cvspils_mem = (CVSpilsMem) lmem; + + spbcg_mem = (SpbcgMem) spils_mem; + + /* Test norm(b); if small, return x = 0 or x = b */ + deltar = eplifac * tq[4]; + + bnorm = N_VWrmsNorm(b, weight); + if (bnorm <= deltar) { + if (mnewt > 0) N_VConst(ZERO, b); + return(0); + } + + /* Set vectors ycur and fcur for use by the Atimes and Psolve routines */ + ycur = ynow; + fcur = fnow; + + /* Set inputs delta and initial guess x = 0 to SpbcgSolve */ + delta = deltar * sqrtN; + N_VConst(ZERO, x); + + /* Call SpbcgSolve and copy x to b */ + retval = SpbcgSolve(spbcg_mem, cv_mem, x, b, pretype, delta, + cv_mem, weight, weight, CVSpilsAtimes, CVSpilsPSolve, + &res_norm, &nli_inc, &nps_inc); + + N_VScale(ONE, x, b); + + /* Increment counters nli, nps, and ncfl */ + nli += nli_inc; + nps += nps_inc; + if (retval != SPBCG_SUCCESS) ncfl++; + + /* Interpret return value from SpbcgSolve */ + + last_flag = retval; + + switch(retval) { + + case SPBCG_SUCCESS: + return(0); + break; + case SPBCG_RES_REDUCED: + if (mnewt == 0) return(0); + else return(1); + break; + case SPBCG_CONV_FAIL: + return(1); + break; + case SPBCG_PSOLVE_FAIL_REC: + return(1); + break; + case SPBCG_ATIMES_FAIL_REC: + return(1); + break; + case SPBCG_MEM_NULL: + return(-1); + break; + case SPBCG_ATIMES_FAIL_UNREC: + cvProcessError(cv_mem, SPBCG_ATIMES_FAIL_UNREC, "CVSPBCG", "CVSpbcgSolve", MSGS_JTIMES_FAILED); + return(-1); + break; + case SPBCG_PSOLVE_FAIL_UNREC: + cvProcessError(cv_mem, SPBCG_PSOLVE_FAIL_UNREC, "CVSPBCG", "CVSpbcgSolve", MSGS_PSOLVE_FAILED); + return(-1); + break; + } + + return(0); + +} + +/* + * ----------------------------------------------------------------- + * Function : CVSpbcgFree + * ----------------------------------------------------------------- + * This routine frees memory specific to the Spbcg linear solver. + * ----------------------------------------------------------------- + */ + +static void CVSpbcgFree(CVodeMem cv_mem) +{ + CVSpilsMem cvspils_mem; + SpbcgMem spbcg_mem; + + cvspils_mem = (CVSpilsMem) lmem; + + N_VDestroy(ytemp); + N_VDestroy(x); + + spbcg_mem = (SpbcgMem) spils_mem; + SpbcgFree(spbcg_mem); + + if (cvspils_mem->s_pfree != NULL) (cvspils_mem->s_pfree)(cv_mem); + + free(cvspils_mem); cvspils_mem = NULL; +} + + +/* + * ================================================================ + * + * PART II - backward problems + * + * ================================================================ + */ + + +/* Additional readability replacements */ + +#define pset_B (cvspilsB_mem->s_psetB) +#define psolve_B (cvspilsB_mem->s_psolveB) +#define jtimes_B (cvspilsB_mem->s_jtimesB) +#define P_data_B (cvspilsB_mem->s_P_dataB) + +/* + * CVSpbcgB + * + * Wrapper for the backward phase + */ + +int CVSpbcgB(void *cvode_mem, int which, int pretypeB, int maxlB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + CVSpilsMemB cvspilsB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPBCG", "CVSpbcgB", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSPBCG", "CVSpbcgB", MSGS_NO_ADJ); + return(CVSPILS_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= ca_mem->ca_nbckpbs ) { + cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPBCG", "CVSpbcgB", MSGS_BAD_WHICH); + return(CVSPILS_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + /* Get memory for CVSpilsMemRecB */ + cvspilsB_mem = NULL; + cvspilsB_mem = (CVSpilsMemB) malloc(sizeof(struct CVSpilsMemRecB)); + if (cvspilsB_mem == NULL) { + cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPBCG", "CVSpbcgB", MSGS_MEM_FAIL); + return(CVSPILS_MEM_FAIL); + } + + pset_B = NULL; + psolve_B = NULL; + P_data_B = NULL; + + /* initialize Jacobian function */ + jtimes_B = NULL; + + /* attach lmemB and lfree */ + cvB_mem->cv_lmem = cvspilsB_mem; + cvB_mem->cv_lfree = CVSpbcgFreeB; + + flag = CVSpbcg(cvodeB_mem, pretypeB, maxlB); + + if (flag != CVSPILS_SUCCESS) { + free(cvspilsB_mem); + cvspilsB_mem = NULL; + } + + return(flag); +} + +/* + * CVSpbcgFreeB + */ + + +static void CVSpbcgFreeB(CVodeBMem cvB_mem) +{ + CVSpilsMemB cvspilsB_mem; + + cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem); + + free(cvspilsB_mem); +} diff --git a/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_spgmr.c b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_spgmr.c new file mode 100644 index 0000000..2eaa05a --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_spgmr.c @@ -0,0 +1,577 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.11 $ + * $Date: 2008/09/03 20:26:21 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the CVSPGMR linear solver. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include "cvodes_spils_impl.h" +#include "cvodes_impl.h" + +#include +#include + +/* Constants */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +/* CVSPGMR linit, lsetup, lsolve, and lfree routines */ + +static int CVSpgmrInit(CVodeMem cv_mem); + +static int CVSpgmrSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, + N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1, + N_Vector vtemp2, N_Vector vtemp3); + +static int CVSpgmrSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector ynow, N_Vector fnow); + +static void CVSpgmrFree(CVodeMem cv_mem); + +/* CVSPGMR lfreeB function */ + +static void CVSpgmrFreeB(CVodeBMem cvB_mem); + +/* + * ================================================================ + * + * PART I - forward problems + * + * ================================================================ + */ + + +/* Readability Replacements */ + +#define tq (cv_mem->cv_tq) +#define nst (cv_mem->cv_nst) +#define tn (cv_mem->cv_tn) +#define h (cv_mem->cv_h) +#define gamma (cv_mem->cv_gamma) +#define gammap (cv_mem->cv_gammap) +#define f (cv_mem->cv_f) +#define user_data (cv_mem->cv_user_data) +#define ewt (cv_mem->cv_ewt) +#define mnewt (cv_mem->cv_mnewt) +#define ropt (cv_mem->cv_ropt) +#define linit (cv_mem->cv_linit) +#define lsetup (cv_mem->cv_lsetup) +#define lsolve (cv_mem->cv_lsolve) +#define lfree (cv_mem->cv_lfree) +#define lmem (cv_mem->cv_lmem) +#define vec_tmpl (cv_mem->cv_tempv) +#define setupNonNull (cv_mem->cv_setupNonNull) + +#define sqrtN (cvspils_mem->s_sqrtN) +#define ytemp (cvspils_mem->s_ytemp) +#define x (cvspils_mem->s_x) +#define ycur (cvspils_mem->s_ycur) +#define fcur (cvspils_mem->s_fcur) +#define delta (cvspils_mem->s_delta) +#define deltar (cvspils_mem->s_deltar) +#define npe (cvspils_mem->s_npe) +#define nli (cvspils_mem->s_nli) +#define nps (cvspils_mem->s_nps) +#define ncfl (cvspils_mem->s_ncfl) +#define nstlpre (cvspils_mem->s_nstlpre) +#define njtimes (cvspils_mem->s_njtimes) +#define nfes (cvspils_mem->s_nfes) +#define spils_mem (cvspils_mem->s_spils_mem) + +#define jtimesDQ (cvspils_mem->s_jtimesDQ) +#define jtimes (cvspils_mem->s_jtimes) +#define j_data (cvspils_mem->s_j_data) + +#define last_flag (cvspils_mem->s_last_flag) + +/* + * ----------------------------------------------------------------- + * CVSpgmr + * ----------------------------------------------------------------- + * This routine initializes the memory record and sets various function + * fields specific to the Spgmr linear solver module. CVSpgmr first + * calls the existing lfree routine if this is not NULL. It then sets + * the cv_linit, cv_lsetup, cv_lsolve, cv_lfree fields in (*cvode_mem) + * to be CVSpgmrInit, CVSpgmrSetup, CVSpgmrSolve, and CVSpgmrFree, + * respectively. It allocates memory for a structure of type + * CVSpilsMemRec and sets the cv_lmem field in (*cvode_mem) to the + * address of this structure. It sets setupNonNull in (*cvode_mem), + * and sets various fields in the CVSpilsMemRec structure. + * Finally, CVSpgmr allocates memory for ytemp and x, and calls + * SpgmrMalloc to allocate memory for the Spgmr solver. + * ----------------------------------------------------------------- + */ + +int CVSpgmr(void *cvode_mem, int pretype, int maxl) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + SpgmrMem spgmr_mem; + int mxl; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPGMR", "CVSpgmr", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Check if N_VDotProd is present */ + if(vec_tmpl->ops->nvdotprod == NULL) { + cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPGMR", "CVSpgmr", MSGS_BAD_NVECTOR); + return(CVSPILS_ILL_INPUT); + } + + if (lfree != NULL) lfree(cv_mem); + + /* Set four main function fields in cv_mem */ + linit = CVSpgmrInit; + lsetup = CVSpgmrSetup; + lsolve = CVSpgmrSolve; + lfree = CVSpgmrFree; + + /* Get memory for CVSpilsMemRec */ + cvspils_mem = NULL; + cvspils_mem = (CVSpilsMem) malloc(sizeof(struct CVSpilsMemRec)); + if (cvspils_mem == NULL) { + cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPGMR", "CVSpgmr", MSGS_MEM_FAIL); + return(CVSPILS_MEM_FAIL); + } + + /* Set ILS type */ + cvspils_mem->s_type = SPILS_SPGMR; + + /* Set Spgmr parameters that have been passed in call sequence */ + cvspils_mem->s_pretype = pretype; + mxl = cvspils_mem->s_maxl = (maxl <= 0) ? CVSPILS_MAXL : maxl; + + /* Set defaults for Jacobian-related fileds */ + jtimesDQ = TRUE; + jtimes = NULL; + j_data = NULL; + + /* Set defaults for preconditioner-related fields */ + cvspils_mem->s_pset = NULL; + cvspils_mem->s_psolve = NULL; + cvspils_mem->s_pfree = NULL; + cvspils_mem->s_P_data = cv_mem->cv_user_data; + + /* Set default values for the rest of the Spgmr parameters */ + cvspils_mem->s_gstype = MODIFIED_GS; + cvspils_mem->s_eplifac = CVSPILS_EPLIN; + + cvspils_mem->s_last_flag = CVSPILS_SUCCESS; + + setupNonNull = FALSE; + + /* Check for legal pretype */ + if ((pretype != PREC_NONE) && (pretype != PREC_LEFT) && + (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) { + cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPGMR", "CVSpgmr", MSGS_BAD_PRETYPE); + return(CVSPILS_ILL_INPUT); + } + + /* Allocate memory for ytemp and x */ + ytemp = N_VClone(vec_tmpl); + if (ytemp == NULL) { + cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPGMR", "CVSpgmr", MSGS_MEM_FAIL); + free(cvspils_mem); cvspils_mem = NULL; + return(CVSPILS_MEM_FAIL); + } + x = N_VClone(vec_tmpl); + if (x == NULL) { + cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPGMR", "CVSpgmr", MSGS_MEM_FAIL); + N_VDestroy(ytemp); + free(cvspils_mem); cvspils_mem = NULL; + return(CVSPILS_MEM_FAIL); + } + + /* Compute sqrtN from a dot product */ + N_VConst(ONE, ytemp); + sqrtN = RSqrt( N_VDotProd(ytemp, ytemp) ); + + /* Call SpgmrMalloc to allocate workspace for Spgmr */ + spgmr_mem = NULL; + spgmr_mem = SpgmrMalloc(mxl, vec_tmpl); + if (spgmr_mem == NULL) { + cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPGMR", "CVSpgmr", MSGS_MEM_FAIL); + N_VDestroy(ytemp); + N_VDestroy(x); + free(cvspils_mem); cvspils_mem = NULL; + return(CVSPILS_MEM_FAIL); + } + + /* Attach SPGMR memory to spils memory structure */ + spils_mem = (void *) spgmr_mem; + + /* Attach linear solver memory to integrator memory */ + lmem = cvspils_mem; + + return(CVSPILS_SUCCESS); +} + + +/* Additional readability Replacements */ + +#define pretype (cvspils_mem->s_pretype) +#define gstype (cvspils_mem->s_gstype) +#define eplifac (cvspils_mem->s_eplifac) +#define maxl (cvspils_mem->s_maxl) +#define psolve (cvspils_mem->s_psolve) +#define pset (cvspils_mem->s_pset) +#define P_data (cvspils_mem->s_P_data) + +/* + * ----------------------------------------------------------------- + * CVSpgmrInit + * ----------------------------------------------------------------- + * This routine does remaining initializations specific to the Spgmr + * linear solver. + * ----------------------------------------------------------------- + */ + +static int CVSpgmrInit(CVodeMem cv_mem) +{ + CVSpilsMem cvspils_mem; + cvspils_mem = (CVSpilsMem) lmem; + + /* Initialize counters */ + npe = nli = nps = ncfl = nstlpre = 0; + njtimes = nfes = 0; + + /* Check for legal combination pretype - psolve */ + if ((pretype != PREC_NONE) && (psolve == NULL)) { + cvProcessError(cv_mem, -1, "CVSPGMR", "CVSpgmrInit", MSGS_PSOLVE_REQ); + last_flag = CVSPILS_ILL_INPUT; + return(-1); + } + + /* Set setupNonNull = TRUE iff there is preconditioning (pretype != PREC_NONE) + and there is a preconditioning setup phase (pset != NULL) */ + setupNonNull = (pretype != PREC_NONE) && (pset != NULL); + + /* Set Jacobian-related fields, based on jtimesDQ */ + if (jtimesDQ) { + jtimes = CVSpilsDQJtimes; + j_data = cv_mem; + } else { + j_data = user_data; + } + + last_flag = CVSPILS_SUCCESS; + return(0); +} + +/* + * ----------------------------------------------------------------- + * CVSpgmrSetup + * ----------------------------------------------------------------- + * This routine does the setup operations for the Spgmr linear solver. + * It makes a decision as to whether or not to signal for re-evaluation + * of Jacobian data in the pset routine, based on various state + * variables, then it calls pset. If we signal for re-evaluation, + * then we reset jcur = *jcurPtr to TRUE, regardless of the pset output. + * In any case, if jcur == TRUE, we increment npe and save nst in nstlpre. + * ----------------------------------------------------------------- + */ + +static int CVSpgmrSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, + N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1, + N_Vector vtemp2, N_Vector vtemp3) +{ + booleantype jbad, jok; + realtype dgamma; + int retval; + CVSpilsMem cvspils_mem; + + cvspils_mem = (CVSpilsMem) lmem; + + /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */ + dgamma = ABS((gamma/gammap) - ONE); + jbad = (nst == 0) || (nst > nstlpre + CVSPILS_MSBPRE) || + ((convfail == CV_FAIL_BAD_J) && (dgamma < CVSPILS_DGMAX)) || + (convfail == CV_FAIL_OTHER); + *jcurPtr = jbad; + jok = !jbad; + + /* Call pset routine and possibly reset jcur */ + retval = pset(tn, ypred, fpred, jok, jcurPtr, gamma, P_data, + vtemp1, vtemp2, vtemp3); + if (retval < 0) { + cvProcessError(cv_mem, SPGMR_PSET_FAIL_UNREC, "CVSPGMR", "CVSpgmrSetup", MSGS_PSET_FAILED); + last_flag = SPGMR_PSET_FAIL_UNREC; + } + if (retval > 0) { + last_flag = SPGMR_PSET_FAIL_REC; + } + + if (jbad) *jcurPtr = TRUE; + + /* If jcur = TRUE, increment npe and save nst value */ + if (*jcurPtr) { + npe++; + nstlpre = nst; + } + + last_flag = SPGMR_SUCCESS; + + /* Return the same value that pset returned */ + return(retval); +} + +/* + * ----------------------------------------------------------------- + * CVSpgmrSolve + * ----------------------------------------------------------------- + * This routine handles the call to the generic solver SpgmrSolve + * for the solution of the linear system Ax = b with the SPGMR method, + * without restarts. The solution x is returned in the vector b. + * + * If the WRMS norm of b is small, we return x = b (if this is the first + * Newton iteration) or x = 0 (if a later Newton iteration). + * + * Otherwise, we set the tolerance parameter and initial guess (x = 0), + * call SpgmrSolve, and copy the solution x into b. The x-scaling and + * b-scaling arrays are both equal to weight, and no restarts are allowed. + * + * The counters nli, nps, and ncfl are incremented, and the return value + * is set according to the success of SpgmrSolve. The success flag is + * returned if SpgmrSolve converged, or if this is the first Newton + * iteration and the residual norm was reduced below its initial value. + * ----------------------------------------------------------------- + */ + +static int CVSpgmrSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector ynow, N_Vector fnow) +{ + realtype bnorm, res_norm; + CVSpilsMem cvspils_mem; + SpgmrMem spgmr_mem; + int nli_inc, nps_inc, retval; + + cvspils_mem = (CVSpilsMem) lmem; + + spgmr_mem = (SpgmrMem) spils_mem; + + /* Test norm(b); if small, return x = 0 or x = b */ + deltar = eplifac*tq[4]; + + bnorm = N_VWrmsNorm(b, weight); + if (bnorm <= deltar) { + if (mnewt > 0) N_VConst(ZERO, b); + return(0); + } + + /* Set vectors ycur and fcur for use by the Atimes and Psolve routines */ + ycur = ynow; + fcur = fnow; + + /* Set inputs delta and initial guess x = 0 to SpgmrSolve */ + delta = deltar * sqrtN; + N_VConst(ZERO, x); + + /* Call SpgmrSolve and copy x to b */ + retval = SpgmrSolve(spgmr_mem, cv_mem, x, b, pretype, gstype, delta, 0, + cv_mem, weight, weight, CVSpilsAtimes, CVSpilsPSolve, + &res_norm, &nli_inc, &nps_inc); + + N_VScale(ONE, x, b); + + /* Increment counters nli, nps, and ncfl */ + nli += nli_inc; + nps += nps_inc; + if (retval != SPGMR_SUCCESS) ncfl++; + + /* Interpret return value from SpgmrSolve */ + + last_flag = retval; + + switch(retval) { + + case SPGMR_SUCCESS: + return(0); + break; + case SPGMR_RES_REDUCED: + if (mnewt == 0) return(0); + else return(1); + break; + case SPGMR_CONV_FAIL: + return(1); + break; + case SPGMR_QRFACT_FAIL: + return(1); + break; + case SPGMR_PSOLVE_FAIL_REC: + return(1); + break; + case SPGMR_ATIMES_FAIL_REC: + return(1); + break; + case SPGMR_MEM_NULL: + return(-1); + break; + case SPGMR_ATIMES_FAIL_UNREC: + cvProcessError(cv_mem, SPGMR_ATIMES_FAIL_UNREC, "CVSPGMR", "CVSpgmrSolve", MSGS_JTIMES_FAILED); + return(-1); + break; + case SPGMR_PSOLVE_FAIL_UNREC: + cvProcessError(cv_mem, SPGMR_PSOLVE_FAIL_UNREC, "CVSPGMR", "CVSpgmrSolve", MSGS_PSOLVE_FAILED); + return(-1); + break; + case SPGMR_GS_FAIL: + return(-1); + break; + case SPGMR_QRSOL_FAIL: + return(-1); + break; + } + + return(0); + +} + +/* + * ----------------------------------------------------------------- + * CVSpgmrFree + * ----------------------------------------------------------------- + * This routine frees memory specific to the Spgmr linear solver. + * ----------------------------------------------------------------- + */ + +static void CVSpgmrFree(CVodeMem cv_mem) +{ + CVSpilsMem cvspils_mem; + SpgmrMem spgmr_mem; + + cvspils_mem = (CVSpilsMem) lmem; + + N_VDestroy(ytemp); + N_VDestroy(x); + + spgmr_mem = (SpgmrMem) spils_mem; + SpgmrFree(spgmr_mem); + + if (cvspils_mem->s_pfree != NULL) (cvspils_mem->s_pfree)(cv_mem); + + free(cvspils_mem); cvspils_mem = NULL; +} + + +/* + * ================================================================ + * + * PART II - backward problems + * + * ================================================================ + */ + + +/* Additional readability replacements */ + +#define pset_B (cvspilsB_mem->s_psetB) +#define psolve_B (cvspilsB_mem->s_psolveB) +#define jtimes_B (cvspilsB_mem->s_jtimesB) +#define P_data_B (cvspilsB_mem->s_P_dataB) + +/* + * CVSpgmrB + * + * Wrapper for the backward phase + * + */ + +int CVSpgmrB(void *cvode_mem, int which, int pretypeB, int maxlB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + CVSpilsMemB cvspilsB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPGMR", "CVSpgmrB", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSPGMR", "CVSpgmrB", MSGS_NO_ADJ); + return(CVSPILS_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= ca_mem->ca_nbckpbs ) { + cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPGMR", "CVSpgmrB", MSGS_BAD_WHICH); + return(CVSPILS_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + /* Get memory for CVSpilsMemRecB */ + cvspilsB_mem = NULL; + cvspilsB_mem = (CVSpilsMemB) malloc(sizeof(struct CVSpilsMemRecB)); + if (cvspilsB_mem == NULL) { + cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPGMR", "CVSpgmrB", MSGS_MEM_FAIL); + return(CVSPILS_MEM_FAIL); + } + + pset_B = NULL; + psolve_B = NULL; + P_data_B = NULL; + + /* initialize Jacobian function */ + jtimes_B = NULL; + + /* attach lmemB and lfreeB */ + cvB_mem->cv_lmem = cvspilsB_mem; + cvB_mem->cv_lfree = CVSpgmrFreeB; + + flag = CVSpgmr(cvodeB_mem, pretypeB, maxlB); + + if (flag != CVSPILS_SUCCESS) { + free(cvspilsB_mem); + cvspilsB_mem = NULL; + } + + return(flag); +} + + +/* + * CVSpgmrFreeB + */ + + +static void CVSpgmrFreeB(CVodeBMem cvB_mem) +{ + CVSpilsMemB cvspilsB_mem; + + cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem); + + free(cvspilsB_mem); +} diff --git a/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_spils.c b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_spils.c new file mode 100644 index 0000000..14759b6 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_spils.c @@ -0,0 +1,1182 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.10 $ + * $Date: 2008/09/03 20:26:21 $ + * ----------------------------------------------------------------- + * Programmer(s):Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the CVSPILS linear solvers. + * + * Part II contains wrappers for using the CVODES iterative linear + * solvers on adjoint (backward) problems. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "cvodes_impl.h" +#include "cvodes_spils_impl.h" + +/* Private constants */ + +#define ZERO RCONST(0.0) +#define PT25 RCONST(0.25) +#define ONE RCONST(1.0) + +/* Algorithmic constants */ + +#define MAX_ITERS 3 /* max. number of attempts to recover in DQ J*v */ + +/* + * ================================================================= + * PRIVATE FUNCTION PROTOTYPES + * ================================================================= + */ + +/* + * cvSpilsPrecSetupBWrapper has type CVSpilsPrecSetupFn + * It wraps around the user-provided function of type CVSpilsPrecSetupFnB + */ + +static int cvSpilsPrecSetupBWrapper(realtype t, N_Vector yB, + N_Vector fyB, booleantype jokB, + booleantype *jcurPtrB, realtype gammaB, + void *cvode_mem, + N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B); + +/* + * cvSpilsPrecSolveBWrapper has type CVSpilsPrecSolveFn + * It wraps around the user-provided function of type CVSpilsPrecSolveFnB + */ + +static int cvSpilsPrecSolveBWrapper(realtype t, N_Vector yB, N_Vector fyB, + N_Vector rB, N_Vector zB, + realtype gammaB, realtype deltaB, + int lrB, void *cvode_mem, N_Vector tmpB); + +/* + * cvSpilsJacTimesVecBWrapper has type CVSpilsJacTimesVecFn + * It wraps around the user-provided function of type CVSpilsJacTimesVecFnB + */ + +static int cvSpilsJacTimesVecBWrapper(N_Vector vB, N_Vector JvB, realtype t, + N_Vector yB, N_Vector fyB, + void *cvode_mem, N_Vector tmpB); + +/* + * ================================================================ + * + * PART I - forward problems + * + * ================================================================ + */ + +/* Readability Replacements */ + +#define lrw1 (cv_mem->cv_lrw1) +#define liw1 (cv_mem->cv_liw1) +#define tq (cv_mem->cv_tq) +#define tn (cv_mem->cv_tn) +#define h (cv_mem->cv_h) +#define gamma (cv_mem->cv_gamma) +#define nfe (cv_mem->cv_nfe) +#define f (cv_mem->cv_f) +#define user_data (cv_mem->cv_user_data) +#define ewt (cv_mem->cv_ewt) +#define lmem (cv_mem->cv_lmem) + +#define ils_type (cvspils_mem->s_type) +#define sqrtN (cvspils_mem->s_sqrtN) +#define ytemp (cvspils_mem->s_ytemp) +#define x (cvspils_mem->s_x) +#define ycur (cvspils_mem->s_ycur) +#define fcur (cvspils_mem->s_fcur) +#define delta (cvspils_mem->s_delta) +#define npe (cvspils_mem->s_npe) +#define nli (cvspils_mem->s_nli) +#define nps (cvspils_mem->s_nps) +#define ncfl (cvspils_mem->s_ncfl) +#define njtimes (cvspils_mem->s_njtimes) +#define nfes (cvspils_mem->s_nfes) + +#define jtimesDQ (cvspils_mem->s_jtimesDQ) +#define jtimes (cvspils_mem->s_jtimes) +#define j_data (cvspils_mem->s_j_data) + +#define last_flag (cvspils_mem->s_last_flag) + + +/* + * ----------------------------------------------------------------- + * OPTIONAL INPUT and OUTPUT FUNCTIONS + * ----------------------------------------------------------------- + */ + + +/* + * ----------------------------------------------------------------- + * CVSpilsSetPrecType + * ----------------------------------------------------------------- + */ + +int CVSpilsSetPrecType(void *cvode_mem, int pretype) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetPrecType", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetPrecType", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + /* Check for legal pretype */ + if ((pretype != PREC_NONE) && (pretype != PREC_LEFT) && + (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) { + cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetPrecType", MSGS_BAD_PRETYPE); + return(CVSPILS_ILL_INPUT); + } + + cvspils_mem->s_pretype = pretype; + + return(CVSPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsSetGSType + * ----------------------------------------------------------------- + */ + +int CVSpilsSetGSType(void *cvode_mem, int gstype) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetGSType", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetGSType", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + if (ils_type != SPILS_SPGMR) { + cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetGSType", MSGS_BAD_LSTYPE); + return(CVSPILS_ILL_INPUT); + } + + /* Check for legal gstype */ + if ((gstype != MODIFIED_GS) && (gstype != CLASSICAL_GS)) { + cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetGSType", MSGS_BAD_GSTYPE); + return(CVSPILS_ILL_INPUT); + } + + cvspils_mem->s_gstype = gstype; + + return(CVSPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * Function : CVSpilsSetMaxl + * ----------------------------------------------------------------- + */ + +int CVSpilsSetMaxl(void *cvode_mem, int maxl) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + int mxl; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetMaxl", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + cvProcessError(NULL, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetMaxl", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + if (ils_type == SPILS_SPGMR) { + cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetMaxl", MSGS_BAD_LSTYPE); + return(CVSPILS_ILL_INPUT); + } + + mxl = (maxl <= 0) ? CVSPILS_MAXL : maxl; + cvspils_mem->s_maxl = mxl; + + /* spbcg_mem->l_max = mxl; */ + + return(CVSPILS_SUCCESS); +} + + +/* + * ----------------------------------------------------------------- + * CVSpilsSetEpsLin + * ----------------------------------------------------------------- + */ + +int CVSpilsSetEpsLin(void *cvode_mem, realtype eplifac) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetEpsLin", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetEpsLin", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + /* Check for legal eplifac */ + if(eplifac < ZERO) { + cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetEpsLin", MSGS_BAD_EPLIN); + return(CVSPILS_ILL_INPUT); + } + + cvspils_mem->s_eplifac = (eplifac == ZERO) ? CVSPILS_EPLIN : eplifac; + + return(CVSPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsSetPrecSetupFn + * ----------------------------------------------------------------- + */ + +int CVSpilsSetPreconditioner(void *cvode_mem, + CVSpilsPrecSetupFn pset, CVSpilsPrecSolveFn psolve) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetPreconditioner", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetPreconditioner", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + cvspils_mem->s_pset = pset; + cvspils_mem->s_psolve = psolve; + + return(CVSPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsSetJacTimesVecFn + * ----------------------------------------------------------------- + */ + +int CVSpilsSetJacTimesVecFn(void *cvode_mem, CVSpilsJacTimesVecFn jtv) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetJacTimesVecFn", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetJacTimesVecFn", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + if (jtv != NULL) { + jtimesDQ = FALSE; + jtimes = jtv; + } else { + jtimesDQ = TRUE; + } + + return(CVSPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsGetWorkSpace + * ----------------------------------------------------------------- + */ + +int CVSpilsGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + int maxl; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetWorkSpace", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetWorkSpace", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + + switch(ils_type) { + case SPILS_SPGMR: + maxl = cvspils_mem->s_maxl; + *lenrwLS = lrw1*(maxl + 5) + maxl*(maxl + 4) + 1; + *leniwLS = liw1*(maxl + 5); + break; + case SPILS_SPBCG: + *lenrwLS = lrw1 * 9; + *leniwLS = liw1 * 9; + break; + case SPILS_SPTFQMR: + *lenrwLS = lrw1*11; + *leniwLS = liw1*11; + break; + } + + + return(CVSPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsGetNumPrecEvals + * ----------------------------------------------------------------- + */ + +int CVSpilsGetNumPrecEvals(void *cvode_mem, long int *npevals) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetNumPrecEvals", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetNumPrecEvals", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + *npevals = npe; + + return(CVSPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsGetNumPrecSolves + * ----------------------------------------------------------------- + */ + +int CVSpilsGetNumPrecSolves(void *cvode_mem, long int *npsolves) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetNumPrecSolves", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetNumPrecSolves", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + *npsolves = nps; + + return(CVSPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsGetNumLinIters + * ----------------------------------------------------------------- + */ + +int CVSpilsGetNumLinIters(void *cvode_mem, long int *nliters) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetNumLinIters", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetNumLinIters", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + *nliters = nli; + + return(CVSPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsGetNumConvFails + * ----------------------------------------------------------------- + */ + +int CVSpilsGetNumConvFails(void *cvode_mem, long int *nlcfails) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetNumConvFails", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetNumConvFails", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + *nlcfails = ncfl; + + return(CVSPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsGetNumJtimesEvals + * ----------------------------------------------------------------- + */ + +int CVSpilsGetNumJtimesEvals(void *cvode_mem, long int *njvevals) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetNumJtimesEvals", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetNumJtimesEvals", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + *njvevals = njtimes; + + return(CVSPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsGetNumRhsEvals + * ----------------------------------------------------------------- + */ + +int CVSpilsGetNumRhsEvals(void *cvode_mem, long int *nfevalsLS) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetNumRhsEvals", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetNumRhsEvals", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + *nfevalsLS = nfes; + + return(CVSPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsGetLastFlag + * ----------------------------------------------------------------- + */ + +int CVSpilsGetLastFlag(void *cvode_mem, int *flag) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetLastFlag", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetLastFlag", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + *flag = last_flag; + + return(CVSPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsGetReturnFlagName + * ----------------------------------------------------------------- + */ + +char *CVSpilsGetReturnFlagName(int flag) +{ + char *name; + + name = (char *)malloc(30*sizeof(char)); + + switch(flag) { + case CVSPILS_SUCCESS: + sprintf(name,"CVSPILS_SUCCESS"); + break; + case CVSPILS_MEM_NULL: + sprintf(name,"CVSPILS_MEM_NULL"); + break; + case CVSPILS_LMEM_NULL: + sprintf(name,"CVSPILS_LMEM_NULL"); + break; + case CVSPILS_ILL_INPUT: + sprintf(name,"CVSPILS_ILL_INPUT"); + break; + case CVSPILS_MEM_FAIL: + sprintf(name,"CVSPILS_MEM_FAIL"); + break; + case CVSPILS_PMEM_NULL: + sprintf(name,"CVSPILS_PMEM_NULL"); + break; + case CVSPILS_NO_ADJ: + sprintf(name,"CVSPILS_NO_ADJ"); + break; + case CVSPILS_LMEMB_NULL: + sprintf(name,"CVSPILS_LMEMB_NULL"); + break; + default: + sprintf(name,"NONE"); + } + + return(name); +} + +/* + * ----------------------------------------------------------------- + * CVSPILS private functions + * ----------------------------------------------------------------- + */ + + +/* Additional readability Replacements */ + +#define pretype (cvspils_mem->s_pretype) +#define eplifac (cvspils_mem->s_eplifac) +#define maxl (cvspils_mem->s_maxl) +#define psolve (cvspils_mem->s_psolve) +#define P_data (cvspils_mem->s_P_data) + +/* + * ----------------------------------------------------------------- + * CVSpilsAtimes + * ----------------------------------------------------------------- + * This routine generates the matrix-vector product z = Mv, where + * M = I - gamma*J. The product J*v is obtained by calling the jtimes + * routine. It is then scaled by -gamma and added to v to obtain M*v. + * The return value is the same as the value returned by jtimes -- + * 0 if successful, nonzero otherwise. + * ----------------------------------------------------------------- + */ + +int CVSpilsAtimes(void *cvode_mem, N_Vector v, N_Vector z) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + int retval; + + cv_mem = (CVodeMem) cvode_mem; + cvspils_mem = (CVSpilsMem) lmem; + + retval = jtimes(v, z, tn, ycur, fcur, j_data, ytemp); + njtimes++; + if (retval != 0) return(retval); + + N_VLinearSum(ONE, v, -gamma, z, z); + + return(0); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsPSolve + * ----------------------------------------------------------------- + * This routine interfaces between the generic SpgmrSolve routine and + * the user's psolve routine. It passes to psolve all required state + * information from cvode_mem. Its return value is the same as that + * returned by psolve. Note that the generic SPGMR solver guarantees + * that CVSpilsPSolve will not be called in the case in which + * preconditioning is not done. This is the only case in which the + * user's psolve routine is allowed to be NULL. + * ----------------------------------------------------------------- + */ + +int CVSpilsPSolve(void *cvode_mem, N_Vector r, N_Vector z, int lr) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + int retval; + + cv_mem = (CVodeMem) cvode_mem; + cvspils_mem = (CVSpilsMem)lmem; + + /* This call is counted in nps within the CVSp***Solve routine */ + retval = psolve(tn, ycur, fcur, r, z, gamma, delta, lr, P_data, ytemp); + + return(retval); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsDQJtimes + * ----------------------------------------------------------------- + * This routine generates a difference quotient approximation to + * the Jacobian times vector f_y(t,y) * v. The approximation is + * Jv = vnrm[f(y + v/vnrm) - f(y)], where vnrm = (WRMS norm of v) is + * input, i.e. the WRMS norm of v/vnrm is 1. + * ----------------------------------------------------------------- + */ + +int CVSpilsDQJtimes(N_Vector v, N_Vector Jv, realtype t, + N_Vector y, N_Vector fy, + void *data, N_Vector work) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + realtype sig, siginv; + int iter, retval; + + /* data is cvode_mem */ + cv_mem = (CVodeMem) data; + cvspils_mem = (CVSpilsMem) lmem; + + /* Initialize perturbation to 1/||v|| */ + sig = ONE/N_VWrmsNorm(v, ewt); + + for (iter=0; iter 0) return(+1); + + /* Replace Jv by (Jv - fy)/sig */ + siginv = ONE/sig; + N_VLinearSum(siginv, Jv, -siginv, fy, Jv); + + return(0); +} + +/* + * ================================================================ + * + * PART II - backward problems + * + * ================================================================ + */ + +/* Readability replacements */ + +#define ytmp (ca_mem->ca_ytmp) +#define yStmp (ca_mem->ca_yStmp) +#define IMget (ca_mem->ca_IMget) + +#define pset_B (cvspilsB_mem->s_psetB) +#define psolve_B (cvspilsB_mem->s_psolveB) +#define jtimes_B (cvspilsB_mem->s_jtimesB) + +/* + * ----------------------------------------------------------------- + * OPTIONAL INPUT and OUTPUT FUNCTIONS + * ----------------------------------------------------------------- + */ + +int CVSpilsSetPrecTypeB(void *cvode_mem, int which, int pretypeB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetPrecTypeB", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSPILS", "CVSpilsSetPrecTypeB", MSGS_NO_ADJ); + return(CVSPILS_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= ca_mem->ca_nbckpbs ) { + cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetPrecTypeB", MSGS_BAD_WHICH); + return(CVSPILS_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + flag = CVSpilsSetPrecType(cvodeB_mem, pretypeB); + + return(flag); +} + +int CVSpilsSetGSTypeB(void *cvode_mem, int which, int gstypeB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetGSTypeB", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSPILS", "CVSpilsSetGSTypeB", MSGS_NO_ADJ); + return(CVSPILS_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= ca_mem->ca_nbckpbs ) { + cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetGSTypeB", MSGS_BAD_WHICH); + return(CVSPILS_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + flag = CVSpilsSetGSType(cvodeB_mem,gstypeB); + + return(flag); +} + +int CVSpilsSetEpsLinB(void *cvode_mem, int which, realtype eplifacB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetEpsLinB", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSPILS", "CVSpilsSetEpsLinB", MSGS_NO_ADJ); + return(CVSPILS_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= ca_mem->ca_nbckpbs ) { + cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetEpsLinB", MSGS_BAD_WHICH); + return(CVSPILS_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + flag = CVSpilsSetEpsLin(cvodeB_mem,eplifacB); + + return(flag); +} + +int CVSpilsSetMaxlB(void *cvode_mem, int which, int maxlB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetMaxlB", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSPILS", "CVSpilsSetMaxlB", MSGS_NO_ADJ); + return(CVSPILS_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= ca_mem->ca_nbckpbs ) { + cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetMaxlB", MSGS_BAD_WHICH); + return(CVSPILS_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + flag = CVSpilsSetMaxl(cvodeB_mem,maxlB); + + return(flag); +} + +int CVSpilsSetPreconditionerB(void *cvode_mem, int which, + CVSpilsPrecSetupFnB psetB, + CVSpilsPrecSolveFnB psolveB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + CVSpilsMemB cvspilsB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetPreconsitionerB", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSPILS", "CVSpilsSetPreconsitionerB", MSGS_NO_ADJ); + return(CVSPILS_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= ca_mem->ca_nbckpbs ) { + cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetPreconsitionerB", MSGS_BAD_WHICH); + return(CVSPILS_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + if (cvB_mem->cv_lmem == NULL) { + cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSPILS", "CVSpilsSetPreconditonerB", MSGS_LMEMB_NULL); + return(CVSPILS_LMEMB_NULL); + } + cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem); + + pset_B = psetB; + psolve_B = psolveB; + + flag = CVSpilsSetPreconditioner(cvodeB_mem, cvSpilsPrecSetupBWrapper, cvSpilsPrecSolveBWrapper); + + return(flag); +} + +int CVSpilsSetJacTimesVecFnB(void *cvode_mem, int which, CVSpilsJacTimesVecFnB jtvB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + CVSpilsMemB cvspilsB_mem; + void *cvodeB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetJacTimesVecFnB", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSPILS", "CVSpilsSetJacTimesVecFnB", MSGS_NO_ADJ); + return(CVSPILS_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= ca_mem->ca_nbckpbs ) { + cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetJacTimesVecFnB", MSGS_BAD_WHICH); + return(CVSPILS_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + if (cvB_mem->cv_lmem == NULL) { + cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSPILS", "CVSpilsSetJacTimesVecFnB", MSGS_LMEMB_NULL); + return(CVSPILS_LMEMB_NULL); + } + cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem); + + jtimes_B = jtvB; + + if (jtvB != NULL) { + flag = CVSpilsSetJacTimesVecFn(cvodeB_mem, cvSpilsJacTimesVecBWrapper); + } else { + flag = CVSpilsSetJacTimesVecFn(cvodeB_mem, NULL); + } + + return(flag); +} + + +/* + * ----------------------------------------------------------------- + * CVSPILS private functions + * ----------------------------------------------------------------- + */ + +/* + * cvSpilsPrecSetupBWrapper + * + * This routine interfaces to the CVSpilsPrecSetupFnB routine + * provided by the user. + */ + +static int cvSpilsPrecSetupBWrapper(realtype t, N_Vector yB, + N_Vector fyB, booleantype jokB, + booleantype *jcurPtrB, realtype gammaB, + void *cvode_mem, + N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + CVSpilsMemB cvspilsB_mem; + int retval, flag; + + cv_mem = (CVodeMem) cvode_mem; + + ca_mem = cv_mem->cv_adj_mem; + + cvB_mem = ca_mem->ca_bckpbCrt; + + cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem); + + /* Forward solution from interpolation */ + flag = IMget(cv_mem, t, ytmp, NULL); + if (flag != CV_SUCCESS) { + cvProcessError(cv_mem, -1, "CVSPILS", "cvSpilsPrecSetupBWrapper", MSGS_BAD_TINTERP); + return(-1); + } + + /* Call user's adjoint precondB routine */ + retval = pset_B(t, ytmp, yB, fyB, jokB, jcurPtrB, gammaB, + cvB_mem->cv_user_data, tmp1B, tmp2B, tmp3B); + + return(retval); +} + + +/* + * cvSpilsPrecSolveBWrapper + * + * This routine interfaces to the CVSpilsPrecSolveFnB routine + * provided by the user. + */ + +static int cvSpilsPrecSolveBWrapper(realtype t, N_Vector yB, N_Vector fyB, + N_Vector rB, N_Vector zB, + realtype gammaB, realtype deltaB, + int lrB, void *cvode_mem, N_Vector tmpB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + CVSpilsMemB cvspilsB_mem; + int retval, flag; + + cv_mem = (CVodeMem) cvode_mem; + + ca_mem = cv_mem->cv_adj_mem; + + cvB_mem = ca_mem->ca_bckpbCrt; + + cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem); + + /* Forward solution from interpolation */ + flag = IMget(cv_mem, t, ytmp, NULL); + if (flag != CV_SUCCESS) { + cvProcessError(cv_mem, -1, "CVSPILS", "cvSpilsPrecSolveBWrapper", MSGS_BAD_TINTERP); + return(-1); + } + + /* Call user's adjoint psolveB routine */ + retval = psolve_B(t, ytmp, yB, fyB, rB, zB, gammaB, deltaB, + lrB, cvB_mem->cv_user_data, tmpB); + + return(retval); +} + + +/* + * cvSpilsJacTimesVecBWrapper + * + * This routine interfaces to the CVSpilsJacTimesVecFnB routine + * provided by the user. + */ + +static int cvSpilsJacTimesVecBWrapper(N_Vector vB, N_Vector JvB, realtype t, + N_Vector yB, N_Vector fyB, + void *cvode_mem, N_Vector tmpB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + CVSpilsMemB cvspilsB_mem; + int retval, flag; + + cv_mem = (CVodeMem) cvode_mem; + + ca_mem = cv_mem->cv_adj_mem; + + cvB_mem = ca_mem->ca_bckpbCrt; + + cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem); + + /* Forward solution from interpolation */ + flag = IMget(cv_mem, t, ytmp, NULL); + if (flag != CV_SUCCESS) { + cvProcessError(cv_mem, -1, "CVSPILS", "cvSpilsJacTimesVecBWrapper", MSGS_BAD_TINTERP); + return(-1); + } + + /* Call user's adjoint jtimesB routine */ + retval = jtimes_B(vB, JvB, t, ytmp, yB, fyB, cvB_mem->cv_user_data, tmpB); + + return(retval); +} + diff --git a/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_spils_impl.h b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_spils_impl.h new file mode 100644 index 0000000..a847ecb --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_spils_impl.h @@ -0,0 +1,183 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.8 $ + * $Date: 2008/09/03 20:26:21 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Common implementation header file for the scaled, preconditioned + * iterative linear solvers + * ----------------------------------------------------------------- + */ + +#ifndef _CVSSPILS_IMPL_H +#define _CVSSPILS_IMPL_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include "cvodes_impl.h" + +/* + * ================================================================= + * C V S P I L S I N T E R N A L C O N S T A N T S + * ================================================================= + */ + +/* Types of iterative linear solvers */ + +#define SPILS_SPGMR 1 +#define SPILS_SPBCG 2 +#define SPILS_SPTFQMR 3 + +/* + * ================================================================= + * PART I: F O R W A R D P R O B L E M S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Types : CVSpilsMemRec, CVSpilsMem + * ----------------------------------------------------------------- + * The type CVSpilsMem is pointer to a CVSpilsMemRec. + * ----------------------------------------------------------------- + */ + +typedef struct CVSpilsMemRec { + + int s_type; /* type of scaled preconditioned iterative LS */ + + int s_pretype; /* type of preconditioning */ + int s_gstype; /* type of Gram-Schmidt orthogonalization */ + realtype s_sqrtN; /* sqrt(N) */ + realtype s_eplifac; /* eplifac = user specified or EPLIN_DEFAULT */ + realtype s_deltar; /* deltar = delt * tq4 */ + realtype s_delta; /* delta = deltar * sqrtN */ + int s_maxl; /* maxl = maximum dimension of the Krylov space */ + + long int s_nstlpre; /* value of nst at the last pset call */ + long int s_npe; /* npe = total number of pset calls */ + long int s_nli; /* nli = total number of linear iterations */ + long int s_nps; /* nps = total number of psolve calls */ + long int s_ncfl; /* ncfl = total number of convergence failures */ + long int s_njtimes; /* njtimes = total number of calls to jtimes */ + long int s_nfes; /* nfeSG = total number of calls to f for + difference quotient Jacobian-vector products */ + + N_Vector s_ytemp; /* temp vector passed to jtimes and psolve */ + N_Vector s_x; /* temp vector used by CVSpilsSolve */ + N_Vector s_ycur; /* CVODE current y vector in Newton Iteration */ + N_Vector s_fcur; /* fcur = f(tn, ycur) */ + + void* s_spils_mem; /* memory used by the generic solver */ + + /* Preconditioner computation + * (a) user-provided: + * - P_data == user_data + * - pfree == NULL (the user dealocates memory for user_data) + * (b) internal preconditioner module + * - P_data == cvode_mem + * - pfree == set by the prec. module and called in CVodeFree + */ + CVSpilsPrecSetupFn s_pset; + CVSpilsPrecSolveFn s_psolve; + void (*s_pfree)(CVodeMem cv_mem); + void *s_P_data; + + /* Jacobian times vector compuation + * (a) jtimes function provided by the user: + * - j_data == user_data + * - jtimesDQ == FALSE + * (b) internal jtimes + * - j_data == cvode_mem + * - jtimesDQ == TRUE + */ + booleantype s_jtimesDQ; + CVSpilsJacTimesVecFn s_jtimes; + void *s_j_data; + + int s_last_flag; /* last error flag returned by any function */ + +} *CVSpilsMem; + +/* + * ----------------------------------------------------------------- + * Prototypes of internal functions + * ----------------------------------------------------------------- + */ + +/* Atimes and PSolve routines called by generic solver */ + +int CVSpilsAtimes(void *cv_mem, N_Vector v, N_Vector z); + +int CVSpilsPSolve(void *cv_mem, N_Vector r, N_Vector z, int lr); + +/* Difference quotient approximation for Jac times vector */ + +int CVSpilsDQJtimes(N_Vector v, N_Vector Jv, realtype t, + N_Vector y, N_Vector fy, void *data, + N_Vector work); +/* + * ================================================================= + * PART II: B A C K W A R D P R O B L E M S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Types : CVSpilsMemRecB, CVSpilsMemB + * ----------------------------------------------------------------- + * CVSpgmrB, CVSpbcgB, and CVSptfqmr attach such a structure to the + * lmemB filed of CVodeBMem + * ----------------------------------------------------------------- + */ + +typedef struct CVSpilsMemRecB { + + CVSpilsJacTimesVecFnB s_jtimesB; + CVSpilsPrecSetupFnB s_psetB; + CVSpilsPrecSolveFnB s_psolveB; + void *s_P_dataB; + +} *CVSpilsMemB; + + +/* + * ================================================================= + * E R R O R M E S S A G E S + * ================================================================= + */ + +#define MSGS_CVMEM_NULL "Integrator memory is NULL." +#define MSGS_MEM_FAIL "A memory request failed." +#define MSGS_BAD_NVECTOR "A required vector operation is not implemented." +#define MSGS_BAD_LSTYPE "Incompatible linear solver type." +#define MSGS_BAD_PRETYPE "Illegal value for pretype. Legal values are PREC_NONE, PREC_LEFT, PREC_RIGHT, and PREC_BOTH." +#define MSGS_PSOLVE_REQ "pretype != PREC_NONE, but PSOLVE = NULL is illegal." +#define MSGS_LMEM_NULL "Linear solver memory is NULL." +#define MSGS_BAD_GSTYPE "Illegal value for gstype. Legal values are MODIFIED_GS and CLASSICAL_GS." +#define MSGS_BAD_EPLIN "eplifac < 0 illegal." + +#define MSGS_PSET_FAILED "The preconditioner setup routine failed in an unrecoverable manner." +#define MSGS_PSOLVE_FAILED "The preconditioner solve routine failed in an unrecoverable manner." +#define MSGS_JTIMES_FAILED "The Jacobian x vector routine failed in an unrecoverable manner." + +#define MSGS_NO_ADJ "Illegal attempt to call before calling CVodeAdjMalloc." +#define MSGS_BAD_WHICH "Illegal value for which." +#define MSGS_LMEMB_NULL "Linear solver memory is NULL for the backward integration." +#define MSGS_BAD_TINTERP "Bad t for interpolation." + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_sptfqmr.c b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_sptfqmr.c new file mode 100644 index 0000000..32a2881 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/cvodes/cvodes_sptfqmr.c @@ -0,0 +1,568 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.11 $ + * $Date: 2008/09/03 20:26:21 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the CVSPTFQMR linear solver. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include "cvodes_spils_impl.h" +#include "cvodes_impl.h" + +#include +#include + +/* Constants */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +/* CVSPTFQMR linit, lsetup, lsolve, and lfree routines */ + +static int CVSptfqmrInit(CVodeMem cv_mem); + +static int CVSptfqmrSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, + N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1, + N_Vector vtemp2, N_Vector vtemp3); + +static int CVSptfqmrSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector ynow, N_Vector fnow); + +static void CVSptfqmrFree(CVodeMem cv_mem); + +/* CVSPTFQMR lfreeB function */ + +static void CVSptfqmrFreeB(CVodeBMem cvB_mem); + +/* + * ================================================================ + * + * PART I - forward problems + * + * ================================================================ + */ + +/* Readability Replacements */ + +#define tq (cv_mem->cv_tq) +#define nst (cv_mem->cv_nst) +#define tn (cv_mem->cv_tn) +#define gamma (cv_mem->cv_gamma) +#define gammap (cv_mem->cv_gammap) +#define f (cv_mem->cv_f) +#define user_data (cv_mem->cv_user_data) +#define ewt (cv_mem->cv_ewt) +#define errfp (cv_mem->cv_errfp) +#define mnewt (cv_mem->cv_mnewt) +#define linit (cv_mem->cv_linit) +#define lsetup (cv_mem->cv_lsetup) +#define lsolve (cv_mem->cv_lsolve) +#define lfree (cv_mem->cv_lfree) +#define lmem (cv_mem->cv_lmem) +#define vec_tmpl (cv_mem->cv_tempv) +#define setupNonNull (cv_mem->cv_setupNonNull) + +#define sqrtN (cvspils_mem->s_sqrtN) +#define ytemp (cvspils_mem->s_ytemp) +#define x (cvspils_mem->s_x) +#define ycur (cvspils_mem->s_ycur) +#define fcur (cvspils_mem->s_fcur) +#define delta (cvspils_mem->s_delta) +#define deltar (cvspils_mem->s_deltar) +#define npe (cvspils_mem->s_npe) +#define nli (cvspils_mem->s_nli) +#define nps (cvspils_mem->s_nps) +#define ncfl (cvspils_mem->s_ncfl) +#define nstlpre (cvspils_mem->s_nstlpre) +#define njtimes (cvspils_mem->s_njtimes) +#define nfes (cvspils_mem->s_nfes) +#define spils_mem (cvspils_mem->s_spils_mem) + +#define jtimesDQ (cvspils_mem->s_jtimesDQ) +#define jtimes (cvspils_mem->s_jtimes) +#define j_data (cvspils_mem->s_j_data) + +#define last_flag (cvspils_mem->s_last_flag) + +/* + * ----------------------------------------------------------------- + * Function : CVSptfqmr + * ----------------------------------------------------------------- + * This routine initializes the memory record and sets various function + * fields specific to the Sptfqmr linear solver module. CVSptfqmr first + * calls the existing lfree routine if this is not NULL. It then sets + * the cv_linit, cv_lsetup, cv_lsolve, cv_lfree fields in (*cvode_mem) + * to be CVSptfqmrInit, CVSptfqmrSetup, CVSptfqmrSolve, and CVSptfqmrFree, + * respectively. It allocates memory for a structure of type + * CVSpilsMemRec and sets the cv_lmem field in (*cvode_mem) to the + * address of this structure. It sets setupNonNull in (*cvode_mem), + * and sets various fields in the CVSpilsMemRec structure. + * Finally, CVSptfqmr allocates memory for ytemp and x, and calls + * SptfqmrMalloc to allocate memory for the Sptfqmr solver. + * ----------------------------------------------------------------- + */ + +int CVSptfqmr(void *cvode_mem, int pretype, int maxl) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + SptfqmrMem sptfqmr_mem; + int mxl; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPTFQMR", "CVSptfqmr", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Check if N_VDotProd is present */ + if (vec_tmpl->ops->nvdotprod == NULL) { + cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPTFQMR", "CVSptfqmr", MSGS_BAD_NVECTOR); + return(CVSPILS_ILL_INPUT); + } + + if (lfree != NULL) lfree(cv_mem); + + /* Set four main function fields in cv_mem */ + linit = CVSptfqmrInit; + lsetup = CVSptfqmrSetup; + lsolve = CVSptfqmrSolve; + lfree = CVSptfqmrFree; + + /* Get memory for CVSpilsMemRec */ + cvspils_mem = NULL; + cvspils_mem = (CVSpilsMem) malloc(sizeof(struct CVSpilsMemRec)); + if (cvspils_mem == NULL) { + cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPTFQMR", "CVSptfqmr", MSGS_MEM_FAIL); + return(CVSPILS_MEM_FAIL); + } + + /* Set ILS type */ + cvspils_mem->s_type = SPILS_SPTFQMR; + + /* Set Sptfqmr parameters that have been passed in call sequence */ + cvspils_mem->s_pretype = pretype; + mxl = cvspils_mem->s_maxl = (maxl <= 0) ? CVSPILS_MAXL : maxl; + + /* Set defaults for Jacobian-related fileds */ + jtimesDQ = TRUE; + jtimes = NULL; + j_data = NULL; + + /* Set defaults for preconditioner-related fields */ + cvspils_mem->s_pset = NULL; + cvspils_mem->s_psolve = NULL; + cvspils_mem->s_pfree = NULL; + cvspils_mem->s_P_data = cv_mem->cv_user_data; + + /* Set default values for the rest of the Sptfqmr parameters */ + cvspils_mem->s_eplifac = CVSPILS_EPLIN; + + cvspils_mem->s_last_flag = CVSPILS_SUCCESS; + + setupNonNull = FALSE; + + /* Check for legal pretype */ + if ((pretype != PREC_NONE) && (pretype != PREC_LEFT) && + (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) { + cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPTFQMR", "CVSptfqmr", MSGS_BAD_PRETYPE); + return(CVSPILS_ILL_INPUT); + } + + /* Allocate memory for ytemp and x */ + ytemp = N_VClone(vec_tmpl); + if (ytemp == NULL) { + cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPTFQMR", "CVSptfqmr", MSGS_MEM_FAIL); + free(cvspils_mem); cvspils_mem = NULL; + return(CVSPILS_MEM_FAIL); + } + x = N_VClone(vec_tmpl); + if (x == NULL) { + cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPTFQMR", "CVSptfqmr", MSGS_MEM_FAIL); + N_VDestroy(ytemp); + free(cvspils_mem); cvspils_mem = NULL; + return(CVSPILS_MEM_FAIL); + } + + /* Compute sqrtN from a dot product */ + N_VConst(ONE, ytemp); + sqrtN = RSqrt(N_VDotProd(ytemp, ytemp)); + + /* Call SptfqmrMalloc to allocate workspace for Sptfqmr */ + sptfqmr_mem = NULL; + sptfqmr_mem = SptfqmrMalloc(mxl, vec_tmpl); + if (sptfqmr_mem == NULL) { + cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPTFQMR", "CVSptfqmr", MSGS_MEM_FAIL); + N_VDestroy(ytemp); + N_VDestroy(x); + free(cvspils_mem); cvspils_mem = NULL; + return(CVSPILS_MEM_FAIL); + } + + /* Attach SPTFQMR memory to spils memory structure */ + spils_mem = (void *) sptfqmr_mem; + + /* Attach linear solver memory to integrator memory */ + lmem = cvspils_mem; + + return(CVSPILS_SUCCESS); +} + +/* Additional readability replacements */ + +#define pretype (cvspils_mem->s_pretype) +#define eplifac (cvspils_mem->s_eplifac) +#define maxl (cvspils_mem->s_maxl) +#define psolve (cvspils_mem->s_psolve) +#define pset (cvspils_mem->s_pset) +#define P_data (cvspils_mem->s_P_data) + +/* + * ----------------------------------------------------------------- + * Function : CVSptfqmrInit + * ----------------------------------------------------------------- + * This routine does remaining initializations specific to the Sptfqmr + * linear solver. + * ----------------------------------------------------------------- + */ + +static int CVSptfqmrInit(CVodeMem cv_mem) +{ + CVSpilsMem cvspils_mem; + SptfqmrMem sptfqmr_mem; + + cvspils_mem = (CVSpilsMem) lmem; + sptfqmr_mem = (SptfqmrMem) spils_mem; + + /* Initialize counters */ + npe = nli = nps = ncfl = nstlpre = 0; + njtimes = nfes = 0; + + /* Check for legal combination pretype - psolve */ + if ((pretype != PREC_NONE) && (psolve == NULL)) { + cvProcessError(cv_mem, -1, "CVSPTFQMR", "CVSptfqmrInit", MSGS_PSOLVE_REQ); + last_flag = CVSPILS_ILL_INPUT; + return(-1); + } + + /* Set setupNonNull = TRUE iff there is preconditioning + (pretype != PREC_NONE) and there is a preconditioning + setup phase (pset != NULL) */ + setupNonNull = (pretype != PREC_NONE) && (pset != NULL); + + /* Set Jacobian-related fields, based on jtimesDQ */ + if (jtimesDQ) { + jtimes = CVSpilsDQJtimes; + j_data = cv_mem; + } else { + j_data = user_data; + } + + /* Set maxl in the SPTFQMR memory in case it was changed by the user */ + sptfqmr_mem->l_max = maxl; + + last_flag = CVSPILS_SUCCESS; + return(0); +} + +/* + * ----------------------------------------------------------------- + * Function : CVSptfqmrSetup + * ----------------------------------------------------------------- + * This routine does the setup operations for the Sptfqmr linear solver. + * It makes a decision as to whether or not to signal for reevaluation + * of Jacobian data in the pset routine, based on various state + * variables, then it calls pset. If we signal for reevaluation, + * then we reset jcur = *jcurPtr to TRUE, regardless of the pset output. + * In any case, if jcur == TRUE, we increment npe and save nst in nstlpre. + * ----------------------------------------------------------------- + */ + +static int CVSptfqmrSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, + N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1, + N_Vector vtemp2, N_Vector vtemp3) +{ + booleantype jbad, jok; + realtype dgamma; + int retval; + CVSpilsMem cvspils_mem; + + cvspils_mem = (CVSpilsMem) lmem; + + /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */ + dgamma = ABS((gamma/gammap) - ONE); + jbad = (nst == 0) || (nst > nstlpre + CVSPILS_MSBPRE) || + ((convfail == CV_FAIL_BAD_J) && (dgamma < CVSPILS_DGMAX)) || + (convfail == CV_FAIL_OTHER); + *jcurPtr = jbad; + jok = !jbad; + + /* Call pset routine and possibly reset jcur */ + retval = pset(tn, ypred, fpred, jok, jcurPtr, gamma, P_data, + vtemp1, vtemp2, vtemp3); + if (retval < 0) { + cvProcessError(cv_mem, SPTFQMR_PSET_FAIL_UNREC, "CVSPTFQMR", "CVSptfqmrSetup", MSGS_PSET_FAILED); + last_flag = SPTFQMR_PSET_FAIL_UNREC; + } + if (retval > 0) { + last_flag = SPTFQMR_PSET_FAIL_REC; + } + + if (jbad) *jcurPtr = TRUE; + + /* If jcur = TRUE, increment npe and save nst value */ + if (*jcurPtr) { + npe++; + nstlpre = nst; + } + + last_flag = SPTFQMR_SUCCESS; + + /* Return the same value that pset returned */ + return(retval); +} + +/* + * ----------------------------------------------------------------- + * Function : CVSptfqmrSolve + * ----------------------------------------------------------------- + * This routine handles the call to the generic solver SptfqmrSolve + * for the solution of the linear system Ax = b with the SPTFQMR method. + * The solution x is returned in the vector b. + * + * If the WRMS norm of b is small, we return x = b (if this is the first + * Newton iteration) or x = 0 (if a later Newton iteration). + * + * Otherwise, we set the tolerance parameter and initial guess (x = 0), + * call SptfqmrSolve, and copy the solution x into b. The x-scaling and + * b-scaling arrays are both equal to weight. + * + * The counters nli, nps, and ncfl are incremented, and the return value + * is set according to the success of SptfqmrSolve. The success flag is + * returned if SptfqmrSolve converged, or if this is the first Newton + * iteration and the residual norm was reduced below its initial value. + * ----------------------------------------------------------------- + */ + +static int CVSptfqmrSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector ynow, N_Vector fnow) +{ + realtype bnorm, res_norm; + CVSpilsMem cvspils_mem; + SptfqmrMem sptfqmr_mem; + int nli_inc, nps_inc, retval; + + cvspils_mem = (CVSpilsMem) lmem; + + sptfqmr_mem = (SptfqmrMem) spils_mem; + + /* Test norm(b); if small, return x = 0 or x = b */ + deltar = eplifac * tq[4]; + + bnorm = N_VWrmsNorm(b, weight); + if (bnorm <= deltar) { + if (mnewt > 0) N_VConst(ZERO, b); + return(0); + } + + /* Set vectors ycur and fcur for use by the Atimes and Psolve routines */ + ycur = ynow; + fcur = fnow; + + /* Set inputs delta and initial guess x = 0 to SptfqmrSolve */ + delta = deltar * sqrtN; + N_VConst(ZERO, x); + + /* Call SptfqmrSolve and copy x to b */ + retval = SptfqmrSolve(sptfqmr_mem, cv_mem, x, b, pretype, delta, + cv_mem, weight, weight, CVSpilsAtimes, CVSpilsPSolve, + &res_norm, &nli_inc, &nps_inc); + + N_VScale(ONE, x, b); + + /* Increment counters nli, nps, and ncfl */ + nli += nli_inc; + nps += nps_inc; + if (retval != SPTFQMR_SUCCESS) ncfl++; + + /* Interpret return value from SpgmrSolve */ + + last_flag = retval; + + switch(retval) { + + case SPTFQMR_SUCCESS: + return(0); + break; + case SPTFQMR_RES_REDUCED: + if (mnewt == 0) return(0); + else return(1); + break; + case SPTFQMR_CONV_FAIL: + return(1); + break; + case SPTFQMR_PSOLVE_FAIL_REC: + return(1); + break; + case SPTFQMR_ATIMES_FAIL_REC: + return(1); + break; + case SPTFQMR_MEM_NULL: + return(-1); + break; + case SPTFQMR_ATIMES_FAIL_UNREC: + cvProcessError(cv_mem, SPTFQMR_ATIMES_FAIL_UNREC, "CVSPTFQMR", "CVSptfqmrSolve", MSGS_JTIMES_FAILED); + return(-1); + break; + case SPTFQMR_PSOLVE_FAIL_UNREC: + cvProcessError(cv_mem, SPTFQMR_PSOLVE_FAIL_UNREC, "CVSPTFQMR", "CVSptfqmrSolve", MSGS_PSOLVE_FAILED); + return(-1); + break; + } + + return(0); + +} + +/* + * ----------------------------------------------------------------- + * Function : CVSptfqmrFree + * ----------------------------------------------------------------- + * This routine frees memory specific to the Sptfqmr linear solver. + * ----------------------------------------------------------------- + */ + +static void CVSptfqmrFree(CVodeMem cv_mem) +{ + CVSpilsMem cvspils_mem; + SptfqmrMem sptfqmr_mem; + + cvspils_mem = (CVSpilsMem) lmem; + + N_VDestroy(ytemp); + N_VDestroy(x); + + sptfqmr_mem = (SptfqmrMem) spils_mem; + SptfqmrFree(sptfqmr_mem); + + if (cvspils_mem->s_pfree != NULL) (cvspils_mem->s_pfree)(cv_mem); + + free(cvspils_mem); cvspils_mem = NULL; + + return; +} + +/* + * ================================================================ + * + * PART II - backward problems + * + * ================================================================ + */ + +/* Additional readability replacements */ + +#define pset_B (cvspilsB_mem->s_psetB) +#define psolve_B (cvspilsB_mem->s_psolveB) +#define jtimes_B (cvspilsB_mem->s_jtimesB) +#define P_data_B (cvspilsB_mem->s_P_dataB) + +/* + * CVSptfqmrB + * + * Wrapper for the backward phase + */ + +int CVSptfqmrB(void *cvode_mem, int which, int pretypeB, int maxlB) +{ + CVodeMem cv_mem; + CVadjMem ca_mem; + CVodeBMem cvB_mem; + void *cvodeB_mem; + CVSpilsMemB cvspilsB_mem; + int flag; + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPTFQMR", "CVSptfqmrB", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Was ASA initialized? */ + if (cv_mem->cv_adjMallocDone == FALSE) { + cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSPTFQMR", "CVSptfqmrB", MSGS_NO_ADJ); + return(CVSPILS_NO_ADJ); + } + ca_mem = cv_mem->cv_adj_mem; + + /* Check which */ + if ( which >= ca_mem->ca_nbckpbs ) { + cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPTFQMR", "CVSptfqmrB", MSGS_BAD_WHICH); + return(CVSPILS_ILL_INPUT); + } + + /* Find the CVodeBMem entry in the linked list corresponding to which */ + cvB_mem = ca_mem->cvB_mem; + while (cvB_mem != NULL) { + if ( which == cvB_mem->cv_index ) break; + cvB_mem = cvB_mem->cv_next; + } + + cvodeB_mem = (void *) (cvB_mem->cv_mem); + + /* Get memory for CVSpilsMemRecB */ + cvspilsB_mem = NULL; + cvspilsB_mem = (CVSpilsMemB) malloc(sizeof(struct CVSpilsMemRecB)); + if (cvspilsB_mem == NULL) { + cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPTFQMR", "CVSptfqmrB", MSGS_MEM_FAIL); + return(CVSPILS_MEM_FAIL); + } + + pset_B = NULL; + psolve_B = NULL; + P_data_B = NULL; + + /* initialize Jacobian function */ + jtimes_B = NULL; + + /* attach lmemB and lfreeB */ + cvB_mem->cv_lmem = cvspilsB_mem; + cvB_mem->cv_lfree = CVSptfqmrFreeB; + + flag = CVSptfqmr(cvodeB_mem, pretypeB, maxlB); + + if (flag != CVSPILS_SUCCESS) { + free(cvspilsB_mem); + cvspilsB_mem = NULL; + } + + return(flag); +} + +/* + * CVSptfqmrFreeB + */ + + +static void CVSptfqmrFreeB(CVodeBMem cvB_mem) +{ + CVSpilsMemB cvspilsB_mem; + + cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem); + + free(cvspilsB_mem); +} diff --git a/odemex/Parser/CVode/cv_src/src/nvec_par/CMakeLists.txt b/odemex/Parser/CVode/cv_src/src/nvec_par/CMakeLists.txt new file mode 100644 index 0000000..f5e359f --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/nvec_par/CMakeLists.txt @@ -0,0 +1,89 @@ +# --------------------------------------------------------------- +# $Revision: 1.3 $ +# $Date: 2009/02/17 02:58:48 $ +# --------------------------------------------------------------- +# Programmer: Radu Serban @ LLNL +# --------------------------------------------------------------- +# Copyright (c) 2007, The Regents of the University of California. +# Produced at the Lawrence Livermore National Laboratory. +# All rights reserved. +# For details, see the LICENSE file. +# --------------------------------------------------------------- +# CMakeLists.txt file for the parallel NVECTOR library + +INSTALL(CODE "MESSAGE(\"\nInstall NVECTOR_PARALLEL\n\")") + +IF(MPI_MPICC) + # use MPI_MPICC as the compiler + SET(CMAKE_C_COMPILER ${MPI_MPICC}) +ELSE(MPI_MPICC) + # add MPI_INCLUDE_PATH to include directories + INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH}) +ENDIF(MPI_MPICC) + +# Add variable nvecparallel_SOURCES with the sources for the NVECPARALLEL lib +SET(nvecparallel_SOURCES nvector_parallel.c) + +# Add variable shared_SOURCES with the common SUNDIALS sources which will +# also be included in the NVECPARALLEL library +SET(shared_SOURCES sundials_math.c) +ADD_PREFIX(${sundials_SOURCE_DIR}/src/sundials/ shared_SOURCES) + +# Add variable nvecparallel_HEADERS with the exported NVECPARALLEL header files +SET(nvecparallel_HEADERS nvector_parallel.h) +ADD_PREFIX(${sundials_SOURCE_DIR}/include/nvector/ nvecparallel_HEADERS) + +# Add source directory to include directories +INCLUDE_DIRECTORIES(.) + +# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY +ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY) + +# Rules for building and installing the static library: +# - Add the build target for the NVECPARALLEL library +# - Set the library name and make sure it is not deleted +# - Install the NVECSERIAL library +IF(BUILD_STATIC_LIBS) + ADD_LIBRARY(sundials_nvecparallel_static STATIC ${nvecparallel_SOURCES} ${shared_SOURCES}) + SET_TARGET_PROPERTIES(sundials_nvecparallel_static + PROPERTIES OUTPUT_NAME sundials_nvecparallel CLEAN_DIRECT_OUTPUT 1) + INSTALL(TARGETS sundials_nvecparallel_static DESTINATION lib) +ENDIF(BUILD_STATIC_LIBS) + +# Rules for building and installing the shared library: +# - Add the build target for the NVECPARALLEL library +# - Set the library name and make sure it is not deleted +# - Set VERSION and SOVERSION for shared libraries +# - Install the NVECSERIAL library +IF(BUILD_SHARED_LIBS) + ADD_LIBRARY(sundials_nvecparallel_shared SHARED ${nvecparallel_SOURCES} ${shared_SOURCES}) + SET_TARGET_PROPERTIES(sundials_nvecparallel_shared + PROPERTIES OUTPUT_NAME sundials_nvecparallel CLEAN_DIRECT_OUTPUT 1) + SET_TARGET_PROPERTIES(sundials_nvecparallel_shared + PROPERTIES VERSION ${nveclib_VERSION} SOVERSION ${nveclib_SOVERSION}) + INSTALL(TARGETS sundials_nvecparallel_shared DESTINATION lib) +ENDIF(BUILD_SHARED_LIBS) + +# Install the NVECPARALLEL header files +INSTALL(FILES ${nvecparallel_HEADERS} DESTINATION include/nvector) + +# If FCMIX is enabled and MPI-F77 works, build and install the FNVECPARALLEL library +IF(FCMIX_ENABLE AND MPIF_FOUND) + SET(fnvecparallel_SOURCES fnvector_parallel.c) + IF(BUILD_STATIC_LIBS) + ADD_LIBRARY(sundials_fnvecparallel_static STATIC ${fnvecparallel_SOURCES}) + SET_TARGET_PROPERTIES(sundials_fnvecparallel_static + PROPERTIES OUTPUT_NAME sundials_fnvecparallel CLEAN_DIRECT_OUTPUT 1) + INSTALL(TARGETS sundials_fnvecparallel_static DESTINATION lib) + ENDIF(BUILD_STATIC_LIBS) + IF(BUILD_SHARED_LIBS) + ADD_LIBRARY(sundials_fnvecparallel_shared SHARED ${fnvecparallel_SOURCES}) + SET_TARGET_PROPERTIES(sundials_fnvecparallel_shared + PROPERTIES OUTPUT_NAME sundials_fnvecparallel CLEAN_DIRECT_OUTPUT 1) + SET_TARGET_PROPERTIES(sundials_fnvecparallel_shared + PROPERTIES VERSION ${nveclib_VERSION} SOVERSION ${nveclib_SOVERSION}) + INSTALL(TARGETS sundials_fnvecparallel_shared DESTINATION lib) + ENDIF(BUILD_SHARED_LIBS) +ENDIF(FCMIX_ENABLE AND MPIF_FOUND) +# +MESSAGE(STATUS "Added NVECTOR_PARALLEL module") diff --git a/odemex/Parser/CVode/cv_src/src/nvec_par/Makefile.in b/odemex/Parser/CVode/cv_src/src/nvec_par/Makefile.in new file mode 100644 index 0000000..bd7ea4f --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/nvec_par/Makefile.in @@ -0,0 +1,128 @@ +# ----------------------------------------------------------------- +# $Revision: 1.8 $ +# $Date: 2007/01/29 17:36:28 $ +# ----------------------------------------------------------------- +# Programmer(s): Radu Serban and Aaron Collier @ LLNL +# ----------------------------------------------------------------- +# Copyright (c) 2002, The Regents of the University of California. +# Produced at the Lawrence Livermore National Laboratory. +# All rights reserved. +# For details, see the LICENSE file. +# ----------------------------------------------------------------- +# Makefile for parallel NVECTOR module +# +# @configure_input@ +# ----------------------------------------------------------------- + +SHELL = @SHELL@ + +@SET_MAKE@ + +srcdir = @srcdir@ +builddir = @builddir@ +abs_builddir = @abs_builddir@ +top_builddir = @top_builddir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +includedir = @includedir@ +libdir = @libdir@ + +INSTALL = @INSTALL@ +INSTALL_LIB = @INSTALL_PROGRAM@ +INSTALL_HEADER = @INSTALL_DATA@ + +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ + +MPICC = @MPICC@ +MPI_INC_DIR = @MPI_INC_DIR@ +MPI_LIB_DIR = @MPI_LIB_DIR@ +MPI_LIBS = @MPI_LIBS@ +MPI_FLAGS = @MPI_FLAGS@ +CPPFLAGS = @CPPFLAGS@ +CFLAGS = @CFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ + +FCMIX_ENABLED = @FCMIX_ENABLED@ + +top_srcdir = $(srcdir)/../.. + +INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(MPI_INC_DIR) + +LIB_REVISION = 0:2:0 + +NVECPAR_LIB = libsundials_nvecparallel.la +NVECPAR_LIB_FILES = nvector_parallel.lo + +FNVECPAR_LIB = libsundials_fnvecparallel.la +FNVECPAR_LIB_FILES = fnvector_parallel.lo + +SHARED_LIB_FILES = $(top_builddir)/src/sundials/sundials_math.lo + +mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs +rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs + +all: $(NVECPAR_LIB) $(FNVECPAR_LIB) + +$(NVECPAR_LIB): shared $(NVECPAR_LIB_FILES) + $(LIBTOOL) --mode=link $(MPICC) $(CFLAGS) $(MPI_FLAGS) -o $(NVECPAR_LIB) $(NVECPAR_LIB_FILES) $(SHARED_LIB_FILES) $(LDFLAGS) -L$(MPI_LIB_DIR) $(MPI_LIBS) $(LIBS) -rpath $(libdir) -version-info $(LIB_REVISION) + +$(FNVECPAR_LIB): $(FNVECPAR_LIB_FILES) + @if test "X${FCMIX_ENABLED}" = "Xyes"; then \ + echo "${LIBTOOL} --mode=link ${MPICC} ${CFLAGS} ${MPI_FLAGS} -o ${FNVECPAR_LIB} ${FNVECPAR_LIB_FILES} ${SHARED_LIB_FILES} ${LDFLAGS} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LIBS} -rpath ${libdir} -version-info ${LIB_REVISION}" ; \ + ${LIBTOOL} --mode=link ${MPICC} ${CFLAGS} ${MPI_FLAGS} -o ${FNVECPAR_LIB} ${FNVECPAR_LIB_FILES} ${SHARED_LIB_FILES} ${LDFLAGS} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LIBS} -rpath ${libdir} -version-info ${LIB_REVISION} ; \ + fi + +install: $(NVECPAR_LIB) $(FNVECPAR_LIB) + $(mkinstalldirs) $(includedir)/nvector + $(mkinstalldirs) $(libdir) + $(LIBTOOL) --mode=install $(INSTALL_LIB) $(NVECPAR_LIB) $(libdir) + $(INSTALL_HEADER) $(top_srcdir)/include/nvector/nvector_parallel.h $(includedir)/nvector/ + @if test "X${FCMIX_ENABLED}" = "Xyes"; then \ + echo "${LIBTOOL} --mode=install ${INSTALL_LIB} ${FNVECPAR_LIB} ${libdir}" ; \ + ${LIBTOOL} --mode=install ${INSTALL_LIB} ${FNVECPAR_LIB} ${libdir} ; \ + fi + +uninstall: + $(LIBTOOL) --mode=uninstall rm -f $(libdir)/$(NVECPAR_LIB) + @if test "X${FCMIX_ENABLED}" = "Xyes"; then \ + echo "${LIBTOOL} --mode=uninstall rm -f ${libdir}/${FNVECPAR_LIB}" ; \ + ${LIBTOOL} --mode=uninstall rm -f ${libdir}/${FNVECPAR_LIB} ; \ + fi + rm -f $(includedir)/nvector/nvector_parallel.h + $(rminstalldirs) ${includedir}/nvector + +shared: + @cd ${top_builddir}/src/sundials ; \ + ${MAKE} ; \ + cd ${abs_builddir} + +clean: + $(LIBTOOL) --mode=clean rm -f $(NVECPAR_LIB) + rm -f $(NVECPAR_LIB_FILES) + rm -f nvector_parallel.o + @if test "X${FCMIX_ENABLED}" = "Xyes"; then \ + echo "${LIBTOOL} --mode=clean rm -f ${FNVECPAR_LIB}" ; \ + ${LIBTOOL} --mode=clean rm -f ${FNVECPAR_LIB} ; \ + echo "rm -f ${FNVECPAR_LIB_FILES}" ; \ + rm -f ${FNVECPAR_LIB_FILES} ; \ + echo "rm -f fnvector_parallel.o" ; \ + rm -f fnvector_parallel.o ; \ + fi + +distclean: clean + rm -f Makefile + +nvector_parallel.lo: $(srcdir)/nvector_parallel.c + $(LIBTOOL) --mode=compile $(MPICC) $(CPPFLAGS) $(MPI_FLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/nvector_parallel.c +fnvector_parallel.lo: $(srcdir)/fnvector_parallel.c + @if test "X${FCMIX_ENABLED}" = "Xyes"; then \ + echo "${LIBTOOL} --mode=compile ${MPICC} ${CPPFLAGS} ${MPI_FLAGS} $(INCLUDES) ${CFLAGS} -c ${srcdir}/fnvector_parallel.c" ; \ + ${LIBTOOL} --mode=compile ${MPICC} ${CPPFLAGS} ${MPI_FLAGS} $(INCLUDES) ${CFLAGS} -c ${srcdir}/fnvector_parallel.c ; \ + fi + +libtool: $(top_builddir)/$(LIBTOOL_DEPS) + @cd ${top_builddir} ; \ + ${SHELL} ./config.status --recheck ; \ + cd ${abs_builddir} diff --git a/odemex/Parser/CVode/cv_src/src/nvec_par/README b/odemex/Parser/CVode/cv_src/src/nvec_par/README new file mode 100644 index 0000000..726603e --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/nvec_par/README @@ -0,0 +1,135 @@ + NVECTOR_PARALLEL + Release 2.4.0, January 2008 + +MPI parallel implementation of the NVECTOR module for SUNDIALS. + +NVECTOR_PARALLEL defines the content field of N_Vector to be a structure +containing the global and local lengths of the vector, a pointer to the +beginning of a contiguous local data array, an MPI communicator, and a +boolean flag indicating ownership of the data array. + +NVECTOR_PARALLEL defines seven macros to provide access to the content of +a parallel N_Vector, several constructors for variables of type N_Vector, +a constructor for an array of variables of type N_Vector, and destructors +for N_Vector and N_Vector array. + +NVECTOR_PARALLEL provides implementations for all vector operations defined +by the generic NVECTOR module in the table of operations. + + +A. Documentation +---------------- + +The MPI parallel NVECTOR implementation is fully described in the user documentation +for any of the SUNDIALS solvers [1-5]. A PDF file for the user guide for a particular +solver is available in the solver's subdirectory under doc/. + + +B. Installation +--------------- + +For basic installation instructions see /sundials/INSTALL_NOTES. +For complete installation instructions see any of the user guides. + + +C. References +------------- + +[1] A. C. Hindmarsh and R. Serban, "User Documentation for CVODE v2.4.0," + LLLNL technical report UCRL-MA-208108, November 2004. + +[2] A. C. Hindmarsh and R. Serban, "User Documentation for CVODES v2.4.0," + LLNL technical report UCRL-MA-208111, November 2004. + +[3] A. C. Hindmarsh and R. Serban, "User Documentation for IDA v2.4.0," + LLNL technical report UCRL-MA-208112, November 2004. + +[4] R. Serban and C. Petra, "User Documentation for IDAS v1.0.0," + LLNL technical report UCRL-SM-234051, August 2007. + +[5] A. M. Collier, A. C. Hindmarsh, R. Serban,and C. S. Woodward, "User + Documentation for KINSOL v2.4.0," LLNL technical report UCRL-MA-208116, + November 2004. + + +D. Releases +----------- + +v. 2.4.0 - Jan. 2008 +v. 2.3.0 - Nov. 2006 +v. 2.2.0 - Mar. 2006 +v. 2.1.1 - May. 2005 +v. 2.1.0 - Apr. 2005 +v. 2.0.2 - Mar. 2005 +v. 2.0.1 - Jan. 2005 +v. 2.0 - Dec. 2004 +v. 1.0 - Jul. 2002 (first SUNDIALS release) + + +E. Revision History +------------------- + +v. 2.3.0 (Nov. 2006) ---> v. 2.4.0 (Jan. 2008) +--------------------------------------------------------- + +- none + +v. 2.2.0 (Mar. 2006) ---> v. 2.3.0 (Nov. 2006) +---------------------------------------------- + +- Changes related to the build system + - reorganized source tree. Header files in ${srcdir}/include/nvector; + sources in ${srcdir}/src/nvec_par + - exported header files in ${includedir}/sundials + +v. 2.1.1 (May. 2005) ---> v. 2.2.0 (Mar. 2006) +---------------------------------------------- + +- none + +v. 2.1.0 (Apr. 2005) ---> v. 2.1.1 (May. 2005) +---------------------------------------------- + +- Changes to user interface + - added argument to initialization routines to allow user to specify a + different MPI communicator + +- Changes to data structures + - added N_VCloneEmpty to global vector operations table + +v. 2.0.2 (Mar. 2005) ---> v. 2.1.0 (Apr. 2005) +---------------------------------------------- + +- none + +v. 2.0.1 (Jan. 2005) ---> v. 2.0.2 (Mar. 2005) +---------------------------------------------- + +- Changes related to the build system + - fixed autoconf-related bug to allow configuration with the PGI Fortran compiler + - modified to use customized detection of the Fortran name mangling scheme + (autoconf's AC_F77_WRAPPERS routine is problematic on some platforms) + - added --with-mpi-flags as a configure option to allow user to specify + MPI-specific flags + - updated Makefiles for Fortran examples to avoid C++ compiler errors (now use + CC and MPICC to link) + +v. 2.0 (Dec. 2004) ---> v. 2.0.1 (Jan. 2005) +-------------------------------------------- + +- Changes related to the build system + - changed order of compiler directives in header files to avoid compilation + errors when using a C++ compiler. + +v. 1.0 (Jul. 2002) ---> v. 2.0 (Dec. 2004) +------------------------------------------ + +- Revised to correspond to new generic NVECTOR module + (see sundials/shared/README). +- Extended the list of user-callable functions provided by NVECTOR_PARALLEL + outside the table of vector operations. +- Revised parallel N_VMin and N_VMinQuotient to use BIG_REAL if + local N is 0 or no quotients found. +- Revised the F/C interface to use underscore flags for name mapping + and to use precision flag from configure. +- Revised F/C routine NVECTOR names for uniformity. diff --git a/odemex/Parser/CVode/cv_src/src/nvec_par/fnvector_parallel.c b/odemex/Parser/CVode/cv_src/src/nvec_par/fnvector_parallel.c new file mode 100644 index 0000000..6ece6b9 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/nvec_par/fnvector_parallel.c @@ -0,0 +1,182 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.1 $ + * $Date: 2006/07/05 15:32:37 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This file (companion of nvector_parallel.h) contains the + * implementation needed for the Fortran initialization of parallel + * vector operations. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "fnvector_parallel.h" + +/* Define global vector variables */ + +N_Vector F2C_CVODE_vec; +N_Vector F2C_CVODE_vecQ; +N_Vector *F2C_CVODE_vecS; +N_Vector F2C_CVODE_vecB; +N_Vector F2C_CVODE_vecQB; + +N_Vector F2C_IDA_vec; +N_Vector F2C_IDA_vecQ; +N_Vector *F2C_IDA_vecS; +N_Vector F2C_IDA_vecB; +N_Vector F2C_IDA_vecQB; + +N_Vector F2C_KINSOL_vec; + +#ifndef SUNDIALS_MPI_COMM_F2C +#define MPI_Fint int +#endif + +/* Fortran callable interfaces */ + +void FNV_INITP(MPI_Fint *comm, int *code, long int *L, long int *N, int *ier) +{ + MPI_Comm F2C_comm; + +#ifdef SUNDIALS_MPI_COMM_F2C + F2C_comm = MPI_Comm_f2c(*comm); +#else + F2C_comm = MPI_COMM_WORLD; +#endif + + *ier = 0; + + switch(*code) { + case FCMIX_CVODE: + F2C_CVODE_vec = NULL; + F2C_CVODE_vec = N_VNewEmpty_Parallel(F2C_comm, *L, *N); + if (F2C_CVODE_vec == NULL) *ier = -1; + break; + case FCMIX_IDA: + F2C_IDA_vec = NULL; + F2C_IDA_vec = N_VNewEmpty_Parallel(F2C_comm, *L, *N); + if (F2C_IDA_vec == NULL) *ier = -1; + break; + case FCMIX_KINSOL: + F2C_KINSOL_vec = NULL; + F2C_KINSOL_vec = N_VNewEmpty_Parallel(F2C_comm, *L, *N); + if (F2C_KINSOL_vec == NULL) *ier = -1; + break; + default: + *ier = -1; + } +} + +void FNV_INITP_Q(MPI_Fint *comm, int *code, long int *Lq, long int *Nq, int *ier) +{ + MPI_Comm F2C_comm; + +#ifdef SUNDIALS_MPI_COMM_F2C + F2C_comm = MPI_Comm_f2c(*comm); +#else + F2C_comm = MPI_COMM_WORLD; +#endif + + *ier = 0; + + switch(*code) { + case FCMIX_CVODE: + F2C_CVODE_vecQ = NULL; + F2C_CVODE_vecQ = N_VNewEmpty_Parallel(F2C_comm, *Lq, *Nq); + if (F2C_CVODE_vecQ == NULL) *ier = -1; + break; + case FCMIX_IDA: + F2C_IDA_vecQ = NULL; + F2C_IDA_vecQ = N_VNewEmpty_Parallel(F2C_comm, *Lq, *Nq); + if (F2C_IDA_vecQ == NULL) *ier = -1; + break; + default: + *ier = -1; + } +} + +void FNV_INITP_B(MPI_Fint *comm, int *code, long int *LB, long int *NB, int *ier) +{ + MPI_Comm F2C_comm; + +#ifdef SUNDIALS_MPI_COMM_F2C + F2C_comm = MPI_Comm_f2c(*comm); +#else + F2C_comm = MPI_COMM_WORLD; +#endif + + *ier = 0; + + switch(*code) { + case FCMIX_CVODE: + F2C_CVODE_vecB = NULL; + F2C_CVODE_vecB = N_VNewEmpty_Parallel(F2C_comm, *LB, *NB); + if (F2C_CVODE_vecB == NULL) *ier = -1; + break; + case FCMIX_IDA: + F2C_IDA_vecB = NULL; + F2C_IDA_vecB = N_VNewEmpty_Parallel(F2C_comm, *LB, *NB); + if (F2C_IDA_vecB == NULL) *ier = -1; + break; + default: + *ier = -1; + } +} + +void FNV_INITP_QB(MPI_Fint *comm, int *code, long int *LqB, long int *NqB, int *ier) +{ + MPI_Comm F2C_comm; + +#ifdef SUNDIALS_MPI_COMM_F2C + F2C_comm = MPI_Comm_f2c(*comm); +#else + F2C_comm = MPI_COMM_WORLD; +#endif + + + *ier = 0; + + switch(*code) { + case FCMIX_CVODE: + F2C_CVODE_vecQB = NULL; + F2C_CVODE_vecQB = N_VNewEmpty_Parallel(F2C_comm, *LqB, *NqB); + if (F2C_CVODE_vecQB == NULL) *ier = -1; + break; + case FCMIX_IDA: + F2C_IDA_vecQB = NULL; + F2C_IDA_vecQB = N_VNewEmpty_Parallel(F2C_comm, *LqB, *NqB); + if (F2C_IDA_vecQB == NULL) *ier = -1; + break; + default: + *ier = -1; + } +} + +void FNV_INITP_S(int *code, int *Ns, int *ier) +{ + *ier = 0; + + switch(*code) { + case FCMIX_CVODE: + F2C_CVODE_vecS = NULL; + F2C_CVODE_vecS = (N_Vector *) N_VCloneVectorArrayEmpty_Parallel(*Ns, F2C_CVODE_vec); + if (F2C_CVODE_vecS == NULL) *ier = -1; + break; + case FCMIX_IDA: + F2C_IDA_vecS = NULL; + F2C_IDA_vecS = (N_Vector *) N_VCloneVectorArrayEmpty_Parallel(*Ns, F2C_IDA_vec); + if (F2C_IDA_vecS == NULL) *ier = -1; + break; + default: + *ier = -1; + } +} diff --git a/odemex/Parser/CVode/cv_src/src/nvec_par/fnvector_parallel.h b/odemex/Parser/CVode/cv_src/src/nvec_par/fnvector_parallel.h new file mode 100644 index 0000000..79837bb --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/nvec_par/fnvector_parallel.h @@ -0,0 +1,88 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.3 $ + * $Date: 2006/11/29 00:05:09 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This file (companion of nvector_parallel.c) contains the + * definitions needed for the initialization of parallel + * vector operations in Fortran. + * ----------------------------------------------------------------- + */ + +#ifndef _FNVECTOR_PARALLEL_H +#define _FNVECTOR_PARALLEL_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +#if defined(F77_FUNC) + +#define FNV_INITP F77_FUNC(fnvinitp, FNVINITP) +#define FNV_INITP_Q F77_FUNC_(fnvinitp_q, FNVINITP_Q) +#define FNV_INITP_S F77_FUNC_(fnvinitp_s, FNVINITP_S) +#define FNV_INITP_B F77_FUNC_(fnvinitp_b, FNVINITP_B) +#define FNV_INITP_QB F77_FUNC_(fnvinitp_qb, FNVINITP_QB) + +#else + +#define FNV_INITP fnvinitp_ +#define FNV_INITP_Q fnvinitp_q_ +#define FNV_INITP_S fnvinitp_s_ +#define FNV_INITP_B fnvinitp_b_ +#define FNV_INITP_QB fnvinitp_qb_ + +#endif + +/* Declarations of global variables */ + +extern N_Vector F2C_CVODE_vec; +extern N_Vector F2C_CVODE_vecQ; +extern N_Vector *F2C_CVODE_vecS; +extern N_Vector F2C_CVODE_vecB; +extern N_Vector F2C_CVODE_vecQB; + +extern N_Vector F2C_IDA_vec; +extern N_Vector F2C_IDA_vecQ; +extern N_Vector *F2C_IDA_vecS; +extern N_Vector F2C_IDA_vecB; +extern N_Vector F2C_IDA_vecQB; + +extern N_Vector F2C_KINSOL_vec; + +/* + * Prototypes of exported functions + * + * FNV_INITP - initializes parallel vector operations for main problem + * FNV_INITP_Q - initializes parallel vector operations for quadratures + * FNV_INITP_S - initializes parallel vector operations for sensitivities + * FNV_INITP_B - initializes parallel vector operations for adjoint problem + * FNV_INITP_QB - initializes parallel vector operations for adjoint quadratures + * + */ + +#ifndef SUNDIALS_MPI_COMM_F2C +#define MPI_Fint int +#endif + +void FNV_INITP(MPI_Fint *comm, int *code, long int *L, long int *N, int *ier); +void FNV_INITP_Q(MPI_Fint *comm, int *code, long int *Lq, long int *Nq, int *ier); +void FNV_INITP_B(MPI_Fint *comm, int *code, long int *LB, long int *NB, int *ier); +void FNV_INITP_QB(MPI_Fint *comm, int *code, long int *LqB, long int *NqB, int *ier); +void FNV_INITP_S(int *code, int *Ns, int *ier); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/src/nvec_par/nvector_parallel.c b/odemex/Parser/CVode/cv_src/src/nvec_par/nvector_parallel.c new file mode 100644 index 0000000..8a53fab --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/nvec_par/nvector_parallel.c @@ -0,0 +1,1152 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.1 $ + * $Date: 2006/07/05 15:32:37 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban, + * and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for a parallel MPI implementation + * of the NVECTOR package. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include + +#define ZERO RCONST(0.0) +#define HALF RCONST(0.5) +#define ONE RCONST(1.0) +#define ONEPT5 RCONST(1.5) + +/* Error Message */ + +#define BAD_N1 "N_VNew_Parallel -- Sum of local vector lengths differs from " +#define BAD_N2 "input global length. \n\n" +#define BAD_N BAD_N1 BAD_N2 + +/* Private function prototypes */ + +/* Reduction operations add/max/min over the processor group */ +static realtype VAllReduce_Parallel(realtype d, int op, MPI_Comm comm); +/* z=x */ +static void VCopy_Parallel(N_Vector x, N_Vector z); +/* z=x+y */ +static void VSum_Parallel(N_Vector x, N_Vector y, N_Vector z); +/* z=x-y */ +static void VDiff_Parallel(N_Vector x, N_Vector y, N_Vector z); +/* z=-x */ +static void VNeg_Parallel(N_Vector x, N_Vector z); +/* z=c(x+y) */ +static void VScaleSum_Parallel(realtype c, N_Vector x, N_Vector y, N_Vector z); +/* z=c(x-y) */ +static void VScaleDiff_Parallel(realtype c, N_Vector x, N_Vector y, N_Vector z); +/* z=ax+y */ +static void VLin1_Parallel(realtype a, N_Vector x, N_Vector y, N_Vector z); +/* z=ax-y */ +static void VLin2_Parallel(realtype a, N_Vector x, N_Vector y, N_Vector z); +/* y <- ax+y */ +static void Vaxpy_Parallel(realtype a, N_Vector x, N_Vector y); +/* x <- ax */ +static void VScaleBy_Parallel(realtype a, N_Vector x); + +/* + * ----------------------------------------------------------------- + * exported functions + * ----------------------------------------------------------------- + */ + +/* ---------------------------------------------------------------- + * Function to create a new parallel vector with empty data array + */ + +N_Vector N_VNewEmpty_Parallel(MPI_Comm comm, + long int local_length, + long int global_length) +{ + N_Vector v; + N_Vector_Ops ops; + N_VectorContent_Parallel content; + long int n, Nsum; + + /* Compute global length as sum of local lengths */ + n = local_length; + MPI_Allreduce(&n, &Nsum, 1, PVEC_INTEGER_MPI_TYPE, MPI_SUM, comm); + if (Nsum != global_length) { + printf(BAD_N); + return(NULL); + } + + /* Create vector */ + v = NULL; + v = (N_Vector) malloc(sizeof *v); + if (v == NULL) return(NULL); + + /* Create vector operation structure */ + ops = NULL; + ops = (N_Vector_Ops) malloc(sizeof(struct _generic_N_Vector_Ops)); + if (ops == NULL) { free(v); return(NULL); } + + ops->nvclone = N_VClone_Parallel; + ops->nvcloneempty = N_VCloneEmpty_Parallel; + ops->nvdestroy = N_VDestroy_Parallel; + ops->nvspace = N_VSpace_Parallel; + ops->nvgetarraypointer = N_VGetArrayPointer_Parallel; + ops->nvsetarraypointer = N_VSetArrayPointer_Parallel; + ops->nvlinearsum = N_VLinearSum_Parallel; + ops->nvconst = N_VConst_Parallel; + ops->nvprod = N_VProd_Parallel; + ops->nvdiv = N_VDiv_Parallel; + ops->nvscale = N_VScale_Parallel; + ops->nvabs = N_VAbs_Parallel; + ops->nvinv = N_VInv_Parallel; + ops->nvaddconst = N_VAddConst_Parallel; + ops->nvdotprod = N_VDotProd_Parallel; + ops->nvmaxnorm = N_VMaxNorm_Parallel; + ops->nvwrmsnormmask = N_VWrmsNormMask_Parallel; + ops->nvwrmsnorm = N_VWrmsNorm_Parallel; + ops->nvmin = N_VMin_Parallel; + ops->nvwl2norm = N_VWL2Norm_Parallel; + ops->nvl1norm = N_VL1Norm_Parallel; + ops->nvcompare = N_VCompare_Parallel; + ops->nvinvtest = N_VInvTest_Parallel; + ops->nvconstrmask = N_VConstrMask_Parallel; + ops->nvminquotient = N_VMinQuotient_Parallel; + + /* Create content */ + content = NULL; + content = (N_VectorContent_Parallel) malloc(sizeof(struct _N_VectorContent_Parallel)); + if (content == NULL) { free(ops); free(v); return(NULL); } + + /* Attach lengths and communicator */ + content->local_length = local_length; + content->global_length = global_length; + content->comm = comm; + content->own_data = FALSE; + content->data = NULL; + + /* Attach content and ops */ + v->content = content; + v->ops = ops; + + return(v); +} + +/* ---------------------------------------------------------------- + * Function to create a new parallel vector + */ + +N_Vector N_VNew_Parallel(MPI_Comm comm, + long int local_length, + long int global_length) +{ + N_Vector v; + realtype *data; + + v = NULL; + v = N_VNewEmpty_Parallel(comm, local_length, global_length); + if (v == NULL) return(NULL); + + /* Create data */ + if(local_length > 0) { + + /* Allocate memory */ + data = NULL; + data = (realtype *) malloc(local_length * sizeof(realtype)); + if(data == NULL) { N_VDestroy_Parallel(v); return(NULL); } + + /* Attach data */ + NV_OWN_DATA_P(v) = TRUE; + NV_DATA_P(v) = data; + + } + + return(v); +} + +/* ---------------------------------------------------------------- + * Function to create a parallel N_Vector with user data component + */ + +N_Vector N_VMake_Parallel(MPI_Comm comm, + long int local_length, + long int global_length, + realtype *v_data) +{ + N_Vector v; + + v = NULL; + v = N_VNewEmpty_Parallel(comm, local_length, global_length); + if (v == NULL) return(NULL); + + if (local_length > 0) { + /* Attach data */ + NV_OWN_DATA_P(v) = FALSE; + NV_DATA_P(v) = v_data; + } + + return(v); +} + +/* ---------------------------------------------------------------- + * Function to create an array of new parallel vectors. + */ + +N_Vector *N_VCloneVectorArray_Parallel(int count, N_Vector w) +{ + N_Vector *vs; + int j; + + if (count <= 0) return(NULL); + + vs = NULL; + vs = (N_Vector *) malloc(count * sizeof(N_Vector)); + if(vs == NULL) return(NULL); + + for (j = 0; j < count; j++) { + vs[j] = NULL; + vs[j] = N_VClone_Parallel(w); + if (vs[j] == NULL) { + N_VDestroyVectorArray_Parallel(vs, j-1); + return(NULL); + } + } + + return(vs); +} + +/* ---------------------------------------------------------------- + * Function to create an array of new parallel vectors with empty + * (NULL) data array. + */ + +N_Vector *N_VCloneVectorArrayEmpty_Parallel(int count, N_Vector w) +{ + N_Vector *vs; + int j; + + if (count <= 0) return(NULL); + + vs = NULL; + vs = (N_Vector *) malloc(count * sizeof(N_Vector)); + if(vs == NULL) return(NULL); + + for (j = 0; j < count; j++) { + vs[j] = NULL; + vs[j] = N_VCloneEmpty_Parallel(w); + if (vs[j] == NULL) { + N_VDestroyVectorArray_Parallel(vs, j-1); + return(NULL); + } + } + + return(vs); +} + +/* ---------------------------------------------------------------- + * Function to free an array created with N_VCloneVectorArray_Parallel + */ + +void N_VDestroyVectorArray_Parallel(N_Vector *vs, int count) +{ + int j; + + for (j = 0; j < count; j++) N_VDestroy_Parallel(vs[j]); + + free(vs); vs = NULL; + + return; +} + +/* ---------------------------------------------------------------- + * Function to print a parallel vector + */ + +void N_VPrint_Parallel(N_Vector x) +{ + long int i, N; + realtype *xd; + + xd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + + for (i = 0; i < N; i++) { +#if defined(SUNDIALS_EXTENDED_PRECISION) + printf("%Lg\n", xd[i]); +#elif defined(SUNDIALS_DOUBLE_PRECISION) + printf("%lg\n", xd[i]); +#else + printf("%g\n", xd[i]); +#endif + } + printf("\n"); + + return; +} + +/* + * ----------------------------------------------------------------- + * implementation of vector operations + * ----------------------------------------------------------------- + */ + +N_Vector N_VCloneEmpty_Parallel(N_Vector w) +{ + N_Vector v; + N_Vector_Ops ops; + N_VectorContent_Parallel content; + + if (w == NULL) return(NULL); + + /* Create vector */ + v = NULL; + v = (N_Vector) malloc(sizeof *v); + if (v == NULL) return(NULL); + + /* Create vector operation structure */ + ops = NULL; + ops = (N_Vector_Ops) malloc(sizeof(struct _generic_N_Vector_Ops)); + if (ops == NULL) { free(v); return(NULL); } + + ops->nvclone = w->ops->nvclone; + ops->nvcloneempty = w->ops->nvcloneempty; + ops->nvdestroy = w->ops->nvdestroy; + ops->nvspace = w->ops->nvspace; + ops->nvgetarraypointer = w->ops->nvgetarraypointer; + ops->nvsetarraypointer = w->ops->nvsetarraypointer; + ops->nvlinearsum = w->ops->nvlinearsum; + ops->nvconst = w->ops->nvconst; + ops->nvprod = w->ops->nvprod; + ops->nvdiv = w->ops->nvdiv; + ops->nvscale = w->ops->nvscale; + ops->nvabs = w->ops->nvabs; + ops->nvinv = w->ops->nvinv; + ops->nvaddconst = w->ops->nvaddconst; + ops->nvdotprod = w->ops->nvdotprod; + ops->nvmaxnorm = w->ops->nvmaxnorm; + ops->nvwrmsnormmask = w->ops->nvwrmsnormmask; + ops->nvwrmsnorm = w->ops->nvwrmsnorm; + ops->nvmin = w->ops->nvmin; + ops->nvwl2norm = w->ops->nvwl2norm; + ops->nvl1norm = w->ops->nvl1norm; + ops->nvcompare = w->ops->nvcompare; + ops->nvinvtest = w->ops->nvinvtest; + ops->nvconstrmask = w->ops->nvconstrmask; + ops->nvminquotient = w->ops->nvminquotient; + + /* Create content */ + content = NULL; + content = (N_VectorContent_Parallel) malloc(sizeof(struct _N_VectorContent_Parallel)); + if (content == NULL) { free(ops); free(v); return(NULL); } + + /* Attach lengths and communicator */ + content->local_length = NV_LOCLENGTH_P(w); + content->global_length = NV_GLOBLENGTH_P(w); + content->comm = NV_COMM_P(w); + content->own_data = FALSE; + content->data = NULL; + + /* Attach content and ops */ + v->content = content; + v->ops = ops; + + return(v); +} + +N_Vector N_VClone_Parallel(N_Vector w) +{ + N_Vector v; + realtype *data; + long int local_length; + + v = NULL; + v = N_VCloneEmpty_Parallel(w); + if (v == NULL) return(NULL); + + local_length = NV_LOCLENGTH_P(w); + + /* Create data */ + if(local_length > 0) { + + /* Allocate memory */ + data = NULL; + data = (realtype *) malloc(local_length * sizeof(realtype)); + if(data == NULL) { N_VDestroy_Parallel(v); return(NULL); } + + /* Attach data */ + NV_OWN_DATA_P(v) = TRUE; + NV_DATA_P(v) = data; + } + + return(v); +} + +void N_VDestroy_Parallel(N_Vector v) +{ + if ((NV_OWN_DATA_P(v) == TRUE) && (NV_DATA_P(v) != NULL)) { + free(NV_DATA_P(v)); + NV_DATA_P(v) = NULL; + } + free(v->content); v->content = NULL; + free(v->ops); v->ops = NULL; + free(v); v = NULL; + + return; +} + +void N_VSpace_Parallel(N_Vector v, long int *lrw, long int *liw) +{ + MPI_Comm comm; + int npes; + + comm = NV_COMM_P(v); + MPI_Comm_size(comm, &npes); + + *lrw = NV_GLOBLENGTH_P(v); + *liw = 2*npes; + + return; +} + +realtype *N_VGetArrayPointer_Parallel(N_Vector v) +{ + return((realtype *) NV_DATA_P(v)); +} + +void N_VSetArrayPointer_Parallel(realtype *v_data, N_Vector v) +{ + if (NV_LOCLENGTH_P(v) > 0) NV_DATA_P(v) = v_data; + + return; +} + +void N_VLinearSum_Parallel(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z) +{ + long int i, N; + realtype c, *xd, *yd, *zd; + N_Vector v1, v2; + booleantype test; + + xd = yd = zd = NULL; + + if ((b == ONE) && (z == y)) { /* BLAS usage: axpy y <- ax+y */ + Vaxpy_Parallel(a, x, y); + return; + } + + if ((a == ONE) && (z == x)) { /* BLAS usage: axpy x <- by+x */ + Vaxpy_Parallel(b, y, x); + return; + } + + /* Case: a == b == 1.0 */ + + if ((a == ONE) && (b == ONE)) { + VSum_Parallel(x, y, z); + return; + } + + /* Cases: (1) a == 1.0, b = -1.0, (2) a == -1.0, b == 1.0 */ + + if ((test = ((a == ONE) && (b == -ONE))) || ((a == -ONE) && (b == ONE))) { + v1 = test ? y : x; + v2 = test ? x : y; + VDiff_Parallel(v2, v1, z); + return; + } + + /* Cases: (1) a == 1.0, b == other or 0.0, (2) a == other or 0.0, b == 1.0 */ + /* if a or b is 0.0, then user should have called N_VScale */ + + if ((test = (a == ONE)) || (b == ONE)) { + c = test ? b : a; + v1 = test ? y : x; + v2 = test ? x : y; + VLin1_Parallel(c, v1, v2, z); + return; + } + + /* Cases: (1) a == -1.0, b != 1.0, (2) a != 1.0, b == -1.0 */ + + if ((test = (a == -ONE)) || (b == -ONE)) { + c = test ? b : a; + v1 = test ? y : x; + v2 = test ? x : y; + VLin2_Parallel(c, v1, v2, z); + return; + } + + /* Case: a == b */ + /* catches case both a and b are 0.0 - user should have called N_VConst */ + + if (a == b) { + VScaleSum_Parallel(a, x, y, z); + return; + } + + /* Case: a == -b */ + + if (a == -b) { + VScaleDiff_Parallel(a, x, y, z); + return; + } + + /* Do all cases not handled above: + (1) a == other, b == 0.0 - user should have called N_VScale + (2) a == 0.0, b == other - user should have called N_VScale + (3) a,b == other, a !=b, a != -b */ + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + yd = NV_DATA_P(y); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) + zd[i] = (a*xd[i])+(b*yd[i]); + + return; +} + +void N_VConst_Parallel(realtype c, N_Vector z) +{ + long int i, N; + realtype *zd; + + zd = NULL; + + N = NV_LOCLENGTH_P(z); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) zd[i] = c; + + return; +} + +void N_VProd_Parallel(N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + yd = NV_DATA_P(y); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]*yd[i]; + + return; +} + +void N_VDiv_Parallel(N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + yd = NV_DATA_P(y); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]/yd[i]; + + return; +} + +void N_VScale_Parallel(realtype c, N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + if (z == x) { /* BLAS usage: scale x <- cx */ + VScaleBy_Parallel(c, x); + return; + } + + if (c == ONE) { + VCopy_Parallel(x, z); + } else if (c == -ONE) { + VNeg_Parallel(x, z); + } else { + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + zd = NV_DATA_P(z); + for (i = 0; i < N; i++) + zd[i] = c*xd[i]; + } + + return; +} + +void N_VAbs_Parallel(N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) + zd[i] = ABS(xd[i]); + + return; +} + +void N_VInv_Parallel(N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) + zd[i] = ONE/xd[i]; + + return; +} + +void N_VAddConst_Parallel(N_Vector x, realtype b, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) zd[i] = xd[i]+b; + + return; +} + +realtype N_VDotProd_Parallel(N_Vector x, N_Vector y) +{ + long int i, N; + realtype sum, *xd, *yd, gsum; + MPI_Comm comm; + + sum = ZERO; + xd = yd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + yd = NV_DATA_P(y); + comm = NV_COMM_P(x); + + for (i = 0; i < N; i++) sum += xd[i]*yd[i]; + + gsum = VAllReduce_Parallel(sum, 1, comm); + + return(gsum); +} + +realtype N_VMaxNorm_Parallel(N_Vector x) +{ + long int i, N; + realtype max, *xd, gmax; + MPI_Comm comm; + + xd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + comm = NV_COMM_P(x); + + max = ZERO; + + for (i = 0; i < N; i++) { + if (ABS(xd[i]) > max) max = ABS(xd[i]); + } + + gmax = VAllReduce_Parallel(max, 2, comm); + + return(gmax); +} + +realtype N_VWrmsNorm_Parallel(N_Vector x, N_Vector w) +{ + long int i, N, N_global; + realtype sum, prodi, *xd, *wd, gsum; + MPI_Comm comm; + + sum = ZERO; + xd = wd = NULL; + + N = NV_LOCLENGTH_P(x); + N_global = NV_GLOBLENGTH_P(x); + xd = NV_DATA_P(x); + wd = NV_DATA_P(w); + comm = NV_COMM_P(x); + + for (i = 0; i < N; i++) { + prodi = xd[i]*wd[i]; + sum += SQR(prodi); + } + + gsum = VAllReduce_Parallel(sum, 1, comm); + + return(RSqrt(gsum/N_global)); +} + +realtype N_VWrmsNormMask_Parallel(N_Vector x, N_Vector w, N_Vector id) +{ + long int i, N, N_global; + realtype sum, prodi, *xd, *wd, *idd, gsum; + MPI_Comm comm; + + sum = ZERO; + xd = wd = idd = NULL; + + N = NV_LOCLENGTH_P(x); + N_global = NV_GLOBLENGTH_P(x); + xd = NV_DATA_P(x); + wd = NV_DATA_P(w); + idd = NV_DATA_P(id); + comm = NV_COMM_P(x); + + for (i = 0; i < N; i++) { + if (idd[i] > ZERO) { + prodi = xd[i]*wd[i]; + sum += SQR(prodi); + } + } + + gsum = VAllReduce_Parallel(sum, 1, comm); + + return(RSqrt(gsum/N_global)); +} + +realtype N_VMin_Parallel(N_Vector x) +{ + long int i, N; + realtype min, *xd, gmin; + MPI_Comm comm; + + xd = NULL; + + N = NV_LOCLENGTH_P(x); + comm = NV_COMM_P(x); + + min = BIG_REAL; + + if (N > 0) { + + xd = NV_DATA_P(x); + + min = xd[0]; + + for (i = 1; i < N; i++) { + if (xd[i] < min) min = xd[i]; + } + + } + + gmin = VAllReduce_Parallel(min, 3, comm); + + return(gmin); +} + +realtype N_VWL2Norm_Parallel(N_Vector x, N_Vector w) +{ + long int i, N; + realtype sum, prodi, *xd, *wd, gsum; + MPI_Comm comm; + + sum = ZERO; + xd = wd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + wd = NV_DATA_P(w); + comm = NV_COMM_P(x); + + for (i = 0; i < N; i++) { + prodi = xd[i]*wd[i]; + sum += SQR(prodi); + } + + gsum = VAllReduce_Parallel(sum, 1, comm); + + return(RSqrt(gsum)); +} + +realtype N_VL1Norm_Parallel(N_Vector x) +{ + long int i, N; + realtype sum, gsum, *xd; + MPI_Comm comm; + + sum = ZERO; + xd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + comm = NV_COMM_P(x); + + for (i = 0; i= c) ? ONE : ZERO; + } + + return; +} + +booleantype N_VInvTest_Parallel(N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd, val, gval; + MPI_Comm comm; + + xd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + zd = NV_DATA_P(z); + comm = NV_COMM_P(x); + + val = ONE; + for (i = 0; i < N; i++) { + if (xd[i] == ZERO) + val = ZERO; + else + zd[i] = ONE/xd[i]; + } + + gval = VAllReduce_Parallel(val, 3, comm); + + if (gval == ZERO) + return(FALSE); + else + return(TRUE); +} + +booleantype N_VConstrMask_Parallel(N_Vector c, N_Vector x, N_Vector m) +{ + long int i, N; + realtype temp; + realtype *cd, *xd, *md; + MPI_Comm comm; + + cd = xd = md = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + cd = NV_DATA_P(c); + md = NV_DATA_P(m); + comm = NV_COMM_P(x); + + temp = ONE; + + for (i = 0; i < N; i++) { + md[i] = ZERO; + if (cd[i] == ZERO) continue; + if (cd[i] > ONEPT5 || cd[i] < -ONEPT5) { + if (xd[i]*cd[i] <= ZERO) { temp = ZERO; md[i] = ONE; } + continue; + } + if (cd[i] > HALF || cd[i] < -HALF) { + if (xd[i]*cd[i] < ZERO ) { temp = ZERO; md[i] = ONE; } + } + } + + temp = VAllReduce_Parallel(temp, 3, comm); + + if (temp == ONE) return(TRUE); + else return(FALSE); +} + +realtype N_VMinQuotient_Parallel(N_Vector num, N_Vector denom) +{ + booleantype notEvenOnce; + long int i, N; + realtype *nd, *dd, min; + MPI_Comm comm; + + nd = dd = NULL; + + N = NV_LOCLENGTH_P(num); + nd = NV_DATA_P(num); + dd = NV_DATA_P(denom); + comm = NV_COMM_P(num); + + notEvenOnce = TRUE; + min = BIG_REAL; + + for (i = 0; i < N; i++) { + if (dd[i] == ZERO) continue; + else { + if (!notEvenOnce) min = MIN(min, nd[i]/dd[i]); + else { + min = nd[i]/dd[i]; + notEvenOnce = FALSE; + } + } + } + + return(VAllReduce_Parallel(min, 3, comm)); +} + +/* + * ----------------------------------------------------------------- + * private functions + * ----------------------------------------------------------------- + */ + +static realtype VAllReduce_Parallel(realtype d, int op, MPI_Comm comm) +{ + /* + * This function does a global reduction. The operation is + * sum if op = 1, + * max if op = 2, + * min if op = 3. + * The operation is over all processors in the communicator + */ + + realtype out; + + switch (op) { + case 1: MPI_Allreduce(&d, &out, 1, PVEC_REAL_MPI_TYPE, MPI_SUM, comm); + break; + + case 2: MPI_Allreduce(&d, &out, 1, PVEC_REAL_MPI_TYPE, MPI_MAX, comm); + break; + + case 3: MPI_Allreduce(&d, &out, 1, PVEC_REAL_MPI_TYPE, MPI_MIN, comm); + break; + + default: break; + } + + return(out); +} + +static void VCopy_Parallel(N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]; + + return; +} + +static void VSum_Parallel(N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + yd = NV_DATA_P(y); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]+yd[i]; + + return; +} + +static void VDiff_Parallel(N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + yd = NV_DATA_P(y); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]-yd[i]; + + return; +} + +static void VNeg_Parallel(N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) + zd[i] = -xd[i]; + + return; +} + +static void VScaleSum_Parallel(realtype c, N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + yd = NV_DATA_P(y); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) + zd[i] = c*(xd[i]+yd[i]); + + return; +} + +static void VScaleDiff_Parallel(realtype c, N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + yd = NV_DATA_P(y); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) + zd[i] = c*(xd[i]-yd[i]); + + return; +} + +static void VLin1_Parallel(realtype a, N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + yd = NV_DATA_P(y); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) + zd[i] = (a*xd[i])+yd[i]; + + return; +} + +static void VLin2_Parallel(realtype a, N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + yd = NV_DATA_P(y); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) + zd[i] = (a*xd[i])-yd[i]; + + return; +} + +static void Vaxpy_Parallel(realtype a, N_Vector x, N_Vector y) +{ + long int i, N; + realtype *xd, *yd; + + xd = yd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + yd = NV_DATA_P(y); + + if (a == ONE) { + for (i = 0; i < N; i++) + yd[i] += xd[i]; + return; + } + + if (a == -ONE) { + for (i = 0; i < N; i++) + yd[i] -= xd[i]; + return; + } + + for (i = 0; i < N; i++) + yd[i] += a*xd[i]; + + return; +} + +static void VScaleBy_Parallel(realtype a, N_Vector x) +{ + long int i, N; + realtype *xd; + + xd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + + for (i = 0; i < N; i++) + xd[i] *= a; + + return; +} diff --git a/odemex/Parser/CVode/cv_src/src/nvec_ser/CMakeLists.txt b/odemex/Parser/CVode/cv_src/src/nvec_ser/CMakeLists.txt new file mode 100644 index 0000000..9c97be5 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/nvec_ser/CMakeLists.txt @@ -0,0 +1,82 @@ +# --------------------------------------------------------------- +# $Revision: 1.3 $ +# $Date: 2009/02/17 02:58:48 $ +# --------------------------------------------------------------- +# Programmer: Radu Serban @ LLNL +# --------------------------------------------------------------- +# Copyright (c) 2007, The Regents of the University of California. +# Produced at the Lawrence Livermore National Laboratory. +# All rights reserved. +# For details, see the LICENSE file. +# --------------------------------------------------------------- +# CMakeLists.txt file for the serial NVECTOR library + +INSTALL(CODE "MESSAGE(\"\nInstall NVECTOR_SERIAL\n\")") + +# Add variable nvecserial_SOURCES with the sources for the NVECSERIAL lib +SET(nvecserial_SOURCES nvector_serial.c) + +# Add variable shared_SOURCES with the common SUNDIALS sources which will +# also be included in the NVECSERIAL library +SET(shared_SOURCES sundials_math.c) +ADD_PREFIX(${sundials_SOURCE_DIR}/src/sundials/ shared_SOURCES) + +# Add variable nvecserial_HEADERS with the exported NVECSERIAL header files +SET(nvecserial_HEADERS nvector_serial.h) +ADD_PREFIX(${sundials_SOURCE_DIR}/include/nvector/ nvecserial_HEADERS) + +# Add source directory to include directories +INCLUDE_DIRECTORIES(.) + +# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY +ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY) + +# Rules for building and installing the static library: +# - Add the build target for the NVECSERIAL library +# - Set the library name and make sure it is not deleted +# - Install the NVECSERIAL library +IF(BUILD_STATIC_LIBS) + ADD_LIBRARY(sundials_nvecserial_static STATIC ${nvecserial_SOURCES} ${shared_SOURCES}) + SET_TARGET_PROPERTIES(sundials_nvecserial_static + PROPERTIES OUTPUT_NAME sundials_nvecserial CLEAN_DIRECT_OUTPUT 1) + INSTALL(TARGETS sundials_nvecserial_static DESTINATION lib) +ENDIF(BUILD_STATIC_LIBS) + +# Rules for building and installing the shared library: +# - Add the build target for the NVECSERIAL library +# - Set the library name and make sure it is not deleted +# - Set VERSION and SOVERSION for shared libraries +# - Install the NVECSERIAL library +IF(BUILD_SHARED_LIBS) + ADD_LIBRARY(sundials_nvecserial_shared SHARED ${nvecserial_SOURCES} ${shared_SOURCES}) + SET_TARGET_PROPERTIES(sundials_nvecserial_shared + PROPERTIES OUTPUT_NAME sundials_nvecserial CLEAN_DIRECT_OUTPUT 1) + SET_TARGET_PROPERTIES(sundials_nvecserial_shared + PROPERTIES VERSION ${nveclib_VERSION} SOVERSION ${nveclib_SOVERSION}) + INSTALL(TARGETS sundials_nvecserial_shared DESTINATION lib) +ENDIF(BUILD_SHARED_LIBS) + +# Install the NVECSERIAL header files +INSTALL(FILES ${nvecserial_HEADERS} DESTINATION include/nvector) + +# If FCMIX is enabled, build and install the FNVECSERIAL library +IF(FCMIX_ENABLE AND F77_FOUND) + SET(fnvecserial_SOURCES fnvector_serial.c) + IF(BUILD_STATIC_LIBS) + ADD_LIBRARY(sundials_fnvecserial_static STATIC ${fnvecserial_SOURCES}) + SET_TARGET_PROPERTIES(sundials_fnvecserial_static + PROPERTIES OUTPUT_NAME sundials_fnvecserial CLEAN_DIRECT_OUTPUT 1) + INSTALL(TARGETS sundials_fnvecserial_static DESTINATION lib) + ENDIF(BUILD_STATIC_LIBS) + IF(BUILD_SHARED_LIBS) + ADD_LIBRARY(sundials_fnvecserial_shared ${fnvecserial_SOURCES}) + SET_TARGET_PROPERTIES(sundials_fnvecserial_shared + PROPERTIES OUTPUT_NAME sundials_fnvecserial CLEAN_DIRECT_OUTPUT 1) + SET_TARGET_PROPERTIES(sundials_fnvecserial_shared + PROPERTIES VERSION ${nveclib_VERSION} SOVERSION ${nveclib_SOVERSION}) + INSTALL(TARGETS sundials_fnvecserial_shared DESTINATION lib) + ENDIF(BUILD_SHARED_LIBS) +ENDIF(FCMIX_ENABLE AND F77_FOUND) + +# +MESSAGE(STATUS "Added NVECTOR_SERIAL module") diff --git a/odemex/Parser/CVode/cv_src/src/nvec_ser/Makefile.in b/odemex/Parser/CVode/cv_src/src/nvec_ser/Makefile.in new file mode 100644 index 0000000..fe8a6dc --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/nvec_ser/Makefile.in @@ -0,0 +1,125 @@ +# ----------------------------------------------------------------- +# $Revision: 1.8 $ +# $Date: 2007/01/29 17:36:28 $ +# ----------------------------------------------------------------- +# Programmer(s): Radu Serban and Aaron Collier @ LLNL +# ----------------------------------------------------------------- +# Copyright (c) 2002, The Regents of the University of California. +# Produced at the Lawrence Livermore National Laboratory. +# All rights reserved. +# For details, see the LICENSE file. +# ----------------------------------------------------------------- +# Makefile for serial NVECTOR module +# +# @configure_input@ +# ----------------------------------------------------------------- + +SHELL = @SHELL@ + +@SET_MAKE@ + +srcdir = @srcdir@ +builddir = @builddir@ +abs_builddir = @abs_builddir@ +top_builddir = @top_builddir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +includedir = @includedir@ +libdir = @libdir@ + +INSTALL = @INSTALL@ +INSTALL_LIB = @INSTALL_PROGRAM@ +INSTALL_HEADER = @INSTALL_DATA@ + +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ + +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CC = @CC@ +CFLAGS = @CFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ + +FCMIX_ENABLED = @FCMIX_ENABLED@ + +top_srcdir = $(srcdir)/../.. + +INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include + +LIB_REVISION = 0:2:0 + +NVECSER_LIB = libsundials_nvecserial.la +NVECSER_LIB_FILES = nvector_serial.lo + +FNVECSER_LIB = libsundials_fnvecserial.la +FNVECSER_LIB_FILES = fnvector_serial.lo + +SHARED_LIB_FILES = $(top_builddir)/src/sundials/sundials_math.lo + +mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs +rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs + +all: $(NVECSER_LIB) $(FNVECSER_LIB) + +$(NVECSER_LIB): shared $(NVECSER_LIB_FILES) + $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(NVECSER_LIB) $(NVECSER_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -version-info $(LIB_REVISION) + +$(FNVECSER_LIB): $(FNVECSER_LIB_FILES) + @if test "X${FCMIX_ENABLED}" = "Xyes"; then \ + echo "${LIBTOOL} --mode=link ${CC} ${CFLAGS} -o ${FNVECSER_LIB} ${FNVECSER_LIB_FILES} ${SHARED_LIB_FILES} -rpath ${libdir} $(LDFLAGS) ${LIBS} -version-info ${LIB_REVISION}" ; \ + ${LIBTOOL} --mode=link ${CC} ${CFLAGS} -o ${FNVECSER_LIB} ${FNVECSER_LIB_FILES} ${SHARED_LIB_FILES} -rpath ${libdir} $(LDFLAGS) ${LIBS} -version-info ${LIB_REVISION} ; \ + fi + +install: $(NVECSER_LIB) $(FNVECSER_LIB) + $(mkinstalldirs) $(includedir)/nvector + $(mkinstalldirs) $(libdir) + $(LIBTOOL) --mode=install $(INSTALL_LIB) $(NVECSER_LIB) $(libdir) + $(INSTALL_HEADER) $(top_srcdir)/include/nvector/nvector_serial.h $(includedir)/nvector/ + @if test "X${FCMIX_ENABLED}" = "Xyes"; then \ + echo "${LIBTOOL} --mode=install ${INSTALL_LIB} ${FNVECSER_LIB} ${libdir}" ; \ + ${LIBTOOL} --mode=install ${INSTALL_LIB} ${FNVECSER_LIB} ${libdir} ; \ + fi + +uninstall: + $(LIBTOOL) --mode=uninstall rm -f $(libdir)/$(NVECSER_LIB) + @if test "X${FCMIX_ENABLED}" = "Xyes"; then \ + echo "${LIBTOOL} --mode=uninstall rm -f ${libdir}/${FNVECSER_LIB}" ; \ + ${LIBTOOL} --mode=uninstall rm -f ${libdir}/${FNVECSER_LIB} ; \ + fi + rm -f $(includedir)/nvector/nvector_serial.h + $(rminstalldirs) ${includedir}/nvector + +shared: + @cd ${top_builddir}/src/sundials ; \ + ${MAKE} ; \ + cd ${abs_builddir} + +clean: + $(LIBTOOL) --mode=clean rm -f $(NVECSER_LIB) + rm -f $(NVECSER_LIB_FILES) + rm -f nvector_serial.o + @if test "X${FCMIX_ENABLED}" = "Xyes"; then \ + echo "${LIBTOOL} --mode=clean rm -f ${FNVECSER_LIB}" ; \ + ${LIBTOOL} --mode=clean rm -f ${FNVECSER_LIB} ; \ + echo "rm -f ${FNVECSER_LIB_FILES}" ; \ + rm -f ${FNVECSER_LIB_FILES} ; \ + echo "rm -f fnvector_serial.o" ; \ + rm -f fnvector_serial.o ; \ + fi + +distclean: clean + rm -f Makefile + +nvector_serial.lo: $(srcdir)/nvector_serial.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/nvector_serial.c +fnvector_serial.lo: $(srcdir)/fnvector_serial.c + @if test "X${FCMIX_ENABLED}" = "Xyes"; then \ + echo "${LIBTOOL} --mode=compile ${CC} ${CPPFLAGS} $(INCLUDES) ${CFLAGS} -c ${srcdir}/fnvector_serial.c" ; \ + ${LIBTOOL} --mode=compile ${CC} ${CPPFLAGS} $(INCLUDES) ${CFLAGS} -c ${srcdir}/fnvector_serial.c ; \ + fi + +libtool: $(top_builddir)/$(LIBTOOL_DEPS) + @cd ${top_builddir} ; \ + ${SHELL} ./config.status --recheck ; \ + cd ${abs_builddir} diff --git a/odemex/Parser/CVode/cv_src/src/nvec_ser/README b/odemex/Parser/CVode/cv_src/src/nvec_ser/README new file mode 100644 index 0000000..03b7ee5 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/nvec_ser/README @@ -0,0 +1,131 @@ + NVECTOR_SERIAL + Release 2.4.0, January 2008 + +Serial implementation of the NVECTOR module for SUNDIALS. + +NVECTOR_SERIAL defines the content field of N_Vector to be a structure +containing the length of the vector, a pointer to the beginning of a +contiguous data array, and a boolean flag indicating ownership of the +data array. + +NVECTOR_SERIAL defines five macros to provide access to the content of +a serial N_Vector, several constructors for variables of type N_Vector, +a constructor for an array of variables of type N_Vector, and destructors +for N_Vector and N_Vector array. + +NVECTOR_SERIAL provides implementations for all vector operations defined +by the generic NVECTOR module in the table of operations. + + +A. Documentation +---------------- + +The serial NVECTOR implementation is fully described in the user documentation +for any of the SUNDIALS solvers [1-5]. A PDF file for the user guide for a +particular solver is available in the solver's subdirectory under doc/. + + +B. Installation +--------------- + +For basic installation instructions see /sundials/INSTALL_NOTES. +For complete installation instructions see any of the user guides. + + +C. References +------------- + +[1] A. C. Hindmarsh and R. Serban, "User Documentation for CVODE v2.4.0," + LLLNL technical report UCRL-MA-208108, November 2004. + +[2] A. C. Hindmarsh and R. Serban, "User Documentation for CVODES v2.4.0," + LLNL technical report UCRL-MA-208111, November 2004. + +[3] A. C. Hindmarsh and R. Serban, "User Documentation for IDA v2.4.0," + LLNL technical report UCRL-MA-208112, November 2004. + +[4] R. Serban and C. Petra, "User Documentation for IDAS v1.0.0," + LLNL technical report UCRL-SM-234051, August 2007. + +[5] A. M. Collier, A. C. Hindmarsh, R. Serban,and C. S. Woodward, "User + Documentation for KINSOL v2.4.0," LLNL technical report UCRL-MA-208116, + November 2004. + + +D. Releases +----------- + +v. 2.4.0 - Jan. 2008 +v. 2.3.0 - Nov. 2006 +v. 2.2.0 - Mar. 2006 +v. 2.1.1 - May. 2005 +v. 2.1.0 - Apr. 2005 +v. 2.0.2 - Mar. 2005 +v. 2.0.1 - Jan. 2005 +v. 2.0 - Dec. 2004 +v. 1.0 - Jul. 2002 (first SUNDIALS release) + + +E. Revision History +------------------- + +v. 2.3.0 (Nov. 2006) ---> v. 2.4.0 (Jan. 2008) +--------------------------------------------------------- + +- none + + +v. 2.2.0 (Mar. 2006) ---> v. 2.3.0 (Nov. 2006) +---------------------------------------------- + +- Changes related to the build system + - reorganized source tree. Header files in ${srcdir}/include/nvector; + sources in ${srcdir}/src/nvec_ser + - exported header files in ${includedir}/sundials + + +v. 2.1.1 (May. 2005) ---> v. 2.2.0 (Mar. 2006) +---------------------------------------------- + +- none + +v. 2.1.0 (Apr. 2005) ---> v. 2.1.1 (May. 2005) +---------------------------------------------- + +- Changes to data structures + - added N_VCloneEmpty to global vector operations table + +v. 2.0.2 (Mar. 2005) ---> v. 2.1.0 (Apr. 2005) +---------------------------------------------- + +- none + +v. 2.0.1 (Jan. 2005) ---> v. 2.0.2 (Mar. 2005) +---------------------------------------------- + +- Changes related to the build system + - fixed autoconf-related bug to allow configuration with the PGI Fortran compiler + - modified to use customized detection of the Fortran name mangling scheme + (autoconf's AC_F77_WRAPPERS routine is problematic on some platforms) + - added --with-mpi-flags as a configure option to allow user to specify + MPI-specific flags + - updated Makefiles for Fortran examples to avoid C++ compiler errors (now use + CC and MPICC to link) + +v. 2.0 (Dec. 2004) ---> v. 2.0.1 (Jan. 2005) +-------------------------------------------- + +- Changes related to the build system + - changed order of compiler directives in header files to avoid compilation + errors when using a C++ compiler. + +v. 1.0 (Jul. 2002) ---> v. 2.0 (Dec. 2004) +------------------------------------------ + +- Revised to correspond to new generic NVECTOR module + (see sundials/shared/README). +- Extended the list of user-callable functions provided by NVECTOR_SERIAL + outside the table of vector operations. +- Revised the F/C interface to use underscore flags for name mapping + and to use precision flag from configure. +- Revised F/C routine NVECTOR names for uniformity. diff --git a/odemex/Parser/CVode/cv_src/src/nvec_ser/fnvector_serial.c b/odemex/Parser/CVode/cv_src/src/nvec_ser/fnvector_serial.c new file mode 100644 index 0000000..8f83c80 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/nvec_ser/fnvector_serial.c @@ -0,0 +1,147 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.1 $ + * $Date: 2006/07/05 15:32:37 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This file (companion of nvector_serial.h) contains the + * implementation needed for the Fortran initialization of serial + * vector operations. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "fnvector_serial.h" + +/* Define global vector variables */ + +N_Vector F2C_CVODE_vec; +N_Vector F2C_CVODE_vecQ; +N_Vector *F2C_CVODE_vecS; +N_Vector F2C_CVODE_vecB; +N_Vector F2C_CVODE_vecQB; + +N_Vector F2C_IDA_vec; +N_Vector F2C_IDA_vecQ; +N_Vector *F2C_IDA_vecS; +N_Vector F2C_IDA_vecB; +N_Vector F2C_IDA_vecQB; + +N_Vector F2C_KINSOL_vec; + +/* Fortran callable interfaces */ + +void FNV_INITS(int *code, long int *N, int *ier) +{ + *ier = 0; + + switch(*code) { + case FCMIX_CVODE: + F2C_CVODE_vec = NULL; + F2C_CVODE_vec = N_VNewEmpty_Serial(*N); + if (F2C_CVODE_vec == NULL) *ier = -1; + break; + case FCMIX_IDA: + F2C_IDA_vec = NULL; + F2C_IDA_vec = N_VNewEmpty_Serial(*N); + if (F2C_IDA_vec == NULL) *ier = -1; + break; + case FCMIX_KINSOL: + F2C_KINSOL_vec = NULL; + F2C_KINSOL_vec = N_VNewEmpty_Serial(*N); + if (F2C_KINSOL_vec == NULL) *ier = -1; + break; + default: + *ier = -1; + } +} + +void FNV_INITS_Q(int *code, long int *Nq, int *ier) +{ + *ier = 0; + + switch(*code) { + case FCMIX_CVODE: + F2C_CVODE_vecQ = NULL; + F2C_CVODE_vecQ = N_VNewEmpty_Serial(*Nq); + if (F2C_CVODE_vecQ == NULL) *ier = -1; + break; + case FCMIX_IDA: + F2C_IDA_vecQ = NULL; + F2C_IDA_vecQ = N_VNewEmpty_Serial(*Nq); + if (F2C_IDA_vecQ == NULL) *ier = -1; + break; + default: + *ier = -1; + } +} + +void FNV_INITS_B(int *code, long int *NB, int *ier) +{ + *ier = 0; + + switch(*code) { + case FCMIX_CVODE: + F2C_CVODE_vecB = NULL; + F2C_CVODE_vecB = N_VNewEmpty_Serial(*NB); + if (F2C_CVODE_vecB == NULL) *ier = -1; + break; + case FCMIX_IDA: + F2C_IDA_vecB = NULL; + F2C_IDA_vecB = N_VNewEmpty_Serial(*NB); + if (F2C_IDA_vecB == NULL) *ier = -1; + break; + default: + *ier = -1; + } +} + +void FNV_INITS_QB(int *code, long int *NqB, int *ier) +{ + *ier = 0; + + switch(*code) { + case FCMIX_CVODE: + F2C_CVODE_vecQB = NULL; + F2C_CVODE_vecQB = N_VNewEmpty_Serial(*NqB); + if (F2C_CVODE_vecQB == NULL) *ier = -1; + break; + case FCMIX_IDA: + F2C_IDA_vecQB = NULL; + F2C_IDA_vecQB = N_VNewEmpty_Serial(*NqB); + if (F2C_IDA_vecQB == NULL) *ier = -1; + break; + default: + *ier = -1; + } +} + +void FNV_INITS_S(int *code, int *Ns, int *ier) +{ + *ier = 0; + + switch(*code) { + case FCMIX_CVODE: + F2C_CVODE_vecS = NULL; + F2C_CVODE_vecS = (N_Vector *) N_VCloneVectorArrayEmpty_Serial(*Ns, F2C_CVODE_vec); + if (F2C_CVODE_vecS == NULL) *ier = -1; + break; + case FCMIX_IDA: + F2C_IDA_vecS = NULL; + F2C_IDA_vecS = (N_Vector *) N_VCloneVectorArrayEmpty_Serial(*Ns, F2C_IDA_vec); + if (F2C_IDA_vecS == NULL) *ier = -1; + break; + default: + *ier = -1; + } +} + + diff --git a/odemex/Parser/CVode/cv_src/src/nvec_ser/fnvector_serial.h b/odemex/Parser/CVode/cv_src/src/nvec_ser/fnvector_serial.h new file mode 100644 index 0000000..2642337 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/nvec_ser/fnvector_serial.h @@ -0,0 +1,84 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.3 $ + * $Date: 2006/11/29 00:05:09 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This file (companion of nvector_serial.h) contains the + * definitions needed for the initialization of serial + * vector operations in Fortran. + * ----------------------------------------------------------------- + */ + +#ifndef _FNVECTOR_SERIAL_H +#define _FNVECTOR_SERIAL_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +#if defined(F77_FUNC) + +#define FNV_INITS F77_FUNC(fnvinits, FNVINITS) +#define FNV_INITS_Q F77_FUNC_(fnvinits_q, FNVINITS_Q) +#define FNV_INITS_S F77_FUNC_(fnvinits_s, FNVINITS_S) +#define FNV_INITS_B F77_FUNC_(fnvinits_b, FNVINITS_B) +#define FNV_INITS_QB F77_FUNC_(fnvinits_qb, FNVINITS_QB) + +#else + +#define FNV_INITS fnvinits_ +#define FNV_INITS_Q fnvinits_q_ +#define FNV_INITS_S fnvinits_s_ +#define FNV_INITS_B fnvinits_b_ +#define FNV_INITS_QB fnvinits_qb_ + +#endif + +/* Declarations of global variables */ + +extern N_Vector F2C_CVODE_vec; +extern N_Vector F2C_CVODE_vecQ; +extern N_Vector *F2C_CVODE_vecS; +extern N_Vector F2C_CVODE_vecB; +extern N_Vector F2C_CVODE_vecQB; + +extern N_Vector F2C_IDA_vec; +extern N_Vector F2C_IDA_vecQ; +extern N_Vector *F2C_IDA_vecS; +extern N_Vector F2C_IDA_vecB; +extern N_Vector F2C_IDA_vecQB; + +extern N_Vector F2C_KINSOL_vec; + +/* + * Prototypes of exported functions + * + * FNV_INITS - initializes serial vector operations for main problem + * FNV_INITS_Q - initializes serial vector operations for quadratures + * FNV_INITS_S - initializes serial vector operations for sensitivities + * FNV_INITS_B - initializes serial vector operations for adjoint problem + * FNV_INITS_QB - initializes serial vector operations for adjoint quadratures + * + */ + +void FNV_INITS(int *code, long int *neq, int *ier); +void FNV_INITS_Q(int *code, long int *Nq, int *ier); +void FNV_INITS_S(int *code, int *Ns, int *ier); +void FNV_INITS_B(int *code, long int *NB, int *ier); +void FNV_INITS_QB(int *code, long int *NqB, int *ier); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/cv_src/src/nvec_ser/nvector_serial.c b/odemex/Parser/CVode/cv_src/src/nvec_ser/nvector_serial.c new file mode 100644 index 0000000..c890253 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/nvec_ser/nvector_serial.c @@ -0,0 +1,1034 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.1 $ + * $Date: 2006/07/05 15:32:37 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban, + * and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for a serial implementation + * of the NVECTOR package. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include + +#define ZERO RCONST(0.0) +#define HALF RCONST(0.5) +#define ONE RCONST(1.0) +#define ONEPT5 RCONST(1.5) + +/* Private function prototypes */ +/* z=x */ +static void VCopy_Serial(N_Vector x, N_Vector z); +/* z=x+y */ +static void VSum_Serial(N_Vector x, N_Vector y, N_Vector z); +/* z=x-y */ +static void VDiff_Serial(N_Vector x, N_Vector y, N_Vector z); +/* z=-x */ +static void VNeg_Serial(N_Vector x, N_Vector z); +/* z=c(x+y) */ +static void VScaleSum_Serial(realtype c, N_Vector x, N_Vector y, N_Vector z); +/* z=c(x-y) */ +static void VScaleDiff_Serial(realtype c, N_Vector x, N_Vector y, N_Vector z); +/* z=ax+y */ +static void VLin1_Serial(realtype a, N_Vector x, N_Vector y, N_Vector z); +/* z=ax-y */ +static void VLin2_Serial(realtype a, N_Vector x, N_Vector y, N_Vector z); +/* y <- ax+y */ +static void Vaxpy_Serial(realtype a, N_Vector x, N_Vector y); +/* x <- ax */ +static void VScaleBy_Serial(realtype a, N_Vector x); + +/* + * ----------------------------------------------------------------- + * exported functions + * ----------------------------------------------------------------- + */ + +/* ---------------------------------------------------------------------------- + * Function to create a new empty serial vector + */ + +N_Vector N_VNewEmpty_Serial(long int length) +{ + N_Vector v; + N_Vector_Ops ops; + N_VectorContent_Serial content; + + /* Create vector */ + v = NULL; + v = (N_Vector) malloc(sizeof *v); + if (v == NULL) return(NULL); + + /* Create vector operation structure */ + ops = NULL; + ops = (N_Vector_Ops) malloc(sizeof(struct _generic_N_Vector_Ops)); + if (ops == NULL) { free(v); return(NULL); } + + ops->nvclone = N_VClone_Serial; + ops->nvcloneempty = N_VCloneEmpty_Serial; + ops->nvdestroy = N_VDestroy_Serial; + ops->nvspace = N_VSpace_Serial; + ops->nvgetarraypointer = N_VGetArrayPointer_Serial; + ops->nvsetarraypointer = N_VSetArrayPointer_Serial; + ops->nvlinearsum = N_VLinearSum_Serial; + ops->nvconst = N_VConst_Serial; + ops->nvprod = N_VProd_Serial; + ops->nvdiv = N_VDiv_Serial; + ops->nvscale = N_VScale_Serial; + ops->nvabs = N_VAbs_Serial; + ops->nvinv = N_VInv_Serial; + ops->nvaddconst = N_VAddConst_Serial; + ops->nvdotprod = N_VDotProd_Serial; + ops->nvmaxnorm = N_VMaxNorm_Serial; + ops->nvwrmsnormmask = N_VWrmsNormMask_Serial; + ops->nvwrmsnorm = N_VWrmsNorm_Serial; + ops->nvmin = N_VMin_Serial; + ops->nvwl2norm = N_VWL2Norm_Serial; + ops->nvl1norm = N_VL1Norm_Serial; + ops->nvcompare = N_VCompare_Serial; + ops->nvinvtest = N_VInvTest_Serial; + ops->nvconstrmask = N_VConstrMask_Serial; + ops->nvminquotient = N_VMinQuotient_Serial; + + /* Create content */ + content = NULL; + content = (N_VectorContent_Serial) malloc(sizeof(struct _N_VectorContent_Serial)); + if (content == NULL) { free(ops); free(v); return(NULL); } + + content->length = length; + content->own_data = FALSE; + content->data = NULL; + + /* Attach content and ops */ + v->content = content; + v->ops = ops; + + return(v); +} + +/* ---------------------------------------------------------------------------- + * Function to create a new serial vector + */ + +N_Vector N_VNew_Serial(long int length) +{ + N_Vector v; + realtype *data; + + v = NULL; + v = N_VNewEmpty_Serial(length); + if (v == NULL) return(NULL); + + /* Create data */ + if (length > 0) { + + /* Allocate memory */ + data = NULL; + data = (realtype *) malloc(length * sizeof(realtype)); + if(data == NULL) { N_VDestroy_Serial(v); return(NULL); } + + /* Attach data */ + NV_OWN_DATA_S(v) = TRUE; + NV_DATA_S(v) = data; + + } + + return(v); +} + +/* ---------------------------------------------------------------------------- + * Function to create a serial N_Vector with user data component + */ + +N_Vector N_VMake_Serial(long int length, realtype *v_data) +{ + N_Vector v; + + v = NULL; + v = N_VNewEmpty_Serial(length); + if (v == NULL) return(NULL); + + if (length > 0) { + /* Attach data */ + NV_OWN_DATA_S(v) = FALSE; + NV_DATA_S(v) = v_data; + } + + return(v); +} + +/* ---------------------------------------------------------------------------- + * Function to create an array of new serial vectors. + */ + +N_Vector *N_VCloneVectorArray_Serial(int count, N_Vector w) +{ + N_Vector *vs; + int j; + + if (count <= 0) return(NULL); + + vs = NULL; + vs = (N_Vector *) malloc(count * sizeof(N_Vector)); + if(vs == NULL) return(NULL); + + for (j = 0; j < count; j++) { + vs[j] = NULL; + vs[j] = N_VClone_Serial(w); + if (vs[j] == NULL) { + N_VDestroyVectorArray_Serial(vs, j-1); + return(NULL); + } + } + + return(vs); +} + +/* ---------------------------------------------------------------------------- + * Function to create an array of new serial vectors with NULL data array. + */ + +N_Vector *N_VCloneVectorArrayEmpty_Serial(int count, N_Vector w) +{ + N_Vector *vs; + int j; + + if (count <= 0) return(NULL); + + vs = NULL; + vs = (N_Vector *) malloc(count * sizeof(N_Vector)); + if(vs == NULL) return(NULL); + + for (j = 0; j < count; j++) { + vs[j] = NULL; + vs[j] = N_VCloneEmpty_Serial(w); + if (vs[j] == NULL) { + N_VDestroyVectorArray_Serial(vs, j-1); + return(NULL); + } + } + + return(vs); +} + +/* ---------------------------------------------------------------------------- + * Function to free an array created with N_VCloneVectorArray_Serial + */ + +void N_VDestroyVectorArray_Serial(N_Vector *vs, int count) +{ + int j; + + for (j = 0; j < count; j++) N_VDestroy_Serial(vs[j]); + + free(vs); vs = NULL; + + return; +} + +/* ---------------------------------------------------------------------------- + * Function to print the a serial vector + */ + +void N_VPrint_Serial(N_Vector x) +{ + long int i, N; + realtype *xd; + + xd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + + for (i = 0; i < N; i++) { +#if defined(SUNDIALS_EXTENDED_PRECISION) + printf("%11.8Lg\n", xd[i]); +#elif defined(SUNDIALS_DOUBLE_PRECISION) + printf("%11.8lg\n", xd[i]); +#else + printf("%11.8g\n", xd[i]); +#endif + } + printf("\n"); + + return; +} + +/* + * ----------------------------------------------------------------- + * implementation of vector operations + * ----------------------------------------------------------------- + */ + +N_Vector N_VCloneEmpty_Serial(N_Vector w) +{ + N_Vector v; + N_Vector_Ops ops; + N_VectorContent_Serial content; + + if (w == NULL) return(NULL); + + /* Create vector */ + v = NULL; + v = (N_Vector) malloc(sizeof *v); + if (v == NULL) return(NULL); + + /* Create vector operation structure */ + ops = NULL; + ops = (N_Vector_Ops) malloc(sizeof(struct _generic_N_Vector_Ops)); + if (ops == NULL) { free(v); return(NULL); } + + ops->nvclone = w->ops->nvclone; + ops->nvcloneempty = w->ops->nvcloneempty; + ops->nvdestroy = w->ops->nvdestroy; + ops->nvspace = w->ops->nvspace; + ops->nvgetarraypointer = w->ops->nvgetarraypointer; + ops->nvsetarraypointer = w->ops->nvsetarraypointer; + ops->nvlinearsum = w->ops->nvlinearsum; + ops->nvconst = w->ops->nvconst; + ops->nvprod = w->ops->nvprod; + ops->nvdiv = w->ops->nvdiv; + ops->nvscale = w->ops->nvscale; + ops->nvabs = w->ops->nvabs; + ops->nvinv = w->ops->nvinv; + ops->nvaddconst = w->ops->nvaddconst; + ops->nvdotprod = w->ops->nvdotprod; + ops->nvmaxnorm = w->ops->nvmaxnorm; + ops->nvwrmsnormmask = w->ops->nvwrmsnormmask; + ops->nvwrmsnorm = w->ops->nvwrmsnorm; + ops->nvmin = w->ops->nvmin; + ops->nvwl2norm = w->ops->nvwl2norm; + ops->nvl1norm = w->ops->nvl1norm; + ops->nvcompare = w->ops->nvcompare; + ops->nvinvtest = w->ops->nvinvtest; + ops->nvconstrmask = w->ops->nvconstrmask; + ops->nvminquotient = w->ops->nvminquotient; + + /* Create content */ + content = NULL; + content = (N_VectorContent_Serial) malloc(sizeof(struct _N_VectorContent_Serial)); + if (content == NULL) { free(ops); free(v); return(NULL); } + + content->length = NV_LENGTH_S(w); + content->own_data = FALSE; + content->data = NULL; + + /* Attach content and ops */ + v->content = content; + v->ops = ops; + + return(v); +} + +N_Vector N_VClone_Serial(N_Vector w) +{ + N_Vector v; + realtype *data; + long int length; + + v = NULL; + v = N_VCloneEmpty_Serial(w); + if (v == NULL) return(NULL); + + length = NV_LENGTH_S(w); + + /* Create data */ + if (length > 0) { + + /* Allocate memory */ + data = NULL; + data = (realtype *) malloc(length * sizeof(realtype)); + if(data == NULL) { N_VDestroy_Serial(v); return(NULL); } + + /* Attach data */ + NV_OWN_DATA_S(v) = TRUE; + NV_DATA_S(v) = data; + + } + + return(v); +} + +void N_VDestroy_Serial(N_Vector v) +{ + if (NV_OWN_DATA_S(v) == TRUE) { + free(NV_DATA_S(v)); + NV_DATA_S(v) = NULL; + } + free(v->content); v->content = NULL; + free(v->ops); v->ops = NULL; + free(v); v = NULL; + + return; +} + +void N_VSpace_Serial(N_Vector v, long int *lrw, long int *liw) +{ + *lrw = NV_LENGTH_S(v); + *liw = 1; + + return; +} + +realtype *N_VGetArrayPointer_Serial(N_Vector v) +{ + return((realtype *) NV_DATA_S(v)); +} + +void N_VSetArrayPointer_Serial(realtype *v_data, N_Vector v) +{ + if (NV_LENGTH_S(v) > 0) NV_DATA_S(v) = v_data; + + return; +} + +void N_VLinearSum_Serial(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z) +{ + long int i, N; + realtype c, *xd, *yd, *zd; + N_Vector v1, v2; + booleantype test; + + xd = yd = zd = NULL; + + if ((b == ONE) && (z == y)) { /* BLAS usage: axpy y <- ax+y */ + Vaxpy_Serial(a,x,y); + return; + } + + if ((a == ONE) && (z == x)) { /* BLAS usage: axpy x <- by+x */ + Vaxpy_Serial(b,y,x); + return; + } + + /* Case: a == b == 1.0 */ + + if ((a == ONE) && (b == ONE)) { + VSum_Serial(x, y, z); + return; + } + + /* Cases: (1) a == 1.0, b = -1.0, (2) a == -1.0, b == 1.0 */ + + if ((test = ((a == ONE) && (b == -ONE))) || ((a == -ONE) && (b == ONE))) { + v1 = test ? y : x; + v2 = test ? x : y; + VDiff_Serial(v2, v1, z); + return; + } + + /* Cases: (1) a == 1.0, b == other or 0.0, (2) a == other or 0.0, b == 1.0 */ + /* if a or b is 0.0, then user should have called N_VScale */ + + if ((test = (a == ONE)) || (b == ONE)) { + c = test ? b : a; + v1 = test ? y : x; + v2 = test ? x : y; + VLin1_Serial(c, v1, v2, z); + return; + } + + /* Cases: (1) a == -1.0, b != 1.0, (2) a != 1.0, b == -1.0 */ + + if ((test = (a == -ONE)) || (b == -ONE)) { + c = test ? b : a; + v1 = test ? y : x; + v2 = test ? x : y; + VLin2_Serial(c, v1, v2, z); + return; + } + + /* Case: a == b */ + /* catches case both a and b are 0.0 - user should have called N_VConst */ + + if (a == b) { + VScaleSum_Serial(a, x, y, z); + return; + } + + /* Case: a == -b */ + + if (a == -b) { + VScaleDiff_Serial(a, x, y, z); + return; + } + + /* Do all cases not handled above: + (1) a == other, b == 0.0 - user should have called N_VScale + (2) a == 0.0, b == other - user should have called N_VScale + (3) a,b == other, a !=b, a != -b */ + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = (a*xd[i])+(b*yd[i]); + + return; +} + +void N_VConst_Serial(realtype c, N_Vector z) +{ + long int i, N; + realtype *zd; + + zd = NULL; + + N = NV_LENGTH_S(z); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) zd[i] = c; + + return; +} + +void N_VProd_Serial(N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]*yd[i]; + + return; +} + +void N_VDiv_Serial(N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]/yd[i]; + + return; +} + +void N_VScale_Serial(realtype c, N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + if (z == x) { /* BLAS usage: scale x <- cx */ + VScaleBy_Serial(c, x); + return; + } + + if (c == ONE) { + VCopy_Serial(x, z); + } else if (c == -ONE) { + VNeg_Serial(x, z); + } else { + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + zd = NV_DATA_S(z); + for (i = 0; i < N; i++) + zd[i] = c*xd[i]; + } + + return; +} + +void N_VAbs_Serial(N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = ABS(xd[i]); + + return; +} + +void N_VInv_Serial(N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = ONE/xd[i]; + + return; +} + +void N_VAddConst_Serial(N_Vector x, realtype b, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]+b; + + return; +} + +realtype N_VDotProd_Serial(N_Vector x, N_Vector y) +{ + long int i, N; + realtype sum, *xd, *yd; + + sum = ZERO; + xd = yd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + + for (i = 0; i < N; i++) + sum += xd[i]*yd[i]; + + return(sum); +} + +realtype N_VMaxNorm_Serial(N_Vector x) +{ + long int i, N; + realtype max, *xd; + + max = ZERO; + xd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + + for (i = 0; i < N; i++) { + if (ABS(xd[i]) > max) max = ABS(xd[i]); + } + + return(max); +} + +realtype N_VWrmsNorm_Serial(N_Vector x, N_Vector w) +{ + long int i, N; + realtype sum, prodi, *xd, *wd; + + sum = ZERO; + xd = wd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + wd = NV_DATA_S(w); + + for (i = 0; i < N; i++) { + prodi = xd[i]*wd[i]; + sum += SQR(prodi); + } + + return(RSqrt(sum/N)); +} + +realtype N_VWrmsNormMask_Serial(N_Vector x, N_Vector w, N_Vector id) +{ + long int i, N; + realtype sum, prodi, *xd, *wd, *idd; + + sum = ZERO; + xd = wd = idd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + wd = NV_DATA_S(w); + idd = NV_DATA_S(id); + + for (i = 0; i < N; i++) { + if (idd[i] > ZERO) { + prodi = xd[i]*wd[i]; + sum += SQR(prodi); + } + } + + return(RSqrt(sum / N)); +} + +realtype N_VMin_Serial(N_Vector x) +{ + long int i, N; + realtype min, *xd; + + xd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + + min = xd[0]; + + for (i = 1; i < N; i++) { + if (xd[i] < min) min = xd[i]; + } + + return(min); +} + +realtype N_VWL2Norm_Serial(N_Vector x, N_Vector w) +{ + long int i, N; + realtype sum, prodi, *xd, *wd; + + sum = ZERO; + xd = wd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + wd = NV_DATA_S(w); + + for (i = 0; i < N; i++) { + prodi = xd[i]*wd[i]; + sum += SQR(prodi); + } + + return(RSqrt(sum)); +} + +realtype N_VL1Norm_Serial(N_Vector x) +{ + long int i, N; + realtype sum, *xd; + + sum = ZERO; + xd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + + for (i = 0; i= c) ? ONE : ZERO; + } + + return; +} + +booleantype N_VInvTest_Serial(N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) { + if (xd[i] == ZERO) return(FALSE); + zd[i] = ONE/xd[i]; + } + + return(TRUE); +} + +booleantype N_VConstrMask_Serial(N_Vector c, N_Vector x, N_Vector m) +{ + long int i, N; + booleantype test; + realtype *cd, *xd, *md; + + cd = xd = md = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + cd = NV_DATA_S(c); + md = NV_DATA_S(m); + + test = TRUE; + + for (i = 0; i < N; i++) { + md[i] = ZERO; + if (cd[i] == ZERO) continue; + if (cd[i] > ONEPT5 || cd[i] < -ONEPT5) { + if ( xd[i]*cd[i] <= ZERO) { test = FALSE; md[i] = ONE; } + continue; + } + if ( cd[i] > HALF || cd[i] < -HALF) { + if (xd[i]*cd[i] < ZERO ) { test = FALSE; md[i] = ONE; } + } + } + + return(test); +} + +realtype N_VMinQuotient_Serial(N_Vector num, N_Vector denom) +{ + booleantype notEvenOnce; + long int i, N; + realtype *nd, *dd, min; + + nd = dd = NULL; + + N = NV_LENGTH_S(num); + nd = NV_DATA_S(num); + dd = NV_DATA_S(denom); + + notEvenOnce = TRUE; + min = BIG_REAL; + + for (i = 0; i < N; i++) { + if (dd[i] == ZERO) continue; + else { + if (!notEvenOnce) min = MIN(min, nd[i]/dd[i]); + else { + min = nd[i]/dd[i]; + notEvenOnce = FALSE; + } + } + } + + return(min); +} + +/* + * ----------------------------------------------------------------- + * private functions + * ----------------------------------------------------------------- + */ + +static void VCopy_Serial(N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]; + + return; +} + +static void VSum_Serial(N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]+yd[i]; + + return; +} + +static void VDiff_Serial(N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]-yd[i]; + + return; +} + +static void VNeg_Serial(N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = -xd[i]; + + return; +} + +static void VScaleSum_Serial(realtype c, N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = c*(xd[i]+yd[i]); + + return; +} + +static void VScaleDiff_Serial(realtype c, N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = c*(xd[i]-yd[i]); + + return; +} + +static void VLin1_Serial(realtype a, N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = (a*xd[i])+yd[i]; + + return; +} + +static void VLin2_Serial(realtype a, N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = (a*xd[i])-yd[i]; + + return; +} + +static void Vaxpy_Serial(realtype a, N_Vector x, N_Vector y) +{ + long int i, N; + realtype *xd, *yd; + + xd = yd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + + if (a == ONE) { + for (i = 0; i < N; i++) + yd[i] += xd[i]; + return; + } + + if (a == -ONE) { + for (i = 0; i < N; i++) + yd[i] -= xd[i]; + return; + } + + for (i = 0; i < N; i++) + yd[i] += a*xd[i]; + + return; +} + +static void VScaleBy_Serial(realtype a, N_Vector x) +{ + long int i, N; + realtype *xd; + + xd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + + for (i = 0; i < N; i++) + xd[i] *= a; + + return; +} diff --git a/odemex/Parser/CVode/cv_src/src/sundials/CMakeLists.txt b/odemex/Parser/CVode/cv_src/src/sundials/CMakeLists.txt new file mode 100644 index 0000000..459dcdf --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/sundials/CMakeLists.txt @@ -0,0 +1,45 @@ +# --------------------------------------------------------------- +# $Revision: 1.4 $ +# $Date: 2009/02/17 02:52:53 $ +# --------------------------------------------------------------- +# Programmer: Radu Serban @ LLNL +# --------------------------------------------------------------- +# Copyright (c) 2007, The Regents of the University of California. +# Produced at the Lawrence Livermore National Laboratory. +# All rights reserved. +# For details, see the LICENSE file. +# --------------------------------------------------------------- +# CMakeLists.txt file for the generic SUNDIALS modules + +# From here we only install the generic SUNDIALS headers. +# The implementations themselves are incorporated in the individual SUNDIALS solver libraries. + +INSTALL(CODE "MESSAGE(\"\nInstall shared components\n\")") + +# Add variable sundials_HEADERS with the exported SUNDIALS header files +SET(sundials_HEADERS + sundials_band.h + sundials_dense.h + sundials_direct.h + sundials_iterative.h + sundials_math.h + sundials_nvector.h + sundials_fnvector.h + sundials_spbcgs.h + sundials_spgmr.h + sundials_sptfqmr.h + sundials_types.h + ) + +# Add prefix with complete path to the SUNDIALS header files +ADD_PREFIX(${sundials_SOURCE_DIR}/include/sundials/ sundials_HEADERS) + +# Install the SUNDIALS header files +INSTALL(FILES ${sundials_HEADERS} DESTINATION include/sundials) + +# If Blas/Lapack support was enabled, install the Lapack interface headers +IF(LAPACK_FOUND) + SET(sundials_BL_HEADERS sundials_lapack.h) + ADD_PREFIX(${sundials_SOURCE_DIR}/include/sundials/ sundials_BL_HEADERS) + INSTALL(FILES ${sundials_BL_HEADERS} DESTINATION include/sundials) +ENDIF(LAPACK_FOUND) diff --git a/odemex/Parser/CVode/cv_src/src/sundials/Makefile.in b/odemex/Parser/CVode/cv_src/src/sundials/Makefile.in new file mode 100644 index 0000000..f750ba1 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/sundials/Makefile.in @@ -0,0 +1,137 @@ +# ----------------------------------------------------------------- +# $Revision: 1.12 $ +# $Date: 2009/02/17 02:52:53 $ +# ----------------------------------------------------------------- +# Programmer(s): Radu Serban and Aaron Collier @ LLNL +# ----------------------------------------------------------------- +# Copyright (c) 2002, The Regents of the University of California. +# Produced at the Lawrence Livermore National Laboratory. +# All rights reserved. +# For details, see the LICENSE file. +# ----------------------------------------------------------------- +# Makefile for SHARED module +# +# @configure_input@ +# ----------------------------------------------------------------- + +SHELL = @SHELL@ + +srcdir = @srcdir@ +builddir = @builddir@ +abs_builddir = @abs_builddir@ +top_builddir = @top_builddir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +includedir = @includedir@ +libdir = @libdir@ +bindir = @bindir@ + +INSTALL = @INSTALL@ +INSTALL_PROG = @INSTALL_PROGRAM@ +INSTALL_HEADER = @INSTALL_DATA@ + +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ + +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CC = @CC@ +CFLAGS = @CFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ + +LAPACK_ENABLED = @LAPACK_ENABLED@ + +top_srcdir = $(srcdir)/../.. + +INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include + +SHARED_SRC_FILES = sundials_direct.c sundials_band.c sundials_dense.c sundials_iterative.c sundials_math.c sundials_nvector.c sundials_spgmr.c sundials_spbcgs.c sundials_sptfqmr.c + +SHARED_OBJ_FILES = $(SHARED_SRC_FILES:.c=.o) + +SHARED_LIB_FILES = $(SHARED_SRC_FILES:.c=.lo) + +mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs +rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs + +# ---------------------------------------------------------------------------------------------------------------------- + + +all: + @if test "X${LAPACK_ENABLED}" = "Xyes"; then \ + make lib_with_bl; \ + else \ + make lib_without_bl; \ + fi + +lib_without_bl: $(SHARED_LIB_FILES) + +lib_with_bl: $(SHARED_LIB_FILES) + +install: + $(mkinstalldirs) $(includedir)/sundials + $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_direct.h $(includedir)/sundials/ + $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_band.h $(includedir)/sundials/ + $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_dense.h $(includedir)/sundials/ + $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_iterative.h $(includedir)/sundials/ + $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_spgmr.h $(includedir)/sundials/ + $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_spbcgs.h $(includedir)/sundials/ + $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_sptfqmr.h $(includedir)/sundials/ + $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_math.h $(includedir)/sundials/ + $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_types.h $(includedir)/sundials/ + $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_nvector.h $(includedir)/sundials/ + $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_fnvector.h $(includedir)/sundials/ + $(INSTALL_HEADER) $(top_builddir)/include/sundials/sundials_config.h $(includedir)/sundials/ + @if test "X${LAPACK_ENABLED}" = "Xyes"; then \ + $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_lapack.h $(includedir)/sundials/ ; \ + fi + +uninstall: + rm -f $(includedir)/sundials/sundials_direct.h + rm -f $(includedir)/sundials/sundials_band.h + rm -f $(includedir)/sundials/sundials_dense.h + rm -f $(includedir)/sundials/sundials_lapack.h + rm -f $(includedir)/sundials/sundials_iterative.h + rm -f $(includedir)/sundials/sundials_spgmr.h + rm -f $(includedir)/sundials/sundials_spbcgs.h + rm -f $(includedir)/sundials/sundials_sptfqmr.h + rm -f $(includedir)/sundials/sundials_math.h + rm -f $(includedir)/sundials/sundials_types.h + rm -f $(includedir)/sundials/sundials_nvector.h + rm -f $(includedir)/sundials/sundials_fnvector.h + rm -f $(includedir)/sundials/sundials_config.h + $(rminstalldirs) $(includedir)/sundials + +clean: + rm -f $(SHARED_LIB_FILES) + rm -f $(SHARED_OBJ_FILES) + rm -rf .libs + +distclean: clean + rm -f $(top_builddir)/include/sundials/sundials_config.h + rm -f Makefile + +sundials_direct.lo: $(srcdir)/sundials_direct.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/sundials_direct.c +sundials_band.lo: $(srcdir)/sundials_band.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/sundials_band.c +sundials_dense.lo: $(srcdir)/sundials_dense.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/sundials_dense.c +sundials_iterative.lo: $(srcdir)/sundials_iterative.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/sundials_iterative.c +sundials_spgmr.lo: $(srcdir)/sundials_spgmr.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/sundials_spgmr.c +sundials_spbcgs.lo: $(srcdir)/sundials_spbcgs.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/sundials_spbcgs.c +sundials_sptfqmr.lo: $(srcdir)/sundials_sptfqmr.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/sundials_sptfqmr.c +sundials_math.lo: $(srcdir)/sundials_math.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/sundials_math.c +sundials_nvector.lo: $(srcdir)/sundials_nvector.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/sundials_nvector.c + +libtool: $(top_builddir)/$(LIBTOOL_DEPS) + @cd ${top_builddir} ; \ + ${SHELL} ./config.status --recheck ; \ + cd ${abs_builddir} diff --git a/odemex/Parser/CVode/cv_src/src/sundials/README b/odemex/Parser/CVode/cv_src/src/sundials/README new file mode 100644 index 0000000..d73e577 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/sundials/README @@ -0,0 +1,201 @@ + SUNDIALS + Shared Module + Release 2.4.0, January 2008 + + +The family of solvers referred to as SUNDIALS consists of solvers +CVODE (ODE), CVODES (ODE with sensitivity analysis capabilities), +IDA (DAE), IDAS (DAE with sensitivity analysis capabilities), and +KINSOL (for nonlinear algebraic systems). + +The various solvers of this family share many subordinate modules contained +in this module: +- generic NVECTOR module +- generic linear solver modules (band, dense, lapack, spgmr, bcg, tfqmr) +- definitions of SUNDIALS types (realtype, booleantype) +- common math functions (RpowerI, RPowerR, RSqrt, RAbs,...) + + +A. Documentation +---------------- +All shared submodules are fully described in the user documentation for any of +the SUNDIALS solvers [1-5]. A PDF file for the user guide for a particular solver +is available in the solver's subdirectory under doc/. + + +B. Installation +--------------- + +For basic installation instructions see the file /sundials/INSTALL_NOTES. +For complete installation instructions see any of the user guides. + + +C. References +------------- + +[1] A. C. Hindmarsh and R. Serban, "User Documentation for CVODE v2.4.0," + LLLNL technical report UCRL-MA-208108, November 2004. + +[2] A. C. Hindmarsh and R. Serban, "User Documentation for CVODES v2.4.0," + LLNL technical report UCRL-MA-208111, November 2004. + +[3] A. C. Hindmarsh and R. Serban, "User Documentation for IDA v2.4.0," + LLNL technical report UCRL-MA-208112, November 2004. + +[4] R. Serban and C. Petra, "User Documentation for IDAS v1.0.0," + LLNL technical report UCRL-SM-234051, August 2007. + +[5] A. M. Collier, A. C. Hindmarsh, R. Serban,and C. S. Woodward, "User + Documentation for KINSOL v2.4.0," LLNL technical report UCRL-MA-208116, + November 2004. + + +D. Releases +----------- + +v. 2.4.0 - Jan. 2008 +v. 2.3.0 - Nov. 2006 +v. 2.2.0 - Mar. 2006 +v. 2.1.1 - May. 2005 +v. 2.1.0 - Apr. 2005 +v. 2.0.2 - Mar. 2005 +v. 2.0.1 - Jan. 2005 +v. 2.0 - Dec. 2004 +v. 1.0 - Jul. 2002 (first SUNDIALS release) +v. 0.0 - Mar. 2002 + + +E. Revision History +------------------- + +v. 2.3.0 (Nov. 2006) ---> v. 2.4.0 (Jan. 2008) +--------------------------------------------------------- + +- New features + - added a new generic linear solver module based on Blas + Lapack + for both dense and banded matrices. + +- Changes to user interface + - common functionality for all direct linear solvers (dense, band, and + the new Lapack solver) has been collected into the DLS (Direct Linear + Solver) module, implemented in the files sundials_direct.h and + sundials_direct.c (similar to the SPILS module for the iterative linear + solvers). + - in order to include the new Lapack-based linear solver, all dimensions + for the above linear solvers (problem sizes, bandwidths,... including + the underlying matrix data types) are now of type 'int' (and not 'long int'). + + +v. 2.2.0 (Mar. 2006) ---> v. 2.3.0 (Nov. 2006) +---------------------------------------------- + +- Changes to the user interface + - modified sundials_dense and sundials_smalldense to work with + rectangular m by n matrices (m <= n). + +- Changes related to the build system + - reorganized source tree + - exported header files are installed in solver-specific subdirectories + of ${includedir} + - sundialsTB is distributed only as part of the SUNDIALS tarball + +v. 2.1.1 (May 2005) ---> v. 2.2.0 (Mar. 2006) +---------------------------------------------- + +- New features + - added SPBCG (scaled preconditioned Bi-CGStab) linear solver module + - added SPTFQMR (scaled preconditioned TFQMR) linear solver module + +- Changes related to the build system + - updated configure script and Makefiles for Fortran examples to avoid C++ + compiler errors (now use CC and MPICC to link only if necessary) + - SUNDIALS shared header files are installed under a 'sundials' subdirectory + of the install include directory + - the shared object files are now linked into each SUNDIALS library rather + than into a separate libsundials_shared library + +- Changes to the user interface + - added prefix 'sundials_' to all shared header files + +v. 2.1.0 (Apr. 2005) ---> v. 2.1.1 (May.2005) +---------------------------------------------- + +- Changes to data structures + - added N_VCloneEmpty to global vector operations table + +v. 2.0.2 (Mar. 2005) ---> v. 2.1.0 (Apr. 2005) +---------------------------------------------- + +- none + +v. 2.0.1 (Jan. 2005) ---> v. 2.0.2 (Mar. 2005) +---------------------------------------------- + +- Changes related to the build system + - fixed autoconf-related bug to allow configuration with the PGI Fortran compiler + - modified to use customized detection of the Fortran name mangling scheme + (autoconf's AC_F77_WRAPPERS routine is problematic on some platforms) + - added --with-mpi-flags as a configure option to allow user to specify + MPI-specific flags + - updated Makefiles for Fortran examples to avoid C++ compiler errors (now use + CC and MPICC to link) + +v. 2.0 (Dec. 2004) ---> v. 2.0.1 (Jan. 2005) +-------------------------------------------- + +- Changes related to the build system + - changed order of compiler directives in header files to avoid compilation + errors when using a C++ compiler. + +v. 1.0 (Jul. 2002) ---> v. 2.0 (Dec. 2004) +------------------------------------------ + +- Changes to the generic NVECTOR module + - removed machEnv, redefined table of vector operations (now contained + in the N_Vector structure itself). + - all SUNDIALS functions create new N_Vector variables through cloning, using + an N_Vector passed by the user as a template. + - a particular NVECTOR implementation is supposed to provide user-callable + constructor and destructor functions. + - removed from structure of vector operations the following functions: + N_VNew, N_VNew_S, N_VFree, N_VFree_S, N_VMake, N_VDispose, N_VGetData, + N_VSetData, N_VConstrProdPos, and N_VOneMask. + - added in structure of vector operations the following functions: + N_VClone, N_VDestroy, N_VSpace, N_VGetArrayPointer, N_VSetArrayPointer, + and N_VWrmsNormMask. + - Note that nvec_ser and nvec_par are now separate modules outside the + shared SUNDIALS module. + +- Changes to the generic linear solvers + - in SPGMR, added a dummy N_Vector argument to be used as a template + for cloning. + - in SPGMR, removed N (problem dimension) from argument list of SpgmrMalloc. + - iterative.{c,h} replace iterativ.{c,h} + - modified constant names in iterative.h (preconditioner types are prefixed + with 'PREC_'). + - changed numerical values for MODIFIED_GS (from 0 to 1) and CLASSICAL_GS + (from 1 to 2). + +- Changes to sundialsmath submodule + - replaced internal routine for estimation of unit roundoff with definition + of unit roundoff from float.h + - modified functions to call appropriate math routines given the precision + level specified by the user. + +- Changes to sundialstypes submodule + - removed type 'integertype'. + - added definitions for 'BIG_REAL', 'SMALL_REAL', and 'UNIT_ROUNDOFF' using + values from float.h based on the precision. + - changed definition of macro RCONST to depend on precision. + +v 0.0 (Mar. 2002) ---> v. 1.0 (Jul. 2002) +----------------------------------------- + +20020321 Defined and implemented generic NVECTOR module, and separate serial/ + parallel NVECTOR modules, including serial/parallel F/C interfaces. + Modified dense and band backsolve routines to take real* type for + RHS and solution vector. +20020329 Named the DenseMat, BandMat, and SpgmrMemRec structures. +20020626 Changed type names to realtype, integertype, booleantype. + Renamed llnltypes and llnlmath files. + diff --git a/odemex/Parser/CVode/cv_src/src/sundials/sundials_band.c b/odemex/Parser/CVode/cv_src/src/sundials/sundials_band.c new file mode 100644 index 0000000..fa4eea7 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/sundials/sundials_band.c @@ -0,0 +1,235 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2009/02/17 02:42:29 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for a generic BAND linear + * solver package. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +#define ROW(i,j,smu) (i-j+smu) + +/* + * ----------------------------------------------------- + * Functions working on DlsMat + * ----------------------------------------------------- + */ + +int BandGBTRF(DlsMat A, int *p) +{ + return(bandGBTRF(A->cols, A->M, A->mu, A->ml, A->s_mu, p)); +} + +void BandGBTRS(DlsMat A, int *p, realtype *b) +{ + bandGBTRS(A->cols, A->M, A->s_mu, A->ml, p, b); +} + +void BandCopy(DlsMat A, DlsMat B, int copymu, int copyml) +{ + bandCopy(A->cols, B->cols, A->M, A->s_mu, B->s_mu, copymu, copyml); +} + +void BandScale(realtype c, DlsMat A) +{ + bandScale(c, A->cols, A->M, A->mu, A->ml, A->s_mu); +} + +/* + * ----------------------------------------------------- + * Functions working on realtype** + * ----------------------------------------------------- + */ + +int bandGBTRF(realtype **a, int n, int mu, int ml, int smu, int *p) +{ + int c, r, num_rows; + int i, j, k, l, storage_l, storage_k, last_col_k, last_row_k; + realtype *a_c, *col_k, *diag_k, *sub_diag_k, *col_j, *kptr, *jptr; + realtype max, temp, mult, a_kj; + booleantype swap; + + /* zero out the first smu - mu rows of the rectangular array a */ + + num_rows = smu - mu; + if (num_rows > 0) { + for (c=0; c < n; c++) { + a_c = a[c]; + for (r=0; r < num_rows; r++) { + a_c[r] = ZERO; + } + } + } + + /* k = elimination step number */ + + for (k=0; k < n-1; k++, p++) { + + col_k = a[k]; + diag_k = col_k + smu; + sub_diag_k = diag_k + 1; + last_row_k = MIN(n-1,k+ml); + + /* find l = pivot row number */ + + l=k; + max = ABS(*diag_k); + for (i=k+1, kptr=sub_diag_k; i <= last_row_k; i++, kptr++) { + if (ABS(*kptr) > max) { + l=i; + max = ABS(*kptr); + } + } + storage_l = ROW(l, k, smu); + *p = l; + + /* check for zero pivot element */ + + if (col_k[storage_l] == ZERO) return(k+1); + + /* swap a(l,k) and a(k,k) if necessary */ + + if ( (swap = (l != k) )) { + temp = col_k[storage_l]; + col_k[storage_l] = *diag_k; + *diag_k = temp; + } + + /* Scale the elements below the diagonal in */ + /* column k by -1.0 / a(k,k). After the above swap, */ + /* a(k,k) holds the pivot element. This scaling */ + /* stores the pivot row multipliers -a(i,k)/a(k,k) */ + /* in a(i,k), i=k+1, ..., MIN(n-1,k+ml). */ + + mult = -ONE / (*diag_k); + for (i=k+1, kptr = sub_diag_k; i <= last_row_k; i++, kptr++) + (*kptr) *= mult; + + /* row_i = row_i - [a(i,k)/a(k,k)] row_k, i=k+1, ..., MIN(n-1,k+ml) */ + /* row k is the pivot row after swapping with row l. */ + /* The computation is done one column at a time, */ + /* column j=k+1, ..., MIN(k+smu,n-1). */ + + last_col_k = MIN(k+smu,n-1); + for (j=k+1; j <= last_col_k; j++) { + + col_j = a[j]; + storage_l = ROW(l,j,smu); + storage_k = ROW(k,j,smu); + a_kj = col_j[storage_l]; + + /* Swap the elements a(k,j) and a(k,l) if l!=k. */ + + if (swap) { + col_j[storage_l] = col_j[storage_k]; + col_j[storage_k] = a_kj; + } + + /* a(i,j) = a(i,j) - [a(i,k)/a(k,k)]*a(k,j) */ + /* a_kj = a(k,j), *kptr = - a(i,k)/a(k,k), *jptr = a(i,j) */ + + if (a_kj != ZERO) { + for (i=k+1, kptr=sub_diag_k, jptr=col_j+ROW(k+1,j,smu); + i <= last_row_k; + i++, kptr++, jptr++) + (*jptr) += a_kj * (*kptr); + } + } + } + + /* set the last pivot row to be n-1 and check for a zero pivot */ + + *p = n-1; + if (a[n-1][smu] == ZERO) return(n); + + /* return 0 to indicate success */ + + return(0); +} + +void bandGBTRS(realtype **a, int n, int smu, int ml, int *p, realtype *b) +{ + int k, l, i, first_row_k, last_row_k; + realtype mult, *diag_k; + + /* Solve Ly = Pb, store solution y in b */ + + for (k=0; k < n-1; k++) { + l = p[k]; + mult = b[l]; + if (l != k) { + b[l] = b[k]; + b[k] = mult; + } + diag_k = a[k]+smu; + last_row_k = MIN(n-1,k+ml); + for (i=k+1; i <= last_row_k; i++) + b[i] += mult * diag_k[i-k]; + } + + /* Solve Ux = y, store solution x in b */ + + for (k=n-1; k >= 0; k--) { + diag_k = a[k]+smu; + first_row_k = MAX(0,k-smu); + b[k] /= (*diag_k); + mult = -b[k]; + for (i=first_row_k; i <= k-1; i++) + b[i] += mult*diag_k[i-k]; + } +} + +void bandCopy(realtype **a, realtype **b, int n, int a_smu, int b_smu, + int copymu, int copyml) +{ + int i, j, copySize; + realtype *a_col_j, *b_col_j; + + copySize = copymu + copyml + 1; + + for (j=0; j < n; j++) { + a_col_j = a[j]+a_smu-copymu; + b_col_j = b[j]+b_smu-copymu; + for (i=0; i < copySize; i++) + b_col_j[i] = a_col_j[i]; + } +} + +void bandScale(realtype c, realtype **a, int n, int mu, int ml, int smu) +{ + int i, j, colSize; + realtype *col_j; + + colSize = mu + ml + 1; + + for(j=0; j < n; j++) { + col_j = a[j]+smu-mu; + for (i=0; i < colSize; i++) + col_j[i] *= c; + } +} + +void bandAddIdentity(realtype **a, int n, int smu) +{ + int j; + + for(j=0; j < n; j++) + a[j][smu] += ONE; +} diff --git a/odemex/Parser/CVode/cv_src/src/sundials/sundials_dense.c b/odemex/Parser/CVode/cv_src/src/sundials/sundials_dense.c new file mode 100644 index 0000000..104e070 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/sundials/sundials_dense.c @@ -0,0 +1,373 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2009/02/17 02:42:29 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for a generic package of dense + * matrix operations. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) +#define TWO RCONST(2.0) + +/* + * ----------------------------------------------------- + * Functions working on DlsMat + * ----------------------------------------------------- + */ + +int DenseGETRF(DlsMat A, int *p) +{ + return(denseGETRF(A->cols, A->M, A->N, p)); +} + +void DenseGETRS(DlsMat A, int *p, realtype *b) +{ + denseGETRS(A->cols, A->N, p, b); +} + +int DensePOTRF(DlsMat A) +{ + return(densePOTRF(A->cols, A->M)); +} + +void DensePOTRS(DlsMat A, realtype *b) +{ + densePOTRS(A->cols, A->M, b); +} + +int DenseGEQRF(DlsMat A, realtype *beta, realtype *wrk) +{ + return(denseGEQRF(A->cols, A->M, A->N, beta, wrk)); +} + +int DenseORMQR(DlsMat A, realtype *beta, realtype *vn, realtype *vm, realtype *wrk) +{ + return(denseORMQR(A->cols, A->M, A->N, beta, vn, vm, wrk)); +} + +void DenseCopy(DlsMat A, DlsMat B) +{ + denseCopy(A->cols, B->cols, A->M, A->N); +} + +void DenseScale(realtype c, DlsMat A) +{ + denseScale(c, A->cols, A->M, A->N); +} + +int denseGETRF(realtype **a, int m, int n, int *p) +{ + int i, j, k, l; + realtype *col_j, *col_k; + realtype temp, mult, a_kj; + + /* k-th elimination step number */ + for (k=0; k < n; k++) { + + col_k = a[k]; + + /* find l = pivot row number */ + l=k; + for (i=k+1; i < m; i++) + if (ABS(col_k[i]) > ABS(col_k[l])) l=i; + p[k] = l; + + /* check for zero pivot element */ + if (col_k[l] == ZERO) return(k+1); + + /* swap a(k,1:n) and a(l,1:n) if necessary */ + if ( l!= k ) { + for (i=0; i 0; k--) { + col_k = a[k]; + b[k] /= col_k[k]; + for (i=0; i0) { + for(i=j; i=0; i--) { + col_i = a[i]; + for (j=i+1; j= n) + * using Householder reflections. + * + * On exit, the elements on and above the diagonal of A contain the n by n + * upper triangular matrix R; the elements below the diagonal, with the array beta, + * represent the orthogonal matrix Q as a product of elementary reflectors . + * + * v (of length m) must be provided as workspace. + * + */ + +int denseGEQRF(realtype **a, int m, int n, realtype *beta, realtype *v) +{ + realtype ajj, s, mu, v1, v1_2; + realtype *col_j, *col_k; + int i, j, k; + + /* For each column...*/ + for(j=0; j= n. + * + * v (of length m) must be provided as workspace. + */ +int denseORMQR(realtype **a, int m, int n, realtype *beta, + realtype *vn, realtype *vm, realtype *v) +{ + realtype *col_j, s; + int i, j; + + /* Initialize vm */ + for(i=0; i=0; j--) { + + col_j = a[j]; + + v[0] = ONE; + s = vm[j]; + for(i=1; i +#include + +#include +#include + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +DlsMat NewDenseMat(int M, int N) +{ + DlsMat A; + int j; + + if ( (M <= 0) || (N <= 0) ) return(NULL); + + A = NULL; + A = (DlsMat) malloc(sizeof *A); + if (A==NULL) return (NULL); + + A->data = (realtype *) malloc(M * N * sizeof(realtype)); + if (A->data == NULL) { + free(A); A = NULL; + return(NULL); + } + A->cols = (realtype **) malloc(N * sizeof(realtype *)); + if (A->cols == NULL) { + free(A->data); A->data = NULL; + free(A); A = NULL; + return(NULL); + } + + for (j=0; j < N; j++) A->cols[j] = A->data + j * M; + + A->M = M; + A->N = N; + A->ldim = M; + A->ldata = M*N; + + A->type = SUNDIALS_DENSE; + + return(A); +} + +realtype **newDenseMat(int m, int n) +{ + int j; + realtype **a; + + if ( (n <= 0) || (m <= 0) ) return(NULL); + + a = NULL; + a = (realtype **) malloc(n * sizeof(realtype *)); + if (a == NULL) return(NULL); + + a[0] = NULL; + a[0] = (realtype *) malloc(m * n * sizeof(realtype)); + if (a[0] == NULL) { + free(a); a = NULL; + return(NULL); + } + + for (j=1; j < n; j++) a[j] = a[0] + j * m; + + return(a); +} + + +DlsMat NewBandMat(int N, int mu, int ml, int smu) +{ + DlsMat A; + int j, colSize; + + if (N <= 0) return(NULL); + + A = NULL; + A = (DlsMat) malloc(sizeof *A); + if (A == NULL) return (NULL); + + colSize = smu + ml + 1; + A->data = NULL; + A->data = (realtype *) malloc(N * colSize * sizeof(realtype)); + if (A->data == NULL) { + free(A); A = NULL; + return(NULL); + } + + A->cols = NULL; + A->cols = (realtype **) malloc(N * sizeof(realtype *)); + if (A->cols == NULL) { + free(A->data); + free(A); A = NULL; + return(NULL); + } + + for (j=0; j < N; j++) A->cols[j] = A->data + j * colSize; + + A->M = N; + A->N = N; + A->mu = mu; + A->ml = ml; + A->s_mu = smu; + A->ldim = colSize; + A->ldata = N * colSize; + + A->type = SUNDIALS_BAND; + + return(A); +} + +realtype **newBandMat(int n, int smu, int ml) +{ + realtype **a; + int j, colSize; + + if (n <= 0) return(NULL); + + a = NULL; + a = (realtype **) malloc(n * sizeof(realtype *)); + if (a == NULL) return(NULL); + + colSize = smu + ml + 1; + a[0] = NULL; + a[0] = (realtype *) malloc(n * colSize * sizeof(realtype)); + if (a[0] == NULL) { + free(a); a = NULL; + return(NULL); + } + + for (j=1; j < n; j++) a[j] = a[0] + j * colSize; + + return(a); +} + +void DestroyMat(DlsMat A) +{ + free(A->data); A->data = NULL; + free(A->cols); + free(A); A = NULL; +} + +void destroyMat(realtype **a) +{ + free(a[0]); a[0] = NULL; + free(a); a = NULL; +} + +int *NewIntArray(int N) +{ + int *vec; + + if (N <= 0) return(NULL); + + vec = NULL; + vec = (int *) malloc(N * sizeof(int)); + + return(vec); +} + +int *newIntArray(int n) +{ + int *v; + + if (n <= 0) return(NULL); + + v = NULL; + v = (int *) malloc(n * sizeof(int)); + + return(v); +} + +realtype *NewRealArray(int N) +{ + realtype *vec; + + if (N <= 0) return(NULL); + + vec = NULL; + vec = (realtype *) malloc(N * sizeof(realtype)); + + return(vec); +} + +realtype *newRealArray(int m) +{ + realtype *v; + + if (m <= 0) return(NULL); + + v = NULL; + v = (realtype *) malloc(m * sizeof(realtype)); + + return(v); +} + +void DestroyArray(void *V) +{ + free(V); + V = NULL; +} + +void destroyArray(void *v) +{ + free(v); + v = NULL; +} + + +void AddIdentity(DlsMat A) +{ + int i; + + switch (A->type) { + + case SUNDIALS_DENSE: + for (i=0; iN; i++) A->cols[i][i] += ONE; + break; + + case SUNDIALS_BAND: + for (i=0; iM; i++) A->cols[i][A->s_mu] += ONE; + break; + + } + +} + + +void SetToZero(DlsMat A) +{ + int i, j, colSize; + realtype *col_j; + + switch (A->type) { + + case SUNDIALS_DENSE: + + for (j=0; jN; j++) { + col_j = A->cols[j]; + for (i=0; iM; i++) + col_j[i] = ZERO; + } + + break; + + case SUNDIALS_BAND: + + colSize = A->mu + A->ml + 1; + for (j=0; jM; j++) { + col_j = A->cols[j] + A->s_mu - A->mu; + for (i=0; itype) { + + case SUNDIALS_DENSE: + + printf("\n"); + for (i=0; i < A->M; i++) { + for (j=0; j < A->N; j++) { +#if defined(SUNDIALS_EXTENDED_PRECISION) + printf("%12Lg ", DENSE_ELEM(A,i,j)); +#elif defined(SUNDIALS_DOUBLE_PRECISION) + printf("%12lg ", DENSE_ELEM(A,i,j)); +#else + printf("%12g ", DENSE_ELEM(A,i,j)); +#endif + } + printf("\n"); + } + printf("\n"); + + break; + + case SUNDIALS_BAND: + + a = A->cols; + printf("\n"); + for (i=0; i < A->N; i++) { + start = MAX(0,i-A->ml); + finish = MIN(A->N-1,i+A->mu); + for (j=0; j < start; j++) printf("%12s ",""); + for (j=start; j <= finish; j++) { +#if defined(SUNDIALS_EXTENDED_PRECISION) + printf("%12Lg ", a[j][i-j+A->s_mu]); +#elif defined(SUNDIALS_DOUBLE_PRECISION) + printf("%12lg ", a[j][i-j+A->s_mu]); +#else + printf("%12g ", a[j][i-j+A->s_mu]); +#endif + } + printf("\n"); + } + printf("\n"); + + break; + + } + +} + + diff --git a/odemex/Parser/CVode/cv_src/src/sundials/sundials_iterative.c b/odemex/Parser/CVode/cv_src/src/sundials/sundials_iterative.c new file mode 100644 index 0000000..41ccc17 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/sundials/sundials_iterative.c @@ -0,0 +1,288 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.1 $ + * $Date: 2006/07/05 15:32:38 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the iterative.h header + * file. It contains the implementation of functions that may be + * useful for many different iterative solvers of A x = b. + * ----------------------------------------------------------------- + */ + +#include + +#include +#include + +#define FACTOR RCONST(1000.0) +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +/* + * ----------------------------------------------------------------- + * Function : ModifiedGS + * ----------------------------------------------------------------- + * This implementation of ModifiedGS is a slight modification of a + * previous modified Gram-Schmidt routine (called mgs) written by + * Milo Dorr. + * ----------------------------------------------------------------- + */ + +int ModifiedGS(N_Vector *v, realtype **h, int k, int p, + realtype *new_vk_norm) +{ + int i, k_minus_1, i0; + realtype new_norm_2, new_product, vk_norm, temp; + + vk_norm = RSqrt(N_VDotProd(v[k],v[k])); + k_minus_1 = k - 1; + i0 = MAX(k-p, 0); + + /* Perform modified Gram-Schmidt */ + + for (i=i0; i < k; i++) { + h[i][k_minus_1] = N_VDotProd(v[i], v[k]); + N_VLinearSum(ONE, v[k], -h[i][k_minus_1], v[i], v[k]); + } + + /* Compute the norm of the new vector at v[k] */ + + *new_vk_norm = RSqrt(N_VDotProd(v[k], v[k])); + + /* If the norm of the new vector at v[k] is less than + FACTOR (== 1000) times unit roundoff times the norm of the + input vector v[k], then the vector will be reorthogonalized + in order to ensure that nonorthogonality is not being masked + by a very small vector length. */ + + temp = FACTOR * vk_norm; + if ((temp + (*new_vk_norm)) != temp) return(0); + + new_norm_2 = ZERO; + + for (i=i0; i < k; i++) { + new_product = N_VDotProd(v[i], v[k]); + temp = FACTOR * h[i][k_minus_1]; + if ((temp + new_product) == temp) continue; + h[i][k_minus_1] += new_product; + N_VLinearSum(ONE, v[k],-new_product, v[i], v[k]); + new_norm_2 += SQR(new_product); + } + + if (new_norm_2 != ZERO) { + new_product = SQR(*new_vk_norm) - new_norm_2; + *new_vk_norm = (new_product > ZERO) ? RSqrt(new_product) : ZERO; + } + + return(0); +} + +/* + * ----------------------------------------------------------------- + * Function : ClassicalGS + * ----------------------------------------------------------------- + * This implementation of ClassicalGS was contributed by Homer Walker + * and Peter Brown. + * ----------------------------------------------------------------- + */ + +int ClassicalGS(N_Vector *v, realtype **h, int k, int p, + realtype *new_vk_norm, N_Vector temp, realtype *s) +{ + int i, k_minus_1, i0; + realtype vk_norm; + + k_minus_1 = k - 1; + + /* Perform Classical Gram-Schmidt */ + + vk_norm = RSqrt(N_VDotProd(v[k], v[k])); + + i0 = MAX(k-p, 0); + for (i=i0; i < k; i++) { + h[i][k_minus_1] = N_VDotProd(v[i], v[k]); + } + + for (i=i0; i < k; i++) { + N_VLinearSum(ONE, v[k], -h[i][k_minus_1], v[i], v[k]); + } + + /* Compute the norm of the new vector at v[k] */ + + *new_vk_norm = RSqrt(N_VDotProd(v[k], v[k])); + + /* Reorthogonalize if necessary */ + + if ((FACTOR * (*new_vk_norm)) < vk_norm) { + + for (i=i0; i < k; i++) { + s[i] = N_VDotProd(v[i], v[k]); + } + + if (i0 < k) { + N_VScale(s[i0], v[i0], temp); + h[i0][k_minus_1] += s[i0]; + } + for (i=i0+1; i < k; i++) { + N_VLinearSum(s[i], v[i], ONE, temp, temp); + h[i][k_minus_1] += s[i]; + } + N_VLinearSum(ONE, v[k], -ONE, temp, v[k]); + + *new_vk_norm = RSqrt(N_VDotProd(v[k],v[k])); + } + + return(0); +} + +/* + * ----------------------------------------------------------------- + * Function : QRfact + * ----------------------------------------------------------------- + * This implementation of QRfact is a slight modification of a + * previous routine (called qrfact) written by Milo Dorr. + * ----------------------------------------------------------------- + */ + +int QRfact(int n, realtype **h, realtype *q, int job) +{ + realtype c, s, temp1, temp2, temp3; + int i, j, k, q_ptr, n_minus_1, code=0; + + switch (job) { + case 0: + + /* Compute a new factorization of H */ + + code = 0; + for (k=0; k < n; k++) { + + /* Multiply column k by the previous k-1 Givens rotations */ + + for (j=0; j < k-1; j++) { + i = 2*j; + temp1 = h[j][k]; + temp2 = h[j+1][k]; + c = q[i]; + s = q[i+1]; + h[j][k] = c*temp1 - s*temp2; + h[j+1][k] = s*temp1 + c*temp2; + } + + /* Compute the Givens rotation components c and s */ + + q_ptr = 2*k; + temp1 = h[k][k]; + temp2 = h[k+1][k]; + if( temp2 == ZERO) { + c = ONE; + s = ZERO; + } else if (ABS(temp2) >= ABS(temp1)) { + temp3 = temp1/temp2; + s = -ONE/RSqrt(ONE+SQR(temp3)); + c = -s*temp3; + } else { + temp3 = temp2/temp1; + c = ONE/RSqrt(ONE+SQR(temp3)); + s = -c*temp3; + } + q[q_ptr] = c; + q[q_ptr+1] = s; + if( (h[k][k] = c*temp1 - s*temp2) == ZERO) code = k+1; + } + break; + + default: + + /* Update the factored H to which a new column has been added */ + + n_minus_1 = n - 1; + code = 0; + + /* Multiply the new column by the previous n-1 Givens rotations */ + + for (k=0; k < n_minus_1; k++) { + i = 2*k; + temp1 = h[k][n_minus_1]; + temp2 = h[k+1][n_minus_1]; + c = q[i]; + s = q[i+1]; + h[k][n_minus_1] = c*temp1 - s*temp2; + h[k+1][n_minus_1] = s*temp1 + c*temp2; + } + + /* Compute new Givens rotation and multiply it times the last two + entries in the new column of H. Note that the second entry of + this product will be 0, so it is not necessary to compute it. */ + + temp1 = h[n_minus_1][n_minus_1]; + temp2 = h[n][n_minus_1]; + if (temp2 == ZERO) { + c = ONE; + s = ZERO; + } else if (ABS(temp2) >= ABS(temp1)) { + temp3 = temp1/temp2; + s = -ONE/RSqrt(ONE+SQR(temp3)); + c = -s*temp3; + } else { + temp3 = temp2/temp1; + c = ONE/RSqrt(ONE+SQR(temp3)); + s = -c*temp3; + } + q_ptr = 2*n_minus_1; + q[q_ptr] = c; + q[q_ptr+1] = s; + if ((h[n_minus_1][n_minus_1] = c*temp1 - s*temp2) == ZERO) + code = n; + } + + return (code); +} + +/* + * ----------------------------------------------------------------- + * Function : QRsol + * ----------------------------------------------------------------- + * This implementation of QRsol is a slight modification of a + * previous routine (called qrsol) written by Milo Dorr. + * ----------------------------------------------------------------- + */ + +int QRsol(int n, realtype **h, realtype *q, realtype *b) +{ + realtype c, s, temp1, temp2; + int i, k, q_ptr, code=0; + + /* Compute Q*b */ + + for (k=0; k < n; k++) { + q_ptr = 2*k; + c = q[q_ptr]; + s = q[q_ptr+1]; + temp1 = b[k]; + temp2 = b[k+1]; + b[k] = c*temp1 - s*temp2; + b[k+1] = s*temp1 + c*temp2; + } + + /* Solve R*x = Q*b */ + + for (k=n-1; k >= 0; k--) { + if (h[k][k] == ZERO) { + code = k + 1; + break; + } + b[k] /= h[k][k]; + for (i=0; i < k; i++) b[i] -= b[k]*h[i][k]; + } + + return (code); +} diff --git a/odemex/Parser/CVode/cv_src/src/sundials/sundials_math.c b/odemex/Parser/CVode/cv_src/src/sundials/sundials_math.c new file mode 100644 index 0000000..8bc9d59 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/sundials/sundials_math.c @@ -0,0 +1,94 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.1 $ + * $Date: 2006/07/05 15:32:38 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for a simple C-language math + * library. + * ----------------------------------------------------------------- + */ + +#include +#include +#include + +#include + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +realtype RPowerI(realtype base, int exponent) +{ + int i, expt; + realtype prod; + + prod = ONE; + expt = abs(exponent); + for(i = 1; i <= expt; i++) prod *= base; + if (exponent < 0) prod = ONE/prod; + return(prod); +} + +realtype RPowerR(realtype base, realtype exponent) +{ + if (base <= ZERO) return(ZERO); + +#if defined(SUNDIALS_USE_GENERIC_MATH) + return((realtype) pow((double) base, (double) exponent)); +#elif defined(SUNDIALS_DOUBLE_PRECISION) + return(pow(base, exponent)); +#elif defined(SUNDIALS_SINGLE_PRECISION) + return(powf(base, exponent)); +#elif defined(SUNDIALS_EXTENDED_PRECISION) + return(powl(base, exponent)); +#endif +} + +realtype RSqrt(realtype x) +{ + if (x <= ZERO) return(ZERO); + +#if defined(SUNDIALS_USE_GENERIC_MATH) + return((realtype) sqrt((double) x)); +#elif defined(SUNDIALS_DOUBLE_PRECISION) + return(sqrt(x)); +#elif defined(SUNDIALS_SINGLE_PRECISION) + return(sqrtf(x)); +#elif defined(SUNDIALS_EXTENDED_PRECISION) + return(sqrtl(x)); +#endif +} + +realtype RAbs(realtype x) +{ +#if defined(SUNDIALS_USE_GENERIC_MATH) + return((realtype) fabs((double) x)); +#elif defined(SUNDIALS_DOUBLE_PRECISION) + return(fabs(x)); +#elif defined(SUNDIALS_SINGLE_PRECISION) + return(fabsf(x)); +#elif defined(SUNDIALS_EXTENDED_PRECISION) + return(fabsl(x)); +#endif +} + +realtype RExp(realtype x) +{ +#if defined(SUNDIALS_USE_GENERIC_MATH) + return((realtype) exp((double) x)); +#elif defined(SUNDIALS_DOUBLE_PRECISION) + return(exp(x)); +#elif defined(SUNDIALS_SINGLE_PRECISION) + return(expf(x)); +#elif defined(SUNDIALS_EXTENDED_PRECISION) + return(expl(x)); +#endif +} diff --git a/odemex/Parser/CVode/cv_src/src/sundials/sundials_nvector.c b/odemex/Parser/CVode/cv_src/src/sundials/sundials_nvector.c new file mode 100644 index 0000000..e8e1b83 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/sundials/sundials_nvector.c @@ -0,0 +1,233 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.3 $ + * $Date: 2007/04/06 20:33:30 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for a generic NVECTOR package. + * It contains the implementation of the N_Vector operations listed + * in nvector.h. + * ----------------------------------------------------------------- + */ + +#include + +#include + +/* + * ----------------------------------------------------------------- + * Functions in the 'ops' structure + * ----------------------------------------------------------------- + */ + +N_Vector N_VClone(N_Vector w) +{ + N_Vector v = NULL; + v = w->ops->nvclone(w); + return(v); +} + +N_Vector N_VCloneEmpty(N_Vector w) +{ + N_Vector v = NULL; + v = w->ops->nvcloneempty(w); + return(v); +} + +void N_VDestroy(N_Vector v) +{ + if (v==NULL) return; + v->ops->nvdestroy(v); + return; +} + +void N_VSpace(N_Vector v, long int *lrw, long int *liw) +{ + v->ops->nvspace(v, lrw, liw); + return; +} + +realtype *N_VGetArrayPointer(N_Vector v) +{ + return((realtype *) v->ops->nvgetarraypointer(v)); +} + +void N_VSetArrayPointer(realtype *v_data, N_Vector v) +{ + v->ops->nvsetarraypointer(v_data, v); + return; +} + +void N_VLinearSum(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z) +{ + z->ops->nvlinearsum(a, x, b, y, z); + return; +} + +void N_VConst(realtype c, N_Vector z) +{ + z->ops->nvconst(c, z); + return; +} + +void N_VProd(N_Vector x, N_Vector y, N_Vector z) +{ + z->ops->nvprod(x, y, z); + return; +} + +void N_VDiv(N_Vector x, N_Vector y, N_Vector z) +{ + z->ops->nvdiv(x, y, z); + return; +} + +void N_VScale(realtype c, N_Vector x, N_Vector z) +{ + z->ops->nvscale(c, x, z); + return; +} + +void N_VAbs(N_Vector x, N_Vector z) +{ + z->ops->nvabs(x, z); + return; +} + +void N_VInv(N_Vector x, N_Vector z) +{ + z->ops->nvinv(x, z); + return; +} + +void N_VAddConst(N_Vector x, realtype b, N_Vector z) +{ + z->ops->nvaddconst(x, b, z); + return; +} + +realtype N_VDotProd(N_Vector x, N_Vector y) +{ + return((realtype) y->ops->nvdotprod(x, y)); +} + +realtype N_VMaxNorm(N_Vector x) +{ + return((realtype) x->ops->nvmaxnorm(x)); +} + +realtype N_VWrmsNorm(N_Vector x, N_Vector w) +{ + return((realtype) x->ops->nvwrmsnorm(x, w)); +} + +realtype N_VWrmsNormMask(N_Vector x, N_Vector w, N_Vector id) +{ + return((realtype) x->ops->nvwrmsnormmask(x, w, id)); +} + +realtype N_VMin(N_Vector x) +{ + return((realtype) x->ops->nvmin(x)); +} + +realtype N_VWL2Norm(N_Vector x, N_Vector w) +{ + return((realtype) x->ops->nvwl2norm(x, w)); +} + +realtype N_VL1Norm(N_Vector x) +{ + return((realtype) x->ops->nvl1norm(x)); +} + +void N_VCompare(realtype c, N_Vector x, N_Vector z) +{ + z->ops->nvcompare(c, x, z); + return; +} + +booleantype N_VInvTest(N_Vector x, N_Vector z) +{ + return((booleantype) z->ops->nvinvtest(x, z)); +} + +booleantype N_VConstrMask(N_Vector c, N_Vector x, N_Vector m) +{ + return((booleantype) x->ops->nvconstrmask(c, x, m)); +} + +realtype N_VMinQuotient(N_Vector num, N_Vector denom) +{ + return((realtype) num->ops->nvminquotient(num, denom)); +} + +/* + * ----------------------------------------------------------------- + * Additional functions exported by the generic NVECTOR: + * N_VCloneEmptyVectorArray + * N_VCloneVectorArray + * N_VDestroyVectorArray + * ----------------------------------------------------------------- + */ + +N_Vector *N_VCloneEmptyVectorArray(int count, N_Vector w) +{ + N_Vector *vs = NULL; + int j; + + if (count <= 0) return(NULL); + + vs = (N_Vector *) malloc(count * sizeof(N_Vector)); + if(vs == NULL) return(NULL); + + for (j = 0; j < count; j++) { + vs[j] = N_VCloneEmpty(w); + if (vs[j] == NULL) { + N_VDestroyVectorArray(vs, j-1); + return(NULL); + } + } + + return(vs); +} + +N_Vector *N_VCloneVectorArray(int count, N_Vector w) +{ + N_Vector *vs = NULL; + int j; + + if (count <= 0) return(NULL); + + vs = (N_Vector *) malloc(count * sizeof(N_Vector)); + if(vs == NULL) return(NULL); + + for (j = 0; j < count; j++) { + vs[j] = N_VClone(w); + if (vs[j] == NULL) { + N_VDestroyVectorArray(vs, j-1); + return(NULL); + } + } + + return(vs); +} + +void N_VDestroyVectorArray(N_Vector *vs, int count) +{ + int j; + + if (vs==NULL) return; + + for (j = 0; j < count; j++) N_VDestroy(vs[j]); + + free(vs); vs = NULL; + + return; +} diff --git a/odemex/Parser/CVode/cv_src/src/sundials/sundials_spbcgs.c b/odemex/Parser/CVode/cv_src/src/sundials/sundials_spbcgs.c new file mode 100644 index 0000000..b73bf26 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/sundials/sundials_spbcgs.c @@ -0,0 +1,379 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2007/04/06 20:33:30 $ + * ----------------------------------------------------------------- + * Programmer(s): Peter Brown and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2004, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the scaled, preconditioned + * Bi-CGSTAB (SPBCG) iterative linear solver. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include + +/* + * ----------------------------------------------------------------- + * private constants + * ----------------------------------------------------------------- + */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +/* + * ----------------------------------------------------------------- + * Function : SpbcgMalloc + * ----------------------------------------------------------------- + */ + +SpbcgMem SpbcgMalloc(int l_max, N_Vector vec_tmpl) +{ + SpbcgMem mem; + N_Vector r_star, r, p, q, u, Ap, vtemp; + + /* Check the input parameters */ + + if (l_max <= 0) return(NULL); + + /* Get arrays to hold temporary vectors */ + + r_star = N_VClone(vec_tmpl); + if (r_star == NULL) { + return(NULL); + } + + r = N_VClone(vec_tmpl); + if (r == NULL) { + N_VDestroy(r_star); + return(NULL); + } + + p = N_VClone(vec_tmpl); + if (p == NULL) { + N_VDestroy(r_star); + N_VDestroy(r); + return(NULL); + } + + q = N_VClone(vec_tmpl); + if (q == NULL) { + N_VDestroy(r_star); + N_VDestroy(r); + N_VDestroy(p); + return(NULL); + } + + u = N_VClone(vec_tmpl); + if (u == NULL) { + N_VDestroy(r_star); + N_VDestroy(r); + N_VDestroy(p); + N_VDestroy(q); + return(NULL); + } + + Ap = N_VClone(vec_tmpl); + if (Ap == NULL) { + N_VDestroy(r_star); + N_VDestroy(r); + N_VDestroy(p); + N_VDestroy(q); + N_VDestroy(u); + return(NULL); + } + + vtemp = N_VClone(vec_tmpl); + if (vtemp == NULL) { + N_VDestroy(r_star); + N_VDestroy(r); + N_VDestroy(p); + N_VDestroy(q); + N_VDestroy(u); + N_VDestroy(Ap); + return(NULL); + } + + /* Get memory for an SpbcgMemRec containing SPBCG matrices and vectors */ + + mem = NULL; + mem = (SpbcgMem) malloc(sizeof(SpbcgMemRec)); + if (mem == NULL) { + N_VDestroy(r_star); + N_VDestroy(r); + N_VDestroy(p); + N_VDestroy(q); + N_VDestroy(u); + N_VDestroy(Ap); + N_VDestroy(vtemp); + return(NULL); + } + + /* Set the fields of mem */ + + mem->l_max = l_max; + mem->r_star = r_star; + mem->r = r; + mem->p = p; + mem->q = q; + mem->u = u; + mem->Ap = Ap; + mem->vtemp = vtemp; + + /* Return the pointer to SPBCG memory */ + + return(mem); +} + +/* + * ----------------------------------------------------------------- + * Function : SpbcgSolve + * ----------------------------------------------------------------- + */ + +int SpbcgSolve(SpbcgMem mem, void *A_data, N_Vector x, N_Vector b, + int pretype, realtype delta, void *P_data, N_Vector sx, + N_Vector sb, ATimesFn atimes, PSolveFn psolve, + realtype *res_norm, int *nli, int *nps) +{ + realtype alpha, beta, omega, omega_denom, beta_num, beta_denom, r_norm, rho; + N_Vector r_star, r, p, q, u, Ap, vtemp; + booleantype preOnLeft, preOnRight, scale_x, scale_b, converged; + int l, l_max, ier; + + if (mem == NULL) return(SPBCG_MEM_NULL); + + /* Make local copies of mem variables */ + + l_max = mem->l_max; + r_star = mem->r_star; + r = mem->r; + p = mem->p; + q = mem->q; + u = mem->u; + Ap = mem->Ap; + vtemp = mem->vtemp; + + *nli = *nps = 0; /* Initialize counters */ + converged = FALSE; /* Initialize converged flag */ + + if ((pretype != PREC_LEFT) && (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) pretype = PREC_NONE; + + preOnLeft = ((pretype == PREC_BOTH) || (pretype == PREC_LEFT)); + preOnRight = ((pretype == PREC_BOTH) || (pretype == PREC_RIGHT)); + + scale_x = (sx != NULL); + scale_b = (sb != NULL); + + /* Set r_star to initial (unscaled) residual r_0 = b - A*x_0 */ + + if (N_VDotProd(x, x) == ZERO) N_VScale(ONE, b, r_star); + else { + ier = atimes(A_data, x, r_star); + if (ier != 0) + return((ier < 0) ? SPBCG_ATIMES_FAIL_UNREC : SPBCG_ATIMES_FAIL_REC); + N_VLinearSum(ONE, b, -ONE, r_star, r_star); + } + + /* Apply left preconditioner and b-scaling to r_star = r_0 */ + + if (preOnLeft) { + ier = psolve(P_data, r_star, r, PREC_LEFT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC); + } + else N_VScale(ONE, r_star, r); + + if (scale_b) N_VProd(sb, r, r_star); + else N_VScale(ONE, r, r_star); + + /* Initialize beta_denom to the dot product of r0 with r0 */ + + beta_denom = N_VDotProd(r_star, r_star); + + /* Set r_norm to L2 norm of r_star = sb P1_inv r_0, and + return if small */ + + *res_norm = r_norm = rho = RSqrt(beta_denom); + if (r_norm <= delta) return(SPBCG_SUCCESS); + + /* Copy r_star to r and p */ + + N_VScale(ONE, r_star, r); + N_VScale(ONE, r_star, p); + + /* Begin main iteration loop */ + + for(l = 0; l < l_max; l++) { + + (*nli)++; + + /* Generate Ap = A-tilde p, where A-tilde = sb P1_inv A P2_inv sx_inv */ + + /* Apply x-scaling: vtemp = sx_inv p */ + + if (scale_x) N_VDiv(p, sx, vtemp); + else N_VScale(ONE, p, vtemp); + + /* Apply right preconditioner: vtemp = P2_inv sx_inv p */ + + if (preOnRight) { + N_VScale(ONE, vtemp, Ap); + ier = psolve(P_data, Ap, vtemp, PREC_RIGHT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC); + } + + /* Apply A: Ap = A P2_inv sx_inv p */ + + ier = atimes(A_data, vtemp, Ap ); + if (ier != 0) + return((ier < 0) ? SPBCG_ATIMES_FAIL_UNREC : SPBCG_ATIMES_FAIL_REC); + + /* Apply left preconditioner: vtemp = P1_inv A P2_inv sx_inv p */ + + if (preOnLeft) { + ier = psolve(P_data, Ap, vtemp, PREC_LEFT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC); + } + else N_VScale(ONE, Ap, vtemp); + + /* Apply b-scaling: Ap = sb P1_inv A P2_inv sx_inv p */ + + if (scale_b) N_VProd(sb, vtemp, Ap); + else N_VScale(ONE, vtemp, Ap); + + + /* Calculate alpha = / */ + + alpha = ((N_VDotProd(r, r_star) / N_VDotProd(Ap, r_star))); + + /* Update q = r - alpha*Ap = r - alpha*(sb P1_inv A P2_inv sx_inv p) */ + + N_VLinearSum(ONE, r, -alpha, Ap, q); + + /* Generate u = A-tilde q */ + + /* Apply x-scaling: vtemp = sx_inv q */ + + if (scale_x) N_VDiv(q, sx, vtemp); + else N_VScale(ONE, q, vtemp); + + /* Apply right preconditioner: vtemp = P2_inv sx_inv q */ + + if (preOnRight) { + N_VScale(ONE, vtemp, u); + ier = psolve(P_data, u, vtemp, PREC_RIGHT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC); + } + + /* Apply A: u = A P2_inv sx_inv u */ + + ier = atimes(A_data, vtemp, u ); + if (ier != 0) + return((ier < 0) ? SPBCG_ATIMES_FAIL_UNREC : SPBCG_ATIMES_FAIL_REC); + + /* Apply left preconditioner: vtemp = P1_inv A P2_inv sx_inv p */ + + if (preOnLeft) { + ier = psolve(P_data, u, vtemp, PREC_LEFT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC); + } + else N_VScale(ONE, u, vtemp); + + /* Apply b-scaling: u = sb P1_inv A P2_inv sx_inv u */ + + if (scale_b) N_VProd(sb, vtemp, u); + else N_VScale(ONE, vtemp, u); + + + /* Calculate omega = / */ + + omega_denom = N_VDotProd(u, u); + if (omega_denom == ZERO) omega_denom = ONE; + omega = (N_VDotProd(u, q) / omega_denom); + + /* Update x = x + alpha*p + omega*q */ + + N_VLinearSum(alpha, p, omega, q, vtemp); + N_VLinearSum(ONE, x, ONE, vtemp, x); + + /* Update the residual r = q - omega*u */ + + N_VLinearSum(ONE, q, -omega, u, r); + + /* Set rho = norm(r) and check convergence */ + + *res_norm = rho = RSqrt(N_VDotProd(r, r)); + if (rho <= delta) { + converged = TRUE; + break; + } + + /* Not yet converged, continue iteration */ + /* Update beta = / * alpha / omega */ + + beta_num = N_VDotProd(r, r_star); + beta = ((beta_num / beta_denom) * (alpha / omega)); + beta_denom = beta_num; + + /* Update p = r + beta*(p - omega*Ap) */ + + N_VLinearSum(ONE, p, -omega, Ap, vtemp); + N_VLinearSum(ONE, r, beta, vtemp, p); + + } + + /* Main loop finished */ + + if ((converged == TRUE) || (rho < r_norm)) { + + /* Apply the x-scaling and right preconditioner: x = P2_inv sx_inv x */ + + if (scale_x) N_VDiv(x, sx, x); + if (preOnRight) { + ier = psolve(P_data, x, vtemp, PREC_RIGHT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC); + N_VScale(ONE, vtemp, x); + } + + if (converged == TRUE) return(SPBCG_SUCCESS); + else return(SPBCG_RES_REDUCED); + } + else return(SPBCG_CONV_FAIL); +} + +/* + * ----------------------------------------------------------------- + * Function : SpbcgFree + * ----------------------------------------------------------------- + */ + +void SpbcgFree(SpbcgMem mem) +{ + + if (mem == NULL) return; + + N_VDestroy(mem->r_star); + N_VDestroy(mem->r); + N_VDestroy(mem->p); + N_VDestroy(mem->q); + N_VDestroy(mem->u); + N_VDestroy(mem->Ap); + N_VDestroy(mem->vtemp); + + free(mem); mem = NULL; +} diff --git a/odemex/Parser/CVode/cv_src/src/sundials/sundials_spgmr.c b/odemex/Parser/CVode/cv_src/src/sundials/sundials_spgmr.c new file mode 100644 index 0000000..7efd187 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/sundials/sundials_spgmr.c @@ -0,0 +1,458 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2007/04/06 20:33:30 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the scaled preconditioned + * GMRES (SPGMR) iterative linear solver. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include + +/* + * ----------------------------------------------------------------- + * private constants + * ----------------------------------------------------------------- + */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +/* + * ----------------------------------------------------------------- + * Function : SpgmrMalloc + * ----------------------------------------------------------------- + */ + +SpgmrMem SpgmrMalloc(int l_max, N_Vector vec_tmpl) +{ + SpgmrMem mem; + N_Vector *V, xcor, vtemp; + realtype **Hes, *givens, *yg; + int k, i; + + /* Check the input parameters. */ + + if (l_max <= 0) return(NULL); + + /* Get memory for the Krylov basis vectors V[0], ..., V[l_max]. */ + + V = N_VCloneVectorArray(l_max+1, vec_tmpl); + if (V == NULL) return(NULL); + + /* Get memory for the Hessenberg matrix Hes. */ + + Hes = NULL; + Hes = (realtype **) malloc((l_max+1)*sizeof(realtype *)); + if (Hes == NULL) { + N_VDestroyVectorArray(V, l_max+1); + return(NULL); + } + + for (k = 0; k <= l_max; k++) { + Hes[k] = NULL; + Hes[k] = (realtype *) malloc(l_max*sizeof(realtype)); + if (Hes[k] == NULL) { + for (i = 0; i < k; i++) {free(Hes[i]); Hes[i] = NULL;} + free(Hes); Hes = NULL; + N_VDestroyVectorArray(V, l_max+1); + return(NULL); + } + } + + /* Get memory for Givens rotation components. */ + + givens = NULL; + givens = (realtype *) malloc(2*l_max*sizeof(realtype)); + if (givens == NULL) { + for (i = 0; i <= l_max; i++) {free(Hes[i]); Hes[i] = NULL;} + free(Hes); Hes = NULL; + N_VDestroyVectorArray(V, l_max+1); + return(NULL); + } + + /* Get memory to hold the correction to z_tilde. */ + + xcor = N_VClone(vec_tmpl); + if (xcor == NULL) { + free(givens); givens = NULL; + for (i = 0; i <= l_max; i++) {free(Hes[i]); Hes[i] = NULL;} + free(Hes); Hes = NULL; + N_VDestroyVectorArray(V, l_max+1); + return(NULL); + } + + /* Get memory to hold SPGMR y and g vectors. */ + + yg = NULL; + yg = (realtype *) malloc((l_max+1)*sizeof(realtype)); + if (yg == NULL) { + N_VDestroy(xcor); + free(givens); givens = NULL; + for (i = 0; i <= l_max; i++) {free(Hes[i]); Hes[i] = NULL;} + free(Hes); Hes = NULL; + N_VDestroyVectorArray(V, l_max+1); + return(NULL); + } + + /* Get an array to hold a temporary vector. */ + + vtemp = N_VClone(vec_tmpl); + if (vtemp == NULL) { + free(yg); yg = NULL; + N_VDestroy(xcor); + free(givens); givens = NULL; + for (i = 0; i <= l_max; i++) {free(Hes[i]); Hes[i] = NULL;} + free(Hes); Hes = NULL; + N_VDestroyVectorArray(V, l_max+1); + return(NULL); + } + + /* Get memory for an SpgmrMemRec containing SPGMR matrices and vectors. */ + + mem = NULL; + mem = (SpgmrMem) malloc(sizeof(SpgmrMemRec)); + if (mem == NULL) { + N_VDestroy(vtemp); + free(yg); yg = NULL; + N_VDestroy(xcor); + free(givens); givens = NULL; + for (i = 0; i <= l_max; i++) {free(Hes[i]); Hes[i] = NULL;} + free(Hes); Hes = NULL; + N_VDestroyVectorArray(V, l_max+1); + return(NULL); + } + + /* Set the fields of mem. */ + + mem->l_max = l_max; + mem->V = V; + mem->Hes = Hes; + mem->givens = givens; + mem->xcor = xcor; + mem->yg = yg; + mem->vtemp = vtemp; + + /* Return the pointer to SPGMR memory. */ + + return(mem); +} + +/* + * ----------------------------------------------------------------- + * Function : SpgmrSolve + * ----------------------------------------------------------------- + */ + +int SpgmrSolve(SpgmrMem mem, void *A_data, N_Vector x, N_Vector b, + int pretype, int gstype, realtype delta, int max_restarts, + void *P_data, N_Vector s1, N_Vector s2, ATimesFn atimes, + PSolveFn psolve, realtype *res_norm, int *nli, int *nps) +{ + N_Vector *V, xcor, vtemp; + realtype **Hes, *givens, *yg; + realtype beta, rotation_product, r_norm, s_product, rho; + booleantype preOnLeft, preOnRight, scale2, scale1, converged; + int i, j, k, l, l_plus_1, l_max, krydim, ier, ntries; + + if (mem == NULL) return(SPGMR_MEM_NULL); + + /* Initialize some variables */ + + l_plus_1 = 0; + krydim = 0; + + /* Make local copies of mem variables. */ + + l_max = mem->l_max; + V = mem->V; + Hes = mem->Hes; + givens = mem->givens; + xcor = mem->xcor; + yg = mem->yg; + vtemp = mem->vtemp; + + *nli = *nps = 0; /* Initialize counters */ + converged = FALSE; /* Initialize converged flag */ + + if (max_restarts < 0) max_restarts = 0; + + if ((pretype != PREC_LEFT) && (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) + pretype = PREC_NONE; + + preOnLeft = ((pretype == PREC_LEFT) || (pretype == PREC_BOTH)); + preOnRight = ((pretype == PREC_RIGHT) || (pretype == PREC_BOTH)); + scale1 = (s1 != NULL); + scale2 = (s2 != NULL); + + /* Set vtemp and V[0] to initial (unscaled) residual r_0 = b - A*x_0. */ + + if (N_VDotProd(x, x) == ZERO) { + N_VScale(ONE, b, vtemp); + } else { + ier = atimes(A_data, x, vtemp); + if (ier != 0) + return((ier < 0) ? SPGMR_ATIMES_FAIL_UNREC : SPGMR_ATIMES_FAIL_REC); + N_VLinearSum(ONE, b, -ONE, vtemp, vtemp); + } + N_VScale(ONE, vtemp, V[0]); + + /* Apply left preconditioner and left scaling to V[0] = r_0. */ + + if (preOnLeft) { + ier = psolve(P_data, V[0], vtemp, PREC_LEFT); + (*nps)++; + if (ier != 0) + return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC); + } else { + N_VScale(ONE, V[0], vtemp); + } + + if (scale1) { + N_VProd(s1, vtemp, V[0]); + } else { + N_VScale(ONE, vtemp, V[0]); + } + + /* Set r_norm = beta to L2 norm of V[0] = s1 P1_inv r_0, and + return if small. */ + + *res_norm = r_norm = beta = RSqrt(N_VDotProd(V[0], V[0])); + if (r_norm <= delta) + return(SPGMR_SUCCESS); + + /* Initialize rho to avoid compiler warning message */ + + rho = beta; + + /* Set xcor = 0. */ + + N_VConst(ZERO, xcor); + + + /* Begin outer iterations: up to (max_restarts + 1) attempts. */ + + for (ntries = 0; ntries <= max_restarts; ntries++) { + + /* Initialize the Hessenberg matrix Hes and Givens rotation + product. Normalize the initial vector V[0]. */ + + for (i = 0; i <= l_max; i++) + for (j = 0; j < l_max; j++) + Hes[i][j] = ZERO; + + rotation_product = ONE; + + N_VScale(ONE/r_norm, V[0], V[0]); + + /* Inner loop: generate Krylov sequence and Arnoldi basis. */ + + for (l = 0; l < l_max; l++) { + + (*nli)++; + + krydim = l_plus_1 = l + 1; + + /* Generate A-tilde V[l], where A-tilde = s1 P1_inv A P2_inv s2_inv. */ + + /* Apply right scaling: vtemp = s2_inv V[l]. */ + + if (scale2) N_VDiv(V[l], s2, vtemp); + else N_VScale(ONE, V[l], vtemp); + + /* Apply right preconditioner: vtemp = P2_inv s2_inv V[l]. */ + + if (preOnRight) { + N_VScale(ONE, vtemp, V[l_plus_1]); + ier = psolve(P_data, V[l_plus_1], vtemp, PREC_RIGHT); + (*nps)++; + if (ier != 0) + return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC); + } + + /* Apply A: V[l+1] = A P2_inv s2_inv V[l]. */ + + ier = atimes(A_data, vtemp, V[l_plus_1] ); + if (ier != 0) + return((ier < 0) ? SPGMR_ATIMES_FAIL_UNREC : SPGMR_ATIMES_FAIL_REC); + + /* Apply left preconditioning: vtemp = P1_inv A P2_inv s2_inv V[l]. */ + + if (preOnLeft) { + ier = psolve(P_data, V[l_plus_1], vtemp, PREC_LEFT); + (*nps)++; + if (ier != 0) + return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC); + } else { + N_VScale(ONE, V[l_plus_1], vtemp); + } + + /* Apply left scaling: V[l+1] = s1 P1_inv A P2_inv s2_inv V[l]. */ + + if (scale1) { + N_VProd(s1, vtemp, V[l_plus_1]); + } else { + N_VScale(ONE, vtemp, V[l_plus_1]); + } + + /* Orthogonalize V[l+1] against previous V[i]: V[l+1] = w_tilde. */ + + if (gstype == CLASSICAL_GS) { + if (ClassicalGS(V, Hes, l_plus_1, l_max, &(Hes[l_plus_1][l]), + vtemp, yg) != 0) + return(SPGMR_GS_FAIL); + } else { + if (ModifiedGS(V, Hes, l_plus_1, l_max, &(Hes[l_plus_1][l])) != 0) + return(SPGMR_GS_FAIL); + } + + /* Update the QR factorization of Hes. */ + + if(QRfact(krydim, Hes, givens, l) != 0 ) + return(SPGMR_QRFACT_FAIL); + + /* Update residual norm estimate; break if convergence test passes. */ + + rotation_product *= givens[2*l+1]; + *res_norm = rho = ABS(rotation_product*r_norm); + + if (rho <= delta) { converged = TRUE; break; } + + /* Normalize V[l+1] with norm value from the Gram-Schmidt routine. */ + + N_VScale(ONE/Hes[l_plus_1][l], V[l_plus_1], V[l_plus_1]); + } + + /* Inner loop is done. Compute the new correction vector xcor. */ + + /* Construct g, then solve for y. */ + + yg[0] = r_norm; + for (i = 1; i <= krydim; i++) yg[i]=ZERO; + if (QRsol(krydim, Hes, givens, yg) != 0) + return(SPGMR_QRSOL_FAIL); + + /* Add correction vector V_l y to xcor. */ + + for (k = 0; k < krydim; k++) + N_VLinearSum(yg[k], V[k], ONE, xcor, xcor); + + /* If converged, construct the final solution vector x and return. */ + + if (converged) { + + /* Apply right scaling and right precond.: vtemp = P2_inv s2_inv xcor. */ + + if (scale2) N_VDiv(xcor, s2, xcor); + if (preOnRight) { + ier = psolve(P_data, xcor, vtemp, PREC_RIGHT); + (*nps)++; + if (ier != 0) + return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC); + } else { + N_VScale(ONE, xcor, vtemp); + } + + /* Add vtemp to initial x to get final solution x, and return */ + + N_VLinearSum(ONE, x, ONE, vtemp, x); + + return(SPGMR_SUCCESS); + } + + /* Not yet converged; if allowed, prepare for restart. */ + + if (ntries == max_restarts) break; + + /* Construct last column of Q in yg. */ + + s_product = ONE; + for (i = krydim; i > 0; i--) { + yg[i] = s_product*givens[2*i-2]; + s_product *= givens[2*i-1]; + } + yg[0] = s_product; + + /* Scale r_norm and yg. */ + r_norm *= s_product; + for (i = 0; i <= krydim; i++) + yg[i] *= r_norm; + r_norm = ABS(r_norm); + + /* Multiply yg by V_(krydim+1) to get last residual vector; restart. */ + N_VScale(yg[0], V[0], V[0]); + for (k = 1; k <= krydim; k++) + N_VLinearSum(yg[k], V[k], ONE, V[0], V[0]); + + } + + /* Failed to converge, even after allowed restarts. + If the residual norm was reduced below its initial value, compute + and return x anyway. Otherwise return failure flag. */ + + if (rho < beta) { + + /* Apply right scaling and right precond.: vtemp = P2_inv s2_inv xcor. */ + + if (scale2) N_VDiv(xcor, s2, xcor); + if (preOnRight) { + ier = psolve(P_data, xcor, vtemp, PREC_RIGHT); + (*nps)++; + if (ier != 0) + return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC); + } else { + N_VScale(ONE, xcor, vtemp); + } + + /* Add vtemp to initial x to get final solution x, and return. */ + + N_VLinearSum(ONE, x, ONE, vtemp, x); + + return(SPGMR_RES_REDUCED); + } + + return(SPGMR_CONV_FAIL); +} + +/* + * ----------------------------------------------------------------- + * Function : SpgmrFree + * ----------------------------------------------------------------- + */ + +void SpgmrFree(SpgmrMem mem) +{ + int i, l_max; + realtype **Hes, *givens, *yg; + + if (mem == NULL) return; + + l_max = mem->l_max; + Hes = mem->Hes; + givens = mem->givens; + yg = mem->yg; + + for (i = 0; i <= l_max; i++) {free(Hes[i]); Hes[i] = NULL;} + free(Hes); Hes = NULL; + free(mem->givens); givens = NULL; + free(mem->yg); yg = NULL; + + N_VDestroyVectorArray(mem->V, l_max+1); + N_VDestroy(mem->xcor); + N_VDestroy(mem->vtemp); + + free(mem); mem = NULL; +} diff --git a/odemex/Parser/CVode/cv_src/src/sundials/sundials_sptfqmr.c b/odemex/Parser/CVode/cv_src/src/sundials/sundials_sptfqmr.c new file mode 100644 index 0000000..626ca00 --- /dev/null +++ b/odemex/Parser/CVode/cv_src/src/sundials/sundials_sptfqmr.c @@ -0,0 +1,516 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2007/04/06 20:33:30 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the scaled preconditioned + * Transpose-Free Quasi-Minimal Residual (SPTFQMR) linear solver. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include + +/* + * ----------------------------------------------------------------- + * private constants + * ----------------------------------------------------------------- + */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +/* + * ----------------------------------------------------------------- + * Function : SptfqmrMalloc + * ----------------------------------------------------------------- + */ + +SptfqmrMem SptfqmrMalloc(int l_max, N_Vector vec_tmpl) +{ + SptfqmrMem mem; + N_Vector *r; + N_Vector q, d, v, p, u; + N_Vector r_star, vtemp1, vtemp2, vtemp3; + + /* Check the input parameters */ + if ((l_max <= 0) || (vec_tmpl == NULL)) return(NULL); + + /* Allocate space for vectors */ + + r_star = N_VClone(vec_tmpl); + if (r_star == NULL) return(NULL); + + q = N_VClone(vec_tmpl); + if (q == NULL) { + N_VDestroy(r_star); + return(NULL); + } + + d = N_VClone(vec_tmpl); + if (d == NULL) { + N_VDestroy(r_star); + N_VDestroy(q); + return(NULL); + } + + v = N_VClone(vec_tmpl); + if (v == NULL) { + N_VDestroy(r_star); + N_VDestroy(q); + N_VDestroy(d); + return(NULL); + } + + p = N_VClone(vec_tmpl); + if (p == NULL) { + N_VDestroy(r_star); + N_VDestroy(q); + N_VDestroy(d); + N_VDestroy(v); + return(NULL); + } + + r = N_VCloneVectorArray(2, vec_tmpl); + if (r == NULL) { + N_VDestroy(r_star); + N_VDestroy(q); + N_VDestroy(d); + N_VDestroy(v); + N_VDestroy(p); + return(NULL); + } + + u = N_VClone(vec_tmpl); + if (u == NULL) { + N_VDestroy(r_star); + N_VDestroy(q); + N_VDestroy(d); + N_VDestroy(v); + N_VDestroy(p); + N_VDestroyVectorArray(r, 2); + return(NULL); + } + + vtemp1 = N_VClone(vec_tmpl); + if (vtemp1 == NULL) { + N_VDestroy(r_star); + N_VDestroy(q); + N_VDestroy(d); + N_VDestroy(v); + N_VDestroy(p); + N_VDestroyVectorArray(r, 2); + N_VDestroy(u); + return(NULL); + } + + vtemp2 = N_VClone(vec_tmpl); + if (vtemp2 == NULL) { + N_VDestroy(r_star); + N_VDestroy(q); + N_VDestroy(d); + N_VDestroy(v); + N_VDestroy(p); + N_VDestroyVectorArray(r, 2); + N_VDestroy(u); + N_VDestroy(vtemp1); + return(NULL); + } + + vtemp3 = N_VClone(vec_tmpl); + if (vtemp3 == NULL) { + N_VDestroy(r_star); + N_VDestroy(q); + N_VDestroy(d); + N_VDestroy(v); + N_VDestroy(p); + N_VDestroyVectorArray(r, 2); + N_VDestroy(u); + N_VDestroy(vtemp1); + N_VDestroy(vtemp2); + return(NULL); + } + + /* Allocate memory for SptfqmrMemRec */ + mem = NULL; + mem = (SptfqmrMem) malloc(sizeof(SptfqmrMemRec)); + if (mem == NULL) { + N_VDestroy(r_star); + N_VDestroy(q); + N_VDestroy(d); + N_VDestroy(v); + N_VDestroy(p); + N_VDestroyVectorArray(r, 2); + N_VDestroy(u); + N_VDestroy(vtemp1); + N_VDestroy(vtemp2); + N_VDestroy(vtemp3); + return(NULL); + } + + /* Intialize SptfqmrMemRec data structure */ + mem->l_max = l_max; + mem->r_star = r_star; + mem->q = q; + mem->d = d; + mem->v = v; + mem->p = p; + mem->r = r; + mem->u = u; + mem->vtemp1 = vtemp1; + mem->vtemp2 = vtemp2; + mem->vtemp3 = vtemp3; + + /* Return pointer to SPTFQMR memory block */ + return(mem); +} + +#define l_max (mem->l_max) +#define r_star (mem->r_star) +#define q_ (mem->q) +#define d_ (mem->d) +#define v_ (mem->v) +#define p_ (mem->p) +#define r_ (mem->r) +#define u_ (mem->u) +#define vtemp1 (mem->vtemp1) +#define vtemp2 (mem->vtemp2) +#define vtemp3 (mem->vtemp3) + +/* + * ----------------------------------------------------------------- + * Function : SptfqmrSolve + * ----------------------------------------------------------------- + */ + +int SptfqmrSolve(SptfqmrMem mem, void *A_data, N_Vector x, N_Vector b, + int pretype, realtype delta, void *P_data, N_Vector sx, + N_Vector sb, ATimesFn atimes, PSolveFn psolve, + realtype *res_norm, int *nli, int *nps) +{ + realtype alpha, tau, eta, beta, c, sigma, v_bar, omega; + realtype rho[2]; + realtype r_init_norm, r_curr_norm; + realtype temp_val; + booleantype preOnLeft, preOnRight, scale_x, scale_b, converged; + booleantype b_ok; + int n, m, ier; + + /* Exit immediately if memory pointer is NULL */ + if (mem == NULL) return(SPTFQMR_MEM_NULL); + + temp_val = r_curr_norm = -ONE; /* Initialize to avoid compiler warnings */ + + *nli = *nps = 0; /* Initialize counters */ + converged = FALSE; /* Initialize convergence flag */ + b_ok = FALSE; + + if ((pretype != PREC_LEFT) && + (pretype != PREC_RIGHT) && + (pretype != PREC_BOTH)) pretype = PREC_NONE; + + preOnLeft = ((pretype == PREC_BOTH) || (pretype == PREC_LEFT)); + preOnRight = ((pretype == PREC_BOTH) || (pretype == PREC_RIGHT)); + + scale_x = (sx != NULL); + scale_b = (sb != NULL); + + /* Set r_star to initial (unscaled) residual r_star = r_0 = b - A*x_0 */ + /* NOTE: if x == 0 then just set residual to b and continue */ + if (N_VDotProd(x, x) == ZERO) N_VScale(ONE, b, r_star); + else { + ier = atimes(A_data, x, r_star); + if (ier != 0) + return((ier < 0) ? SPTFQMR_ATIMES_FAIL_UNREC : SPTFQMR_ATIMES_FAIL_REC); + N_VLinearSum(ONE, b, -ONE, r_star, r_star); + } + + /* Apply left preconditioner and b-scaling to r_star (or really just r_0) */ + if (preOnLeft) { + ier = psolve(P_data, r_star, vtemp1, PREC_LEFT); + (*nps)++; + if (ier != 0) + return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC); + } + else N_VScale(ONE, r_star, vtemp1); + if (scale_b) N_VProd(sb, vtemp1, r_star); + else N_VScale(ONE, vtemp1, r_star); + + /* Initialize rho[0] */ + /* NOTE: initialized here to reduce number of computations - avoid need + to compute r_star^T*r_star twice, and avoid needlessly squaring + values */ + rho[0] = N_VDotProd(r_star, r_star); + + /* Compute norm of initial residual (r_0) to see if we really need + to do anything */ + *res_norm = r_init_norm = RSqrt(rho[0]); + if (r_init_norm <= delta) return(SPTFQMR_SUCCESS); + + /* Set v_ = A*r_0 (preconditioned and scaled) */ + if (scale_x) N_VDiv(r_star, sx, vtemp1); + else N_VScale(ONE, r_star, vtemp1); + if (preOnRight) { + N_VScale(ONE, vtemp1, v_); + ier = psolve(P_data, v_, vtemp1, PREC_RIGHT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC); + } + ier = atimes(A_data, vtemp1, v_); + if (ier != 0) + return((ier < 0) ? SPTFQMR_ATIMES_FAIL_UNREC : SPTFQMR_ATIMES_FAIL_REC); + if (preOnLeft) { + ier = psolve(P_data, v_, vtemp1, PREC_LEFT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC); + } + else N_VScale(ONE, v_, vtemp1); + if (scale_b) N_VProd(sb, vtemp1, v_); + else N_VScale(ONE, vtemp1, v_); + + /* Initialize remaining variables */ + N_VScale(ONE, r_star, r_[0]); + N_VScale(ONE, r_star, u_); + N_VScale(ONE, r_star, p_); + N_VConst(ZERO, d_); + + tau = r_init_norm; + v_bar = eta = ZERO; + + /* START outer loop */ + for (n = 0; n < l_max; ++n) { + + /* Increment linear iteration counter */ + (*nli)++; + + /* sigma = r_star^T*v_ */ + sigma = N_VDotProd(r_star, v_); + + /* alpha = rho[0]/sigma */ + alpha = rho[0]/sigma; + + /* q_ = u_-alpha*v_ */ + N_VLinearSum(ONE, u_, -alpha, v_, q_); + + /* r_[1] = r_[0]-alpha*A*(u_+q_) */ + N_VLinearSum(ONE, u_, ONE, q_, r_[1]); + if (scale_x) N_VDiv(r_[1], sx, r_[1]); + if (preOnRight) { + N_VScale(ONE, r_[1], vtemp1); + ier = psolve(P_data, vtemp1, r_[1], PREC_RIGHT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC); + } + ier = atimes(A_data, r_[1], vtemp1); + if (ier != 0) + return((ier < 0) ? SPTFQMR_ATIMES_FAIL_UNREC : SPTFQMR_ATIMES_FAIL_REC); + if (preOnLeft) { + ier = psolve(P_data, vtemp1, r_[1], PREC_LEFT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC); + } + else N_VScale(ONE, vtemp1, r_[1]); + if (scale_b) N_VProd(sb, r_[1], vtemp1); + else N_VScale(ONE, r_[1], vtemp1); + N_VLinearSum(ONE, r_[0], -alpha, vtemp1, r_[1]); + + /* START inner loop */ + for (m = 0; m < 2; ++m) { + + /* d_ = [*]+(v_bar^2*eta/alpha)*d_ */ + /* NOTES: + * (1) [*] = u_ if m == 0, and q_ if m == 1 + * (2) using temp_val reduces the number of required computations + * if the inner loop is executed twice + */ + if (m == 0) { + temp_val = RSqrt(N_VDotProd(r_[1], r_[1])); + omega = RSqrt(RSqrt(N_VDotProd(r_[0], r_[0]))*temp_val); + N_VLinearSum(ONE, u_, SQR(v_bar)*eta/alpha, d_, d_); + } + else { + omega = temp_val; + N_VLinearSum(ONE, q_, SQR(v_bar)*eta/alpha, d_, d_); + } + + /* v_bar = omega/tau */ + v_bar = omega/tau; + + /* c = (1+v_bar^2)^(-1/2) */ + c = ONE / RSqrt(ONE+SQR(v_bar)); + + /* tau = tau*v_bar*c */ + tau = tau*v_bar*c; + + /* eta = c^2*alpha */ + eta = SQR(c)*alpha; + + /* x = x+eta*d_ */ + N_VLinearSum(ONE, x, eta, d_, x); + + /* Check for convergence... */ + /* NOTE: just use approximation to norm of residual, if possible */ + *res_norm = r_curr_norm = tau*RSqrt(m+1); + + /* Exit inner loop if iteration has converged based upon approximation + to norm of current residual */ + if (r_curr_norm <= delta) { + converged = TRUE; + break; + } + + /* Decide if actual norm of residual vector should be computed */ + /* NOTES: + * (1) if r_curr_norm > delta, then check if actual residual norm + * is OK (recall we first compute an approximation) + * (2) if r_curr_norm >= r_init_norm and m == 1 and n == l_max, then + * compute actual residual norm to see if the iteration can be + * saved + * (3) the scaled and preconditioned right-hand side of the given + * linear system (denoted by b) is only computed once, and the + * result is stored in vtemp3 so it can be reused - reduces the + * number of psovles if using left preconditioning + */ + if ((r_curr_norm > delta) || + (r_curr_norm >= r_init_norm && m == 1 && n == l_max)) { + + /* Compute norm of residual ||b-A*x||_2 (preconditioned and scaled) */ + if (scale_x) N_VDiv(x, sx, vtemp1); + else N_VScale(ONE, x, vtemp1); + if (preOnRight) { + ier = psolve(P_data, vtemp1, vtemp2, PREC_RIGHT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_UNREC); + N_VScale(ONE, vtemp2, vtemp1); + } + ier = atimes(A_data, vtemp1, vtemp2); + if (ier != 0) + return((ier < 0) ? SPTFQMR_ATIMES_FAIL_UNREC : SPTFQMR_ATIMES_FAIL_REC); + if (preOnLeft) { + ier = psolve(P_data, vtemp2, vtemp1, PREC_LEFT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC); + } + else N_VScale(ONE, vtemp2, vtemp1); + if (scale_b) N_VProd(sb, vtemp1, vtemp2); + else N_VScale(ONE, vtemp1, vtemp2); + /* Only precondition and scale b once (result saved for reuse) */ + if (!b_ok) { + b_ok = TRUE; + if (preOnLeft) { + ier = psolve(P_data, b, vtemp3, PREC_LEFT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC); + } + else N_VScale(ONE, b, vtemp3); + if (scale_b) N_VProd(sb, vtemp3, vtemp3); + } + N_VLinearSum(ONE, vtemp3, -ONE, vtemp2, vtemp1); + *res_norm = r_curr_norm = RSqrt(N_VDotProd(vtemp1, vtemp1)); + + /* Exit inner loop if inequality condition is satisfied + (meaning exit if we have converged) */ + if (r_curr_norm <= delta) { + converged = TRUE; + break; + } + + } + + } /* END inner loop */ + + /* If converged, then exit outer loop as well */ + if (converged == TRUE) break; + + /* rho[1] = r_star^T*r_[1] */ + rho[1] = N_VDotProd(r_star, r_[1]); + + /* beta = rho[1]/rho[0] */ + beta = rho[1]/rho[0]; + + /* u_ = r_[1]+beta*q_ */ + N_VLinearSum(ONE, r_[1], beta, q_, u_); + + /* p_ = u_+beta*(q_+beta*p_) */ + N_VLinearSum(beta, q_, SQR(beta), p_, p_); + N_VLinearSum(ONE, u_, ONE, p_, p_); + + /* v_ = A*p_ */ + if (scale_x) N_VDiv(p_, sx, vtemp1); + else N_VScale(ONE, p_, vtemp1); + if (preOnRight) { + N_VScale(ONE, vtemp1, v_); + ier = psolve(P_data, v_, vtemp1, PREC_RIGHT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC); + } + ier = atimes(A_data, vtemp1, v_); + if (ier != 0) + return((ier < 0) ? SPTFQMR_ATIMES_FAIL_UNREC : SPTFQMR_ATIMES_FAIL_REC); + if (preOnLeft) { + ier = psolve(P_data, v_, vtemp1, PREC_LEFT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC); + } + else N_VScale(ONE, v_, vtemp1); + if (scale_b) N_VProd(sb, vtemp1, v_); + else N_VScale(ONE, vtemp1, v_); + + /* Shift variable values */ + /* NOTE: reduces storage requirements */ + N_VScale(ONE, r_[1], r_[0]); + rho[0] = rho[1]; + + } /* END outer loop */ + + /* Determine return value */ + /* If iteration converged or residual was reduced, then return current iterate (x) */ + if ((converged == TRUE) || (r_curr_norm < r_init_norm)) { + if (scale_x) N_VDiv(x, sx, x); + if (preOnRight) { + ier = psolve(P_data, x, vtemp1, PREC_RIGHT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_UNREC); + N_VScale(ONE, vtemp1, x); + } + if (converged == TRUE) return(SPTFQMR_SUCCESS); + else return(SPTFQMR_RES_REDUCED); + } + /* Otherwise, return error code */ + else return(SPTFQMR_CONV_FAIL); +} + +/* + * ----------------------------------------------------------------- + * Function : SptfqmrFree + * ----------------------------------------------------------------- + */ + +void SptfqmrFree(SptfqmrMem mem) +{ + + if (mem == NULL) return; + + N_VDestroy(r_star); + N_VDestroy(q_); + N_VDestroy(d_); + N_VDestroy(v_); + N_VDestroy(p_); + N_VDestroyVectorArray(r_, 2); + N_VDestroy(u_); + N_VDestroy(vtemp1); + N_VDestroy(vtemp2); + N_VDestroy(vtemp3); + + free(mem); mem = NULL; +} diff --git a/odemex/Parser/CVode/ida_src/include/ida.h b/odemex/Parser/CVode/ida_src/include/ida.h new file mode 100644 index 0000000..ae1f335 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/ida.h @@ -0,0 +1,944 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.12 $ + * $Date: 2007/11/26 16:19:58 $ + * ----------------------------------------------------------------- + * Programmer(s): Allan G. Taylor, Alan C. Hindmarsh, Radu Serban, + * and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California + * Produced at the Lawrence Livermore National Laboratory + * All rights reserved + * For details, see the LICENSE file + * ----------------------------------------------------------------- + * This is the header (include) file for the main IDA solver. + * ----------------------------------------------------------------- + * + * IDA is used to solve numerically the initial value problem + * for the differential algebraic equation (DAE) system + * F(t,y,y') = 0, + * given initial conditions + * y(t0) = y0, y'(t0) = yp0. + * Here y and F are vectors of length N. + * + * ----------------------------------------------------------------- + */ + +#ifndef _IDA_H +#define _IDA_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +#include + +/* + * ================================================================= + * I D A C O N S T A N T S + * ================================================================= + */ + +/* + * ---------------------------------------------------------------- + * Inputs to IDAInit, IDAReInit, IDACalcIC, and IDASolve. + * ---------------------------------------------------------------- + */ + +/* itask */ +#define IDA_NORMAL 1 +#define IDA_ONE_STEP 2 + +/* icopt */ +#define IDA_YA_YDP_INIT 1 +#define IDA_Y_INIT 2 + +/* + * ---------------------------------------- + * IDA return flags + * ---------------------------------------- + */ + +#define IDA_SUCCESS 0 +#define IDA_TSTOP_RETURN 1 +#define IDA_ROOT_RETURN 2 + +#define IDA_WARNING 99 + +#define IDA_MEM_NULL -1 +#define IDA_ILL_INPUT -2 +#define IDA_NO_MALLOC -3 +#define IDA_TOO_MUCH_WORK -4 +#define IDA_TOO_MUCH_ACC -5 +#define IDA_ERR_FAIL -6 +#define IDA_CONV_FAIL -7 +#define IDA_LINIT_FAIL -8 +#define IDA_LSETUP_FAIL -9 +#define IDA_LSOLVE_FAIL -10 +#define IDA_RES_FAIL -11 +#define IDA_CONSTR_FAIL -12 +#define IDA_REP_RES_ERR -13 + +#define IDA_MEM_FAIL -14 + +#define IDA_BAD_T -15 + +#define IDA_BAD_EWT -16 +#define IDA_FIRST_RES_FAIL -17 +#define IDA_LINESEARCH_FAIL -18 +#define IDA_NO_RECOVERY -19 + +#define IDA_RTFUNC_FAIL -20 + +/* + * ---------------------------------------------------------------- + * Type : IDAResFn + * ---------------------------------------------------------------- + * The F function which defines the DAE system F(t,y,y')=0 + * must have type IDAResFn. + * Symbols are as follows: + * t <-> t y <-> yy + * y' <-> yp F <-> rr + * A IDAResFn takes as input the independent variable value t, + * the dependent variable vector yy, and the derivative (with + * respect to t) of the yy vector, yp. It stores the result of + * F(t,y,y') in the vector rr. The yy, yp, and rr arguments are of + * type N_Vector. The user_data parameter is the pointer user_data + * passed by the user to the IDASetRdata routine. This user-supplied + * pointer is passed to the user's res function every time it is called, + * to provide access in res to user data. + * + * A IDAResFn res should return a value of 0 if successful, a positive + * value if a recoverable error occured (e.g. yy has an illegal value), + * or a negative value if a nonrecoverable error occured. In the latter + * case, the program halts. If a recoverable error occured, the integrator + * will attempt to correct and retry. + * ---------------------------------------------------------------- + */ + +typedef int (*IDAResFn)(realtype tt, N_Vector yy, N_Vector yp, + N_Vector rr, void *user_data); + +/* + * ----------------------------------------------------------------- + * Type : IDARootFn + * ----------------------------------------------------------------- + * A function g, which defines a set of functions g_i(t,y,y') whose + * roots are sought during the integration, must have type IDARootFn. + * The function g takes as input the independent variable value t, + * the dependent variable vector y, and its t-derivative yp (= y'). + * It stores the nrtfn values g_i(t,y,y') in the realtype array gout. + * (Allocation of memory for gout is handled within IDA.) + * The user_data parameter is the same as that passed by the user + * to the IDASetRdata routine. This user-supplied pointer is + * passed to the user's g function every time it is called. + * + * An IDARootFn should return 0 if successful or a non-zero value + * if an error occured (in which case the integration will be halted). + * ----------------------------------------------------------------- + */ + +typedef int (*IDARootFn)(realtype t, N_Vector y, N_Vector yp, + realtype *gout, void *user_data); + +/* + * ----------------------------------------------------------------- + * Type : IDAEwtFn + * ----------------------------------------------------------------- + * A function e, which sets the error weight vector ewt, must have + * type IDAEwtFn. + * The function e takes as input the current dependent variable y. + * It must set the vector of error weights used in the WRMS norm: + * + * ||y||_WRMS = sqrt [ 1/N * sum ( ewt_i * y_i)^2 ] + * + * Typically, the vector ewt has components: + * + * ewt_i = 1 / (reltol * |y_i| + abstol_i) + * + * The user_data parameter is the same as that passed by the user + * to the IDASetRdata routine. This user-supplied pointer is + * passed to the user's e function every time it is called. + * An IDAEwtFn e must return 0 if the error weight vector has been + * successfuly set and a non-zero value otherwise. + * ----------------------------------------------------------------- + */ + +typedef int (*IDAEwtFn)(N_Vector y, N_Vector ewt, void *user_data); + +/* + * ----------------------------------------------------------------- + * Type : IDAErrHandlerFn + * ----------------------------------------------------------------- + * A function eh, which handles error messages, must have type + * IDAErrHandlerFn. + * The function eh takes as input the error code, the name of the + * module reporting the error, the error message, and a pointer to + * user data, the same as that passed to IDASetRdata. + * + * All error codes are negative, except IDA_WARNING which indicates + * a warning (the solver continues). + * + * An IDAErrHandlerFn has no return value. + * ----------------------------------------------------------------- + */ + +typedef void (*IDAErrHandlerFn)(int error_code, + const char *module, const char *function, + char *msg, void *user_data); + +/* + * ================================================================ + * U S E R - C A L L A B L E R O U T I N E S + * ================================================================ + */ + +/* + * ---------------------------------------------------------------- + * Function : IDACreate + * ---------------------------------------------------------------- + * IDACreate creates an internal memory block for a problem to + * be solved by IDA. + * + * If successful, IDACreate returns a pointer to initialized + * problem memory. This pointer should be passed to IDAInit. + * If an initialization error occurs, IDACreate prints an error + * message to standard err and returns NULL. + * + * ---------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void *IDACreate(void); + +/* + * ---------------------------------------------------------------- + * Integrator optional input specification functions + * ---------------------------------------------------------------- + * The following functions can be called to set optional inputs + * to values other than the defaults given below: + * + * | + * Function | Optional input / [ default value ] + * | + * ---------------------------------------------------------------- + * | + * IDASetErrHandlerFn | user-provided ErrHandler function. + * | [internal] + * | + * IDASetErrFile | the file pointer for an error file + * | where all IDA warning and error + * | messages will be written if the default + * | internal error handling function is used. + * | This parameter can be stdout (standard + * | output), stderr (standard error), or a + * | file pointer (corresponding to a user + * | error file opened for writing) returned + * | by fopen. + * | If not called, then all messages will + * | be written to the standard error stream. + * | [stderr] + * | + * IDASetUserData | a pointer to user data that will be + * | passed to the user's res function every + * | time a user-supplied function is called. + * | [NULL] + * | + * IDASetMaxOrd | maximum lmm order to be used by the + * | solver. + * | [5] + * | + * IDASetMaxNumSteps | maximum number of internal steps to be + * | taken by the solver in its attempt to + * | reach tout. + * | [500] + * | + * IDASetInitStep | initial step size. + * | [estimated by IDA] + * | + * IDASetMaxStep | maximum absolute value of step size + * | allowed. + * | [infinity] + * | + * IDASetStopTime | the independent variable value past + * | which the solution is not to proceed. + * | [infinity] + * | + * IDASetNonlinConvCoef | Newton convergence test constant + * | for use during integration. + * | [0.33] + * | + * IDASetMaxErrTestFails| Maximum number of error test failures + * | in attempting one step. + * | [10] + * | + * IDASetMaxNonlinIters | Maximum number of nonlinear solver + * | iterations at one solution. + * | [4] + * | + * IDASetMaxConvFails | Maximum number of allowable conv. + * | failures in attempting one step. + * | [10] + * | + * IDASetSuppressAlg | flag to indicate whether or not to + * | suppress algebraic variables in the + * | local error tests: + * | FALSE = do not suppress; + * | TRUE = do suppress; + * | [FALSE] + * | NOTE: if suppressed algebraic variables + * | is selected, the nvector 'id' must be + * | supplied for identification of those + * | algebraic components (see IDASetId). + * | + * IDASetId | an N_Vector, which states a given + * | element to be either algebraic or + * | differential. + * | A value of 1.0 indicates a differential + * | variable while a 0.0 indicates an + * | algebraic variable. 'id' is required + * | if optional input SUPPRESSALG is set, + * | or if IDACalcIC is to be called with + * | icopt = IDA_YA_YDP_INIT. + * | + * IDASetConstraints | an N_Vector defining inequality + * | constraints for each component of the + * | solution vector y. If a given element + * | of this vector has values +2 or -2, + * | then the corresponding component of y + * | will be constrained to be > 0.0 or + * | <0.0, respectively, while if it is +1 + * | or -1, the y component is constrained + * | to be >= 0.0 or <= 0.0, respectively. + * | If a component of constraints is 0.0, + * | then no constraint is imposed on the + * | corresponding component of y. + * | The presence of a non-NULL constraints + * | vector that is not 0.0 (ZERO) in all + * | components will cause constraint + * | checking to be performed. + * | + * ----------------------------------------------------------------- + * | + * IDASetRootDirection | Specifies the direction of zero + * | crossings to be monitored + * | [both directions] + * | + * IDASetNoInactiveRootWarn | disable warning about possible + * | g==0 at beginning of integration + * | + * ----------------------------------------------------------------- + * Return flag: + * IDA_SUCCESS if successful + * IDA_MEM_NULL if the ida memory is NULL + * IDA_ILL_INPUT if an argument has an illegal value + * + * ---------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDASetErrHandlerFn(void *ida_mem, IDAErrHandlerFn ehfun, void *eh_data); +SUNDIALS_EXPORT int IDASetErrFile(void *ida_mem, FILE *errfp); +SUNDIALS_EXPORT int IDASetUserData(void *ida_mem, void *user_data); +SUNDIALS_EXPORT int IDASetMaxOrd(void *ida_mem, int maxord); +SUNDIALS_EXPORT int IDASetMaxNumSteps(void *ida_mem, long int mxsteps); +SUNDIALS_EXPORT int IDASetInitStep(void *ida_mem, realtype hin); +SUNDIALS_EXPORT int IDASetMaxStep(void *ida_mem, realtype hmax); +SUNDIALS_EXPORT int IDASetStopTime(void *ida_mem, realtype tstop); +SUNDIALS_EXPORT int IDASetNonlinConvCoef(void *ida_mem, realtype epcon); +SUNDIALS_EXPORT int IDASetMaxErrTestFails(void *ida_mem, int maxnef); +SUNDIALS_EXPORT int IDASetMaxNonlinIters(void *ida_mem, int maxcor); +SUNDIALS_EXPORT int IDASetMaxConvFails(void *ida_mem, int maxncf); +SUNDIALS_EXPORT int IDASetSuppressAlg(void *ida_mem, booleantype suppressalg); +SUNDIALS_EXPORT int IDASetId(void *ida_mem, N_Vector id); +SUNDIALS_EXPORT int IDASetConstraints(void *ida_mem, N_Vector constraints); + +SUNDIALS_EXPORT int IDASetRootDirection(void *ida_mem, int *rootdir); +SUNDIALS_EXPORT int IDASetNoInactiveRootWarn(void *ida_mem); + +/* + * ---------------------------------------------------------------- + * Function : IDAInit + * ---------------------------------------------------------------- + * IDAInit allocates and initializes memory for a problem to + * to be solved by IDA. + * + * res is the residual function F in F(t,y,y') = 0. + * + * t0 is the initial value of t, the independent variable. + * + * yy0 is the initial condition vector y(t0). + * + * yp0 is the initial condition vector y'(t0) + * + * IDA_SUCCESS if successful + * IDA_MEM_NULL if the ida memory was NULL + * IDA_MEM_FAIL if a memory allocation failed + * IDA_ILL_INPUT f an argument has an illegal value. + * + * ---------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDAInit(void *ida_mem, IDAResFn res, + realtype t0, N_Vector yy0, N_Vector yp0); + +/* + * ---------------------------------------------------------------- + * Function : IDAReInit + * ---------------------------------------------------------------- + * IDAReInit re-initializes IDA for the solution of a problem, + * where a prior call to IDAInit has been made. + * IDAReInit performs the same input checking and initializations + * that IDAInit does. + * But it does no memory allocation, assuming that the existing + * internal memory is sufficient for the new problem. + * + * The use of IDAReInit requires that the maximum method order, + * maxord, is no larger for the new problem than for the problem + * specified in the last call to IDAInit. This condition is + * automatically fulfilled if the default value for maxord is + * specified. + * + * Following the call to IDAReInit, a call to the linear solver + * specification routine is necessary if a different linear solver + * is chosen, but may not be otherwise. If the same linear solver + * is chosen, and there are no changes in its input parameters, + * then no call to that routine is needed. + * + * The first argument to IDAReInit is: + * + * ida_mem = pointer to IDA memory returned by IDACreate. + * + * All the remaining arguments to IDAReInit have names and + * meanings identical to those of IDAInit. + * + * The return value of IDAReInit is equal to SUCCESS = 0 if there + * were no errors; otherwise it is a negative int equal to: + * IDA_MEM_NULL indicating ida_mem was NULL, or + * IDA_NO_MALLOC indicating that ida_mem was not allocated. + * IDA_ILL_INPUT indicating an input argument was illegal + * (including an attempt to increase maxord). + * In case of an error return, an error message is also printed. + * ---------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDAReInit(void *ida_mem, + realtype t0, N_Vector yy0, N_Vector yp0); + +/* + * ----------------------------------------------------------------- + * Functions : IDASStolerances + * IDASVtolerances + * IDAWFtolerances + * ----------------------------------------------------------------- + * + * These functions specify the integration tolerances. One of them + * MUST be called before the first call to IDA. + * + * IDASStolerances specifies scalar relative and absolute tolerances. + * IDASVtolerances specifies scalar relative tolerance and a vector + * absolute tolerance (a potentially different absolute tolerance + * for each vector component). + * IDAWFtolerances specifies a user-provides function (of type IDAEwtFn) + * which will be called to set the error weight vector. + * + * The tolerances reltol and abstol define a vector of error weights, + * ewt, with components + * ewt[i] = 1/(reltol*abs(y[i]) + abstol) (in the SS case), or + * ewt[i] = 1/(reltol*abs(y[i]) + abstol[i]) (in the SV case). + * This vector is used in all error and convergence tests, which + * use a weighted RMS norm on all error-like vectors v: + * WRMSnorm(v) = sqrt( (1/N) sum(i=1..N) (v[i]*ewt[i])^2 ), + * where N is the problem dimension. + * + * The return value of these functions is equal to IDA_SUCCESS = 0 if + * there were no errors; otherwise it is a negative int equal to: + * IDa_MEM_NULL indicating ida_mem was NULL (i.e., + * IDACreate has not been called). + * IDA_NO_MALLOC indicating that ida_mem has not been + * allocated (i.e., IDAInit has not been + * called). + * IDA_ILL_INPUT indicating an input argument was illegal + * (e.g. a negative tolerance) + * In case of an error return, an error message is also printed. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDASStolerances(void *ida_mem, realtype reltol, realtype abstol); +SUNDIALS_EXPORT int IDASVtolerances(void *ida_mem, realtype reltol, N_Vector abstol); +SUNDIALS_EXPORT int IDAWFtolerances(void *ida_mem, IDAEwtFn efun); + +/* ---------------------------------------------------------------- + * Initial Conditions optional input specification functions + * ---------------------------------------------------------------- + * The following functions can be called to set optional inputs + * to control the initial conditions calculations. + * + * | + * Function | Optional input / [ default value ] + * | + * -------------------------------------------------------------- + * | + * IDASetNonlinConvCoefIC | positive coeficient in the Newton + * | convergence test. This test uses a + * | weighted RMS norm (with weights + * | defined by the tolerances, as in + * | IDASolve). For new initial value + * | vectors y and y' to be accepted, the + * | norm of J-inverse F(t0,y,y') is + * | required to be less than epiccon, + * | where J is the system Jacobian. + * | [0.01 * 0.33] + * | + * IDASetMaxNumStepsIC | maximum number of values of h allowed + * | when icopt = IDA_YA_YDP_INIT, where + * | h appears in the system Jacobian, + * | J = dF/dy + (1/h)dF/dy'. + * | [5] + * | + * IDASetMaxNumJacsIC | maximum number of values of the + * | approximate Jacobian or preconditioner + * | allowed, when the Newton iterations + * | appear to be slowly converging. + * | [4] + * | + * IDASetMaxNumItersIC | maximum number of Newton iterations + * | allowed in any one attempt to solve + * | the IC problem. + * | [10] + * | + * IDASetLineSearchOffIC | a boolean flag to turn off the + * | linesearch algorithm. + * | [FALSE] + * | + * IDASetStepToleranceIC | positive lower bound on the norm of + * | a Newton step. + * | [(unit roundoff)^(2/3) + * + * ---------------------------------------------------------------- + * Return flag: + * IDA_SUCCESS if successful + * IDA_MEM_NULL if the ida memory is NULL + * IDA_ILL_INPUT if an argument has an illegal value + * + * ---------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDASetNonlinConvCoefIC(void *ida_mem, realtype epiccon); +SUNDIALS_EXPORT int IDASetMaxNumStepsIC(void *ida_mem, int maxnh); +SUNDIALS_EXPORT int IDASetMaxNumJacsIC(void *ida_mem, int maxnj); +SUNDIALS_EXPORT int IDASetMaxNumItersIC(void *ida_mem, int maxnit); +SUNDIALS_EXPORT int IDASetLineSearchOffIC(void *ida_mem, booleantype lsoff); +SUNDIALS_EXPORT int IDASetStepToleranceIC(void *ida_mem, realtype steptol); + +/* + * ----------------------------------------------------------------- + * Function : IDARootInit + * ----------------------------------------------------------------- + * IDARootInit initializes a rootfinding problem to be solved + * during the integration of the DAE system. It must be called + * after IDACreate, and before IDASolve. The arguments are: + * + * ida_mem = pointer to IDA memory returned by IDACreate. + * + * nrtfn = number of functions g_i, an int >= 0. + * + * g = name of user-supplied function, of type IDARootFn, + * defining the functions g_i whose roots are sought. + * + * If a new problem is to be solved with a call to IDAReInit, + * where the new problem has no root functions but the prior one + * did, then call IDARootInit with nrtfn = 0. + * + * The return value of IDARootInit is IDA_SUCCESS = 0 if there were + * no errors; otherwise it is a negative int equal to: + * IDA_MEM_NULL indicating ida_mem was NULL, or + * IDA_MEM_FAIL indicating a memory allocation failed. + * (including an attempt to increase maxord). + * IDA_ILL_INPUT indicating nrtfn > 0 but g = NULL. + * In case of an error return, an error message is also printed. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDARootInit(void *ida_mem, int nrtfn, IDARootFn g); + +/* + * ---------------------------------------------------------------- + * Function : IDACalcIC + * ---------------------------------------------------------------- + * IDACalcIC calculates corrected initial conditions for the DAE + * system for a class of index-one problems of semi-implicit form. + * It uses Newton iteration combined with a Linesearch algorithm. + * Calling IDACalcIC is optional. It is only necessary when the + * initial conditions do not solve the given system. I.e., if + * y0 and yp0 are known to satisfy F(t0, y0, yp0) = 0, then + * a call to IDACalcIC is NOT necessary (for index-one problems). + * + * A call to IDACalcIC must be preceded by a successful call to + * IDAInit or IDAReInit for the given DAE problem, and by a + * successful call to the linear system solver specification + * routine. + * + * The call to IDACalcIC should precede the call(s) to IDASolve + * for the given problem. + * + * The arguments to IDACalcIC are as follows: + * + * ida_mem is the pointer to IDA memory returned by IDACreate. + * + * icopt is the option of IDACalcIC to be used. + * icopt = IDA_YA_YDP_INIT directs IDACalcIC to compute + * the algebraic components of y and differential + * components of y', given the differential + * components of y. This option requires that the + * N_Vector id was set through a call to IDASetId + * specifying the differential and algebraic + * components. + * icopt = IDA_Y_INIT directs IDACalcIC to compute all + * components of y, given y'. id is not required. + * + * tout1 is the first value of t at which a soluton will be + * requested (from IDASolve). (This is needed here to + * determine the direction of integration and rough scale + * in the independent variable t.) + * + * + * IDACalcIC returns an int flag. Its symbolic values and their + * meanings are as follows. (The numerical return values are set + * above in this file.) All unsuccessful returns give a negative + * return value. If IFACalcIC failed, y0 and yp0 contain + * (possibly) altered values, computed during the attempt. + * + * IDA_SUCCESS IDACalcIC was successful. The corrected + * initial value vectors were stored internally. + * + * IDA_MEM_NULL The argument ida_mem was NULL. + * + * IDA_ILL_INPUT One of the input arguments was illegal. + * See printed message. + * + * IDA_LINIT_FAIL The linear solver's init routine failed. + * + * IDA_BAD_EWT Some component of the error weight vector + * is zero (illegal), either for the input + * value of y0 or a corrected value. + * + * IDA_RES_FAIL The user's residual routine returned + * a non-recoverable error flag. + * + * IDA_FIRST_RES_FAIL The user's residual routine returned + * a recoverable error flag on the first call, + * but IDACalcIC was unable to recover. + * + * IDA_LSETUP_FAIL The linear solver's setup routine had a + * non-recoverable error. + * + * IDA_LSOLVE_FAIL The linear solver's solve routine had a + * non-recoverable error. + * + * IDA_NO_RECOVERY The user's residual routine, or the linear + * solver's setup or solve routine had a + * recoverable error, but IDACalcIC was + * unable to recover. + * + * IDA_CONSTR_FAIL IDACalcIC was unable to find a solution + * satisfying the inequality constraints. + * + * IDA_LINESEARCH_FAIL The Linesearch algorithm failed to find a + * solution with a step larger than steptol + * in weighted RMS norm. + * + * IDA_CONV_FAIL IDACalcIC failed to get convergence of the + * Newton iterations. + * + * ---------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDACalcIC(void *ida_mem, int icopt, realtype tout1); + +/* + * ---------------------------------------------------------------- + * Function : IDASolve + * ---------------------------------------------------------------- + * IDASolve integrates the DAE over an interval in t, the + * independent variable. If itask is IDA_NORMAL, then the solver + * integrates from its current internal t value to a point at or + * beyond tout, then interpolates to t = tout and returns y(tret) + * in the user-allocated vector yret. In general, tret = tout. + * If itask is IDA_ONE_STEP, then the solver takes one internal + * step of the independent variable and returns in yret the value + * of y at the new internal independent variable value. In this + * case, tout is used only during the first call to IDASolve to + * determine the direction of integration and the rough scale of + * the problem. If tstop is enabled (through a call to IDASetStopTime), + * then IDASolve returns the solution at tstop. Once the integrator + * returns at a tstop time, any future testing for tstop is disabled + * (and can be reenabled only though a new call to IDASetStopTime). + * The time reached by the solver is placed in (*tret). The + * user is responsible for allocating the memory for this value. + * + * ida_mem is the pointer (void) to IDA memory returned by + * IDACreate. + * + * tout is the next independent variable value at which a + * computed solution is desired. + * + * tret is a pointer to a real location. IDASolve sets (*tret) + * to the actual t value reached, corresponding to the + * solution vector yret. In IDA_NORMAL mode, with no + * errors and no roots found, (*tret) = tout. + * + * yret is the computed solution vector. With no errors, + * yret = y(tret). + * + * ypret is the derivative of the computed solution at t = tret. + * + * Note: yret and ypret may be the same N_Vectors as y0 and yp0 + * in the call to IDAInit or IDAReInit. + * + * itask is IDA_NORMAL or IDA_ONE_STEP. These two modes are described above. + * + * + * The return values for IDASolve are described below. + * (The numerical return values are defined above in this file.) + * All unsuccessful returns give a negative return value. + * + * IDA_SUCCESS + * IDASolve succeeded and no roots were found. + * + * IDA_ROOT_RETURN: IDASolve succeeded, and found one or more roots. + * If nrtfn > 1, call IDAGetRootInfo to see which g_i were found + * to have a root at (*tret). + * + * IDA_TSTOP_RETURN: + * IDASolve returns computed results for the independent variable + * value tstop. That is, tstop was reached. + * + * IDA_MEM_NULL: + * The IDA_mem argument was NULL. + * + * IDA_ILL_INPUT: + * One of the inputs to IDASolve is illegal. This includes the + * situation when a component of the error weight vectors + * becomes < 0 during internal stepping. It also includes the + * situation where a root of one of the root functions was found + * both at t0 and very near t0. The ILL_INPUT flag + * will also be returned if the linear solver function IDA--- + * (called by the user after calling IDACreate) failed to set one + * of the linear solver-related fields in ida_mem or if the linear + * solver's init routine failed. In any case, the user should see + * the printed error message for more details. + * + * IDA_TOO_MUCH_WORK: + * The solver took mxstep internal steps but could not reach tout. + * The default value for mxstep is MXSTEP_DEFAULT = 500. + * + * IDA_TOO_MUCH_ACC: + * The solver could not satisfy the accuracy demanded by the user + * for some internal step. + * + * IDA_ERR_FAIL: + * Error test failures occurred too many times (=MXETF = 10) during + * one internal step. + * + * IDA_CONV_FAIL: + * Convergence test failures occurred too many times (= MXNCF = 10) + * during one internal step. + * + * IDA_LSETUP_FAIL: + * The linear solver's setup routine failed + * in an unrecoverable manner. + * + * IDA_LSOLVE_FAIL: + * The linear solver's solve routine failed + * in an unrecoverable manner. + * + * IDA_CONSTR_FAIL: + * The inequality constraints were violated, + * and the solver was unable to recover. + * + * IDA_REP_RES_ERR: + * The user's residual function repeatedly returned a recoverable + * error flag, but the solver was unable to recover. + * + * IDA_RES_FAIL: + * The user's residual function returned a nonrecoverable error + * flag. + * + * ---------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDASolve(void *ida_mem, realtype tout, realtype *tret, + N_Vector yret, N_Vector ypret, int itask); + +/* + * ---------------------------------------------------------------- + * Function: IDAGetSolution + * ---------------------------------------------------------------- + * + * This routine evaluates y(t) and y'(t) as the value and + * derivative of the interpolating polynomial at the independent + * variable t, and stores the results in the vectors yret and + * ypret. It uses the current independent variable value, tn, + * and the method order last used, kused. This function is + * called by IDASolve with t = tout, t = tn, or t = tstop. + * + * If kused = 0 (no step has been taken), or if t = tn, then the + * order used here is taken to be 1, giving yret = phi[0], + * ypret = phi[1]/psi[0]. + * + * The return values are: + * IDA_SUCCESS: succeess. + * IDA_BAD_T: t is not in the interval [tn-hu,tn]. + * IDA_MEM_NULL: The ida_mem argument was NULL. + * + * ---------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDAGetSolution(void *ida_mem, realtype t, + N_Vector yret, N_Vector ypret); + +/* ---------------------------------------------------------------- + * Integrator optional output extraction functions + * ---------------------------------------------------------------- + * + * The following functions can be called to get optional outputs + * and statistics related to the main integrator. + * ---------------------------------------------------------------- + * + * IDAGetWorkSpace returns the IDA real and integer workspace sizes + * IDAGetNumSteps returns the cumulative number of internal + * steps taken by the solver + * IDAGetNumRhsEvals returns the number of calls to the user's + * res function + * IDAGetNumLinSolvSetups returns the number of calls made to + * the linear solver's setup routine + * IDAGetNumErrTestFails returns the number of local error test + * failures that have occured + * IDAGetNumBacktrackOps returns the number of backtrack + * operations done in the linesearch algorithm in IDACalcIC + * IDAGetConsistentIC returns the consistent initial conditions + * computed by IDACalcIC + * IDAGetLastOrder returns the order used during the last + * internal step + * IDAGetCurentOrder returns the order to be used on the next + * internal step + * IDAGetActualInitStep returns the actual initial step size + * used by IDA + * IDAGetLAstStep returns the step size for the last internal + * step (if from IDASolve), or the last value of the + * artificial step size h (if from IDACalcIC) + * IDAGetCurrentStep returns the step size to be attempted on the + * next internal step + * IDAGetCurrentTime returns the current internal time reached + * by the solver + * IDAGetTolScaleFactor returns a suggested factor by which the + * user's tolerances should be scaled when too much + * accuracy has been requested for some internal step + * IDAGetErrWeights returns the current state error weight vector. + * The user must allocate space for eweight. + * IDAGetEstLocalErrors returns the estimated local errors. The user + * must allocate space for the vector ele. + * IDAGetNumGEvals returns the number of calls to the user's + * g function (for rootfinding) + * IDAGetRootInfo returns the indices for which g_i was found to + * have a root. The user must allocate space for rootsfound. + * For i = 0 ... nrtfn-1, rootsfound[i] = 1 if g_i has a root, + * and rootsfound[i]= 0 if not. + * + * IDAGet* return values: + * IDA_SUCCESS if succesful + * IDA_MEM_NULL if the ida memory was NULL + * IDA_ILL_INPUT if some input is illegal + * + * ---------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDAGetWorkSpace(void *ida_mem, long int *lenrw, long int *leniw); +SUNDIALS_EXPORT int IDAGetNumSteps(void *ida_mem, long int *nsteps); +SUNDIALS_EXPORT int IDAGetNumResEvals(void *ida_mem, long int *nrevals); +SUNDIALS_EXPORT int IDAGetNumLinSolvSetups(void *ida_mem, long int *nlinsetups); +SUNDIALS_EXPORT int IDAGetNumErrTestFails(void *ida_mem, long int *netfails); +SUNDIALS_EXPORT int IDAGetNumBacktrackOps(void *ida_mem, long int *nbacktr); +SUNDIALS_EXPORT int IDAGetConsistentIC(void *ida_mem, N_Vector yy0_mod, N_Vector yp0_mod); +SUNDIALS_EXPORT int IDAGetLastOrder(void *ida_mem, int *klast); +SUNDIALS_EXPORT int IDAGetCurrentOrder(void *ida_mem, int *kcur); +SUNDIALS_EXPORT int IDAGetActualInitStep(void *ida_mem, realtype *hinused); +SUNDIALS_EXPORT int IDAGetLastStep(void *ida_mem, realtype *hlast); +SUNDIALS_EXPORT int IDAGetCurrentStep(void *ida_mem, realtype *hcur); +SUNDIALS_EXPORT int IDAGetCurrentTime(void *ida_mem, realtype *tcur); +SUNDIALS_EXPORT int IDAGetTolScaleFactor(void *ida_mem, realtype *tolsfact); +SUNDIALS_EXPORT int IDAGetErrWeights(void *ida_mem, N_Vector eweight); +SUNDIALS_EXPORT int IDAGetEstLocalErrors(void *ida_mem, N_Vector ele); +SUNDIALS_EXPORT int IDAGetNumGEvals(void *ida_mem, long int *ngevals); +SUNDIALS_EXPORT int IDAGetRootInfo(void *ida_mem, int *rootsfound); + +/* + * ---------------------------------------------------------------- + * As a convenience, the following function provides the + * optional outputs in a group. + * ---------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDAGetIntegratorStats(void *ida_mem, long int *nsteps, + long int *nrevals, long int *nlinsetups, + long int *netfails, int *qlast, int *qcur, + realtype *hinused, realtype *hlast, realtype *hcur, + realtype *tcur); + +/* + * ---------------------------------------------------------------- + * Nonlinear solver optional output extraction functions + * ---------------------------------------------------------------- + * + * The following functions can be called to get optional outputs + * and statistics related to the nonlinear solver. + * -------------------------------------------------------------- + * + * IDAGetNumNonlinSolvIters returns the number of nonlinear + * solver iterations performed. + * IDAGetNumNonlinSolvConvFails returns the number of nonlinear + * convergence failures. + * + * ---------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDAGetNumNonlinSolvIters(void *ida_mem, long int *nniters); +SUNDIALS_EXPORT int IDAGetNumNonlinSolvConvFails(void *ida_mem, long int *nncfails); + +/* + * ---------------------------------------------------------------- + * As a convenience, the following function provides the + * nonlinear solver optional outputs in a group. + * ---------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDAGetNonlinSolvStats(void *ida_mem, long int *nniters, + long int *nncfails); + +/* + * ----------------------------------------------------------------- + * The following function returns the name of the constant + * associated with an IDA return flag + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT char *IDAGetReturnFlagName(int flag); + +/* + * ---------------------------------------------------------------- + * Function : IDAFree + * ---------------------------------------------------------------- + * IDAFree frees the problem memory IDA_mem allocated by + * IDAInit. Its only argument is the pointer idamem + * returned by IDAInit. + * ---------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void IDAFree(void **ida_mem); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/ida/ida.h b/odemex/Parser/CVode/ida_src/include/ida/ida.h new file mode 100644 index 0000000..ae1f335 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/ida/ida.h @@ -0,0 +1,944 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.12 $ + * $Date: 2007/11/26 16:19:58 $ + * ----------------------------------------------------------------- + * Programmer(s): Allan G. Taylor, Alan C. Hindmarsh, Radu Serban, + * and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California + * Produced at the Lawrence Livermore National Laboratory + * All rights reserved + * For details, see the LICENSE file + * ----------------------------------------------------------------- + * This is the header (include) file for the main IDA solver. + * ----------------------------------------------------------------- + * + * IDA is used to solve numerically the initial value problem + * for the differential algebraic equation (DAE) system + * F(t,y,y') = 0, + * given initial conditions + * y(t0) = y0, y'(t0) = yp0. + * Here y and F are vectors of length N. + * + * ----------------------------------------------------------------- + */ + +#ifndef _IDA_H +#define _IDA_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +#include + +/* + * ================================================================= + * I D A C O N S T A N T S + * ================================================================= + */ + +/* + * ---------------------------------------------------------------- + * Inputs to IDAInit, IDAReInit, IDACalcIC, and IDASolve. + * ---------------------------------------------------------------- + */ + +/* itask */ +#define IDA_NORMAL 1 +#define IDA_ONE_STEP 2 + +/* icopt */ +#define IDA_YA_YDP_INIT 1 +#define IDA_Y_INIT 2 + +/* + * ---------------------------------------- + * IDA return flags + * ---------------------------------------- + */ + +#define IDA_SUCCESS 0 +#define IDA_TSTOP_RETURN 1 +#define IDA_ROOT_RETURN 2 + +#define IDA_WARNING 99 + +#define IDA_MEM_NULL -1 +#define IDA_ILL_INPUT -2 +#define IDA_NO_MALLOC -3 +#define IDA_TOO_MUCH_WORK -4 +#define IDA_TOO_MUCH_ACC -5 +#define IDA_ERR_FAIL -6 +#define IDA_CONV_FAIL -7 +#define IDA_LINIT_FAIL -8 +#define IDA_LSETUP_FAIL -9 +#define IDA_LSOLVE_FAIL -10 +#define IDA_RES_FAIL -11 +#define IDA_CONSTR_FAIL -12 +#define IDA_REP_RES_ERR -13 + +#define IDA_MEM_FAIL -14 + +#define IDA_BAD_T -15 + +#define IDA_BAD_EWT -16 +#define IDA_FIRST_RES_FAIL -17 +#define IDA_LINESEARCH_FAIL -18 +#define IDA_NO_RECOVERY -19 + +#define IDA_RTFUNC_FAIL -20 + +/* + * ---------------------------------------------------------------- + * Type : IDAResFn + * ---------------------------------------------------------------- + * The F function which defines the DAE system F(t,y,y')=0 + * must have type IDAResFn. + * Symbols are as follows: + * t <-> t y <-> yy + * y' <-> yp F <-> rr + * A IDAResFn takes as input the independent variable value t, + * the dependent variable vector yy, and the derivative (with + * respect to t) of the yy vector, yp. It stores the result of + * F(t,y,y') in the vector rr. The yy, yp, and rr arguments are of + * type N_Vector. The user_data parameter is the pointer user_data + * passed by the user to the IDASetRdata routine. This user-supplied + * pointer is passed to the user's res function every time it is called, + * to provide access in res to user data. + * + * A IDAResFn res should return a value of 0 if successful, a positive + * value if a recoverable error occured (e.g. yy has an illegal value), + * or a negative value if a nonrecoverable error occured. In the latter + * case, the program halts. If a recoverable error occured, the integrator + * will attempt to correct and retry. + * ---------------------------------------------------------------- + */ + +typedef int (*IDAResFn)(realtype tt, N_Vector yy, N_Vector yp, + N_Vector rr, void *user_data); + +/* + * ----------------------------------------------------------------- + * Type : IDARootFn + * ----------------------------------------------------------------- + * A function g, which defines a set of functions g_i(t,y,y') whose + * roots are sought during the integration, must have type IDARootFn. + * The function g takes as input the independent variable value t, + * the dependent variable vector y, and its t-derivative yp (= y'). + * It stores the nrtfn values g_i(t,y,y') in the realtype array gout. + * (Allocation of memory for gout is handled within IDA.) + * The user_data parameter is the same as that passed by the user + * to the IDASetRdata routine. This user-supplied pointer is + * passed to the user's g function every time it is called. + * + * An IDARootFn should return 0 if successful or a non-zero value + * if an error occured (in which case the integration will be halted). + * ----------------------------------------------------------------- + */ + +typedef int (*IDARootFn)(realtype t, N_Vector y, N_Vector yp, + realtype *gout, void *user_data); + +/* + * ----------------------------------------------------------------- + * Type : IDAEwtFn + * ----------------------------------------------------------------- + * A function e, which sets the error weight vector ewt, must have + * type IDAEwtFn. + * The function e takes as input the current dependent variable y. + * It must set the vector of error weights used in the WRMS norm: + * + * ||y||_WRMS = sqrt [ 1/N * sum ( ewt_i * y_i)^2 ] + * + * Typically, the vector ewt has components: + * + * ewt_i = 1 / (reltol * |y_i| + abstol_i) + * + * The user_data parameter is the same as that passed by the user + * to the IDASetRdata routine. This user-supplied pointer is + * passed to the user's e function every time it is called. + * An IDAEwtFn e must return 0 if the error weight vector has been + * successfuly set and a non-zero value otherwise. + * ----------------------------------------------------------------- + */ + +typedef int (*IDAEwtFn)(N_Vector y, N_Vector ewt, void *user_data); + +/* + * ----------------------------------------------------------------- + * Type : IDAErrHandlerFn + * ----------------------------------------------------------------- + * A function eh, which handles error messages, must have type + * IDAErrHandlerFn. + * The function eh takes as input the error code, the name of the + * module reporting the error, the error message, and a pointer to + * user data, the same as that passed to IDASetRdata. + * + * All error codes are negative, except IDA_WARNING which indicates + * a warning (the solver continues). + * + * An IDAErrHandlerFn has no return value. + * ----------------------------------------------------------------- + */ + +typedef void (*IDAErrHandlerFn)(int error_code, + const char *module, const char *function, + char *msg, void *user_data); + +/* + * ================================================================ + * U S E R - C A L L A B L E R O U T I N E S + * ================================================================ + */ + +/* + * ---------------------------------------------------------------- + * Function : IDACreate + * ---------------------------------------------------------------- + * IDACreate creates an internal memory block for a problem to + * be solved by IDA. + * + * If successful, IDACreate returns a pointer to initialized + * problem memory. This pointer should be passed to IDAInit. + * If an initialization error occurs, IDACreate prints an error + * message to standard err and returns NULL. + * + * ---------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void *IDACreate(void); + +/* + * ---------------------------------------------------------------- + * Integrator optional input specification functions + * ---------------------------------------------------------------- + * The following functions can be called to set optional inputs + * to values other than the defaults given below: + * + * | + * Function | Optional input / [ default value ] + * | + * ---------------------------------------------------------------- + * | + * IDASetErrHandlerFn | user-provided ErrHandler function. + * | [internal] + * | + * IDASetErrFile | the file pointer for an error file + * | where all IDA warning and error + * | messages will be written if the default + * | internal error handling function is used. + * | This parameter can be stdout (standard + * | output), stderr (standard error), or a + * | file pointer (corresponding to a user + * | error file opened for writing) returned + * | by fopen. + * | If not called, then all messages will + * | be written to the standard error stream. + * | [stderr] + * | + * IDASetUserData | a pointer to user data that will be + * | passed to the user's res function every + * | time a user-supplied function is called. + * | [NULL] + * | + * IDASetMaxOrd | maximum lmm order to be used by the + * | solver. + * | [5] + * | + * IDASetMaxNumSteps | maximum number of internal steps to be + * | taken by the solver in its attempt to + * | reach tout. + * | [500] + * | + * IDASetInitStep | initial step size. + * | [estimated by IDA] + * | + * IDASetMaxStep | maximum absolute value of step size + * | allowed. + * | [infinity] + * | + * IDASetStopTime | the independent variable value past + * | which the solution is not to proceed. + * | [infinity] + * | + * IDASetNonlinConvCoef | Newton convergence test constant + * | for use during integration. + * | [0.33] + * | + * IDASetMaxErrTestFails| Maximum number of error test failures + * | in attempting one step. + * | [10] + * | + * IDASetMaxNonlinIters | Maximum number of nonlinear solver + * | iterations at one solution. + * | [4] + * | + * IDASetMaxConvFails | Maximum number of allowable conv. + * | failures in attempting one step. + * | [10] + * | + * IDASetSuppressAlg | flag to indicate whether or not to + * | suppress algebraic variables in the + * | local error tests: + * | FALSE = do not suppress; + * | TRUE = do suppress; + * | [FALSE] + * | NOTE: if suppressed algebraic variables + * | is selected, the nvector 'id' must be + * | supplied for identification of those + * | algebraic components (see IDASetId). + * | + * IDASetId | an N_Vector, which states a given + * | element to be either algebraic or + * | differential. + * | A value of 1.0 indicates a differential + * | variable while a 0.0 indicates an + * | algebraic variable. 'id' is required + * | if optional input SUPPRESSALG is set, + * | or if IDACalcIC is to be called with + * | icopt = IDA_YA_YDP_INIT. + * | + * IDASetConstraints | an N_Vector defining inequality + * | constraints for each component of the + * | solution vector y. If a given element + * | of this vector has values +2 or -2, + * | then the corresponding component of y + * | will be constrained to be > 0.0 or + * | <0.0, respectively, while if it is +1 + * | or -1, the y component is constrained + * | to be >= 0.0 or <= 0.0, respectively. + * | If a component of constraints is 0.0, + * | then no constraint is imposed on the + * | corresponding component of y. + * | The presence of a non-NULL constraints + * | vector that is not 0.0 (ZERO) in all + * | components will cause constraint + * | checking to be performed. + * | + * ----------------------------------------------------------------- + * | + * IDASetRootDirection | Specifies the direction of zero + * | crossings to be monitored + * | [both directions] + * | + * IDASetNoInactiveRootWarn | disable warning about possible + * | g==0 at beginning of integration + * | + * ----------------------------------------------------------------- + * Return flag: + * IDA_SUCCESS if successful + * IDA_MEM_NULL if the ida memory is NULL + * IDA_ILL_INPUT if an argument has an illegal value + * + * ---------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDASetErrHandlerFn(void *ida_mem, IDAErrHandlerFn ehfun, void *eh_data); +SUNDIALS_EXPORT int IDASetErrFile(void *ida_mem, FILE *errfp); +SUNDIALS_EXPORT int IDASetUserData(void *ida_mem, void *user_data); +SUNDIALS_EXPORT int IDASetMaxOrd(void *ida_mem, int maxord); +SUNDIALS_EXPORT int IDASetMaxNumSteps(void *ida_mem, long int mxsteps); +SUNDIALS_EXPORT int IDASetInitStep(void *ida_mem, realtype hin); +SUNDIALS_EXPORT int IDASetMaxStep(void *ida_mem, realtype hmax); +SUNDIALS_EXPORT int IDASetStopTime(void *ida_mem, realtype tstop); +SUNDIALS_EXPORT int IDASetNonlinConvCoef(void *ida_mem, realtype epcon); +SUNDIALS_EXPORT int IDASetMaxErrTestFails(void *ida_mem, int maxnef); +SUNDIALS_EXPORT int IDASetMaxNonlinIters(void *ida_mem, int maxcor); +SUNDIALS_EXPORT int IDASetMaxConvFails(void *ida_mem, int maxncf); +SUNDIALS_EXPORT int IDASetSuppressAlg(void *ida_mem, booleantype suppressalg); +SUNDIALS_EXPORT int IDASetId(void *ida_mem, N_Vector id); +SUNDIALS_EXPORT int IDASetConstraints(void *ida_mem, N_Vector constraints); + +SUNDIALS_EXPORT int IDASetRootDirection(void *ida_mem, int *rootdir); +SUNDIALS_EXPORT int IDASetNoInactiveRootWarn(void *ida_mem); + +/* + * ---------------------------------------------------------------- + * Function : IDAInit + * ---------------------------------------------------------------- + * IDAInit allocates and initializes memory for a problem to + * to be solved by IDA. + * + * res is the residual function F in F(t,y,y') = 0. + * + * t0 is the initial value of t, the independent variable. + * + * yy0 is the initial condition vector y(t0). + * + * yp0 is the initial condition vector y'(t0) + * + * IDA_SUCCESS if successful + * IDA_MEM_NULL if the ida memory was NULL + * IDA_MEM_FAIL if a memory allocation failed + * IDA_ILL_INPUT f an argument has an illegal value. + * + * ---------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDAInit(void *ida_mem, IDAResFn res, + realtype t0, N_Vector yy0, N_Vector yp0); + +/* + * ---------------------------------------------------------------- + * Function : IDAReInit + * ---------------------------------------------------------------- + * IDAReInit re-initializes IDA for the solution of a problem, + * where a prior call to IDAInit has been made. + * IDAReInit performs the same input checking and initializations + * that IDAInit does. + * But it does no memory allocation, assuming that the existing + * internal memory is sufficient for the new problem. + * + * The use of IDAReInit requires that the maximum method order, + * maxord, is no larger for the new problem than for the problem + * specified in the last call to IDAInit. This condition is + * automatically fulfilled if the default value for maxord is + * specified. + * + * Following the call to IDAReInit, a call to the linear solver + * specification routine is necessary if a different linear solver + * is chosen, but may not be otherwise. If the same linear solver + * is chosen, and there are no changes in its input parameters, + * then no call to that routine is needed. + * + * The first argument to IDAReInit is: + * + * ida_mem = pointer to IDA memory returned by IDACreate. + * + * All the remaining arguments to IDAReInit have names and + * meanings identical to those of IDAInit. + * + * The return value of IDAReInit is equal to SUCCESS = 0 if there + * were no errors; otherwise it is a negative int equal to: + * IDA_MEM_NULL indicating ida_mem was NULL, or + * IDA_NO_MALLOC indicating that ida_mem was not allocated. + * IDA_ILL_INPUT indicating an input argument was illegal + * (including an attempt to increase maxord). + * In case of an error return, an error message is also printed. + * ---------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDAReInit(void *ida_mem, + realtype t0, N_Vector yy0, N_Vector yp0); + +/* + * ----------------------------------------------------------------- + * Functions : IDASStolerances + * IDASVtolerances + * IDAWFtolerances + * ----------------------------------------------------------------- + * + * These functions specify the integration tolerances. One of them + * MUST be called before the first call to IDA. + * + * IDASStolerances specifies scalar relative and absolute tolerances. + * IDASVtolerances specifies scalar relative tolerance and a vector + * absolute tolerance (a potentially different absolute tolerance + * for each vector component). + * IDAWFtolerances specifies a user-provides function (of type IDAEwtFn) + * which will be called to set the error weight vector. + * + * The tolerances reltol and abstol define a vector of error weights, + * ewt, with components + * ewt[i] = 1/(reltol*abs(y[i]) + abstol) (in the SS case), or + * ewt[i] = 1/(reltol*abs(y[i]) + abstol[i]) (in the SV case). + * This vector is used in all error and convergence tests, which + * use a weighted RMS norm on all error-like vectors v: + * WRMSnorm(v) = sqrt( (1/N) sum(i=1..N) (v[i]*ewt[i])^2 ), + * where N is the problem dimension. + * + * The return value of these functions is equal to IDA_SUCCESS = 0 if + * there were no errors; otherwise it is a negative int equal to: + * IDa_MEM_NULL indicating ida_mem was NULL (i.e., + * IDACreate has not been called). + * IDA_NO_MALLOC indicating that ida_mem has not been + * allocated (i.e., IDAInit has not been + * called). + * IDA_ILL_INPUT indicating an input argument was illegal + * (e.g. a negative tolerance) + * In case of an error return, an error message is also printed. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDASStolerances(void *ida_mem, realtype reltol, realtype abstol); +SUNDIALS_EXPORT int IDASVtolerances(void *ida_mem, realtype reltol, N_Vector abstol); +SUNDIALS_EXPORT int IDAWFtolerances(void *ida_mem, IDAEwtFn efun); + +/* ---------------------------------------------------------------- + * Initial Conditions optional input specification functions + * ---------------------------------------------------------------- + * The following functions can be called to set optional inputs + * to control the initial conditions calculations. + * + * | + * Function | Optional input / [ default value ] + * | + * -------------------------------------------------------------- + * | + * IDASetNonlinConvCoefIC | positive coeficient in the Newton + * | convergence test. This test uses a + * | weighted RMS norm (with weights + * | defined by the tolerances, as in + * | IDASolve). For new initial value + * | vectors y and y' to be accepted, the + * | norm of J-inverse F(t0,y,y') is + * | required to be less than epiccon, + * | where J is the system Jacobian. + * | [0.01 * 0.33] + * | + * IDASetMaxNumStepsIC | maximum number of values of h allowed + * | when icopt = IDA_YA_YDP_INIT, where + * | h appears in the system Jacobian, + * | J = dF/dy + (1/h)dF/dy'. + * | [5] + * | + * IDASetMaxNumJacsIC | maximum number of values of the + * | approximate Jacobian or preconditioner + * | allowed, when the Newton iterations + * | appear to be slowly converging. + * | [4] + * | + * IDASetMaxNumItersIC | maximum number of Newton iterations + * | allowed in any one attempt to solve + * | the IC problem. + * | [10] + * | + * IDASetLineSearchOffIC | a boolean flag to turn off the + * | linesearch algorithm. + * | [FALSE] + * | + * IDASetStepToleranceIC | positive lower bound on the norm of + * | a Newton step. + * | [(unit roundoff)^(2/3) + * + * ---------------------------------------------------------------- + * Return flag: + * IDA_SUCCESS if successful + * IDA_MEM_NULL if the ida memory is NULL + * IDA_ILL_INPUT if an argument has an illegal value + * + * ---------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDASetNonlinConvCoefIC(void *ida_mem, realtype epiccon); +SUNDIALS_EXPORT int IDASetMaxNumStepsIC(void *ida_mem, int maxnh); +SUNDIALS_EXPORT int IDASetMaxNumJacsIC(void *ida_mem, int maxnj); +SUNDIALS_EXPORT int IDASetMaxNumItersIC(void *ida_mem, int maxnit); +SUNDIALS_EXPORT int IDASetLineSearchOffIC(void *ida_mem, booleantype lsoff); +SUNDIALS_EXPORT int IDASetStepToleranceIC(void *ida_mem, realtype steptol); + +/* + * ----------------------------------------------------------------- + * Function : IDARootInit + * ----------------------------------------------------------------- + * IDARootInit initializes a rootfinding problem to be solved + * during the integration of the DAE system. It must be called + * after IDACreate, and before IDASolve. The arguments are: + * + * ida_mem = pointer to IDA memory returned by IDACreate. + * + * nrtfn = number of functions g_i, an int >= 0. + * + * g = name of user-supplied function, of type IDARootFn, + * defining the functions g_i whose roots are sought. + * + * If a new problem is to be solved with a call to IDAReInit, + * where the new problem has no root functions but the prior one + * did, then call IDARootInit with nrtfn = 0. + * + * The return value of IDARootInit is IDA_SUCCESS = 0 if there were + * no errors; otherwise it is a negative int equal to: + * IDA_MEM_NULL indicating ida_mem was NULL, or + * IDA_MEM_FAIL indicating a memory allocation failed. + * (including an attempt to increase maxord). + * IDA_ILL_INPUT indicating nrtfn > 0 but g = NULL. + * In case of an error return, an error message is also printed. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDARootInit(void *ida_mem, int nrtfn, IDARootFn g); + +/* + * ---------------------------------------------------------------- + * Function : IDACalcIC + * ---------------------------------------------------------------- + * IDACalcIC calculates corrected initial conditions for the DAE + * system for a class of index-one problems of semi-implicit form. + * It uses Newton iteration combined with a Linesearch algorithm. + * Calling IDACalcIC is optional. It is only necessary when the + * initial conditions do not solve the given system. I.e., if + * y0 and yp0 are known to satisfy F(t0, y0, yp0) = 0, then + * a call to IDACalcIC is NOT necessary (for index-one problems). + * + * A call to IDACalcIC must be preceded by a successful call to + * IDAInit or IDAReInit for the given DAE problem, and by a + * successful call to the linear system solver specification + * routine. + * + * The call to IDACalcIC should precede the call(s) to IDASolve + * for the given problem. + * + * The arguments to IDACalcIC are as follows: + * + * ida_mem is the pointer to IDA memory returned by IDACreate. + * + * icopt is the option of IDACalcIC to be used. + * icopt = IDA_YA_YDP_INIT directs IDACalcIC to compute + * the algebraic components of y and differential + * components of y', given the differential + * components of y. This option requires that the + * N_Vector id was set through a call to IDASetId + * specifying the differential and algebraic + * components. + * icopt = IDA_Y_INIT directs IDACalcIC to compute all + * components of y, given y'. id is not required. + * + * tout1 is the first value of t at which a soluton will be + * requested (from IDASolve). (This is needed here to + * determine the direction of integration and rough scale + * in the independent variable t.) + * + * + * IDACalcIC returns an int flag. Its symbolic values and their + * meanings are as follows. (The numerical return values are set + * above in this file.) All unsuccessful returns give a negative + * return value. If IFACalcIC failed, y0 and yp0 contain + * (possibly) altered values, computed during the attempt. + * + * IDA_SUCCESS IDACalcIC was successful. The corrected + * initial value vectors were stored internally. + * + * IDA_MEM_NULL The argument ida_mem was NULL. + * + * IDA_ILL_INPUT One of the input arguments was illegal. + * See printed message. + * + * IDA_LINIT_FAIL The linear solver's init routine failed. + * + * IDA_BAD_EWT Some component of the error weight vector + * is zero (illegal), either for the input + * value of y0 or a corrected value. + * + * IDA_RES_FAIL The user's residual routine returned + * a non-recoverable error flag. + * + * IDA_FIRST_RES_FAIL The user's residual routine returned + * a recoverable error flag on the first call, + * but IDACalcIC was unable to recover. + * + * IDA_LSETUP_FAIL The linear solver's setup routine had a + * non-recoverable error. + * + * IDA_LSOLVE_FAIL The linear solver's solve routine had a + * non-recoverable error. + * + * IDA_NO_RECOVERY The user's residual routine, or the linear + * solver's setup or solve routine had a + * recoverable error, but IDACalcIC was + * unable to recover. + * + * IDA_CONSTR_FAIL IDACalcIC was unable to find a solution + * satisfying the inequality constraints. + * + * IDA_LINESEARCH_FAIL The Linesearch algorithm failed to find a + * solution with a step larger than steptol + * in weighted RMS norm. + * + * IDA_CONV_FAIL IDACalcIC failed to get convergence of the + * Newton iterations. + * + * ---------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDACalcIC(void *ida_mem, int icopt, realtype tout1); + +/* + * ---------------------------------------------------------------- + * Function : IDASolve + * ---------------------------------------------------------------- + * IDASolve integrates the DAE over an interval in t, the + * independent variable. If itask is IDA_NORMAL, then the solver + * integrates from its current internal t value to a point at or + * beyond tout, then interpolates to t = tout and returns y(tret) + * in the user-allocated vector yret. In general, tret = tout. + * If itask is IDA_ONE_STEP, then the solver takes one internal + * step of the independent variable and returns in yret the value + * of y at the new internal independent variable value. In this + * case, tout is used only during the first call to IDASolve to + * determine the direction of integration and the rough scale of + * the problem. If tstop is enabled (through a call to IDASetStopTime), + * then IDASolve returns the solution at tstop. Once the integrator + * returns at a tstop time, any future testing for tstop is disabled + * (and can be reenabled only though a new call to IDASetStopTime). + * The time reached by the solver is placed in (*tret). The + * user is responsible for allocating the memory for this value. + * + * ida_mem is the pointer (void) to IDA memory returned by + * IDACreate. + * + * tout is the next independent variable value at which a + * computed solution is desired. + * + * tret is a pointer to a real location. IDASolve sets (*tret) + * to the actual t value reached, corresponding to the + * solution vector yret. In IDA_NORMAL mode, with no + * errors and no roots found, (*tret) = tout. + * + * yret is the computed solution vector. With no errors, + * yret = y(tret). + * + * ypret is the derivative of the computed solution at t = tret. + * + * Note: yret and ypret may be the same N_Vectors as y0 and yp0 + * in the call to IDAInit or IDAReInit. + * + * itask is IDA_NORMAL or IDA_ONE_STEP. These two modes are described above. + * + * + * The return values for IDASolve are described below. + * (The numerical return values are defined above in this file.) + * All unsuccessful returns give a negative return value. + * + * IDA_SUCCESS + * IDASolve succeeded and no roots were found. + * + * IDA_ROOT_RETURN: IDASolve succeeded, and found one or more roots. + * If nrtfn > 1, call IDAGetRootInfo to see which g_i were found + * to have a root at (*tret). + * + * IDA_TSTOP_RETURN: + * IDASolve returns computed results for the independent variable + * value tstop. That is, tstop was reached. + * + * IDA_MEM_NULL: + * The IDA_mem argument was NULL. + * + * IDA_ILL_INPUT: + * One of the inputs to IDASolve is illegal. This includes the + * situation when a component of the error weight vectors + * becomes < 0 during internal stepping. It also includes the + * situation where a root of one of the root functions was found + * both at t0 and very near t0. The ILL_INPUT flag + * will also be returned if the linear solver function IDA--- + * (called by the user after calling IDACreate) failed to set one + * of the linear solver-related fields in ida_mem or if the linear + * solver's init routine failed. In any case, the user should see + * the printed error message for more details. + * + * IDA_TOO_MUCH_WORK: + * The solver took mxstep internal steps but could not reach tout. + * The default value for mxstep is MXSTEP_DEFAULT = 500. + * + * IDA_TOO_MUCH_ACC: + * The solver could not satisfy the accuracy demanded by the user + * for some internal step. + * + * IDA_ERR_FAIL: + * Error test failures occurred too many times (=MXETF = 10) during + * one internal step. + * + * IDA_CONV_FAIL: + * Convergence test failures occurred too many times (= MXNCF = 10) + * during one internal step. + * + * IDA_LSETUP_FAIL: + * The linear solver's setup routine failed + * in an unrecoverable manner. + * + * IDA_LSOLVE_FAIL: + * The linear solver's solve routine failed + * in an unrecoverable manner. + * + * IDA_CONSTR_FAIL: + * The inequality constraints were violated, + * and the solver was unable to recover. + * + * IDA_REP_RES_ERR: + * The user's residual function repeatedly returned a recoverable + * error flag, but the solver was unable to recover. + * + * IDA_RES_FAIL: + * The user's residual function returned a nonrecoverable error + * flag. + * + * ---------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDASolve(void *ida_mem, realtype tout, realtype *tret, + N_Vector yret, N_Vector ypret, int itask); + +/* + * ---------------------------------------------------------------- + * Function: IDAGetSolution + * ---------------------------------------------------------------- + * + * This routine evaluates y(t) and y'(t) as the value and + * derivative of the interpolating polynomial at the independent + * variable t, and stores the results in the vectors yret and + * ypret. It uses the current independent variable value, tn, + * and the method order last used, kused. This function is + * called by IDASolve with t = tout, t = tn, or t = tstop. + * + * If kused = 0 (no step has been taken), or if t = tn, then the + * order used here is taken to be 1, giving yret = phi[0], + * ypret = phi[1]/psi[0]. + * + * The return values are: + * IDA_SUCCESS: succeess. + * IDA_BAD_T: t is not in the interval [tn-hu,tn]. + * IDA_MEM_NULL: The ida_mem argument was NULL. + * + * ---------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDAGetSolution(void *ida_mem, realtype t, + N_Vector yret, N_Vector ypret); + +/* ---------------------------------------------------------------- + * Integrator optional output extraction functions + * ---------------------------------------------------------------- + * + * The following functions can be called to get optional outputs + * and statistics related to the main integrator. + * ---------------------------------------------------------------- + * + * IDAGetWorkSpace returns the IDA real and integer workspace sizes + * IDAGetNumSteps returns the cumulative number of internal + * steps taken by the solver + * IDAGetNumRhsEvals returns the number of calls to the user's + * res function + * IDAGetNumLinSolvSetups returns the number of calls made to + * the linear solver's setup routine + * IDAGetNumErrTestFails returns the number of local error test + * failures that have occured + * IDAGetNumBacktrackOps returns the number of backtrack + * operations done in the linesearch algorithm in IDACalcIC + * IDAGetConsistentIC returns the consistent initial conditions + * computed by IDACalcIC + * IDAGetLastOrder returns the order used during the last + * internal step + * IDAGetCurentOrder returns the order to be used on the next + * internal step + * IDAGetActualInitStep returns the actual initial step size + * used by IDA + * IDAGetLAstStep returns the step size for the last internal + * step (if from IDASolve), or the last value of the + * artificial step size h (if from IDACalcIC) + * IDAGetCurrentStep returns the step size to be attempted on the + * next internal step + * IDAGetCurrentTime returns the current internal time reached + * by the solver + * IDAGetTolScaleFactor returns a suggested factor by which the + * user's tolerances should be scaled when too much + * accuracy has been requested for some internal step + * IDAGetErrWeights returns the current state error weight vector. + * The user must allocate space for eweight. + * IDAGetEstLocalErrors returns the estimated local errors. The user + * must allocate space for the vector ele. + * IDAGetNumGEvals returns the number of calls to the user's + * g function (for rootfinding) + * IDAGetRootInfo returns the indices for which g_i was found to + * have a root. The user must allocate space for rootsfound. + * For i = 0 ... nrtfn-1, rootsfound[i] = 1 if g_i has a root, + * and rootsfound[i]= 0 if not. + * + * IDAGet* return values: + * IDA_SUCCESS if succesful + * IDA_MEM_NULL if the ida memory was NULL + * IDA_ILL_INPUT if some input is illegal + * + * ---------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDAGetWorkSpace(void *ida_mem, long int *lenrw, long int *leniw); +SUNDIALS_EXPORT int IDAGetNumSteps(void *ida_mem, long int *nsteps); +SUNDIALS_EXPORT int IDAGetNumResEvals(void *ida_mem, long int *nrevals); +SUNDIALS_EXPORT int IDAGetNumLinSolvSetups(void *ida_mem, long int *nlinsetups); +SUNDIALS_EXPORT int IDAGetNumErrTestFails(void *ida_mem, long int *netfails); +SUNDIALS_EXPORT int IDAGetNumBacktrackOps(void *ida_mem, long int *nbacktr); +SUNDIALS_EXPORT int IDAGetConsistentIC(void *ida_mem, N_Vector yy0_mod, N_Vector yp0_mod); +SUNDIALS_EXPORT int IDAGetLastOrder(void *ida_mem, int *klast); +SUNDIALS_EXPORT int IDAGetCurrentOrder(void *ida_mem, int *kcur); +SUNDIALS_EXPORT int IDAGetActualInitStep(void *ida_mem, realtype *hinused); +SUNDIALS_EXPORT int IDAGetLastStep(void *ida_mem, realtype *hlast); +SUNDIALS_EXPORT int IDAGetCurrentStep(void *ida_mem, realtype *hcur); +SUNDIALS_EXPORT int IDAGetCurrentTime(void *ida_mem, realtype *tcur); +SUNDIALS_EXPORT int IDAGetTolScaleFactor(void *ida_mem, realtype *tolsfact); +SUNDIALS_EXPORT int IDAGetErrWeights(void *ida_mem, N_Vector eweight); +SUNDIALS_EXPORT int IDAGetEstLocalErrors(void *ida_mem, N_Vector ele); +SUNDIALS_EXPORT int IDAGetNumGEvals(void *ida_mem, long int *ngevals); +SUNDIALS_EXPORT int IDAGetRootInfo(void *ida_mem, int *rootsfound); + +/* + * ---------------------------------------------------------------- + * As a convenience, the following function provides the + * optional outputs in a group. + * ---------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDAGetIntegratorStats(void *ida_mem, long int *nsteps, + long int *nrevals, long int *nlinsetups, + long int *netfails, int *qlast, int *qcur, + realtype *hinused, realtype *hlast, realtype *hcur, + realtype *tcur); + +/* + * ---------------------------------------------------------------- + * Nonlinear solver optional output extraction functions + * ---------------------------------------------------------------- + * + * The following functions can be called to get optional outputs + * and statistics related to the nonlinear solver. + * -------------------------------------------------------------- + * + * IDAGetNumNonlinSolvIters returns the number of nonlinear + * solver iterations performed. + * IDAGetNumNonlinSolvConvFails returns the number of nonlinear + * convergence failures. + * + * ---------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDAGetNumNonlinSolvIters(void *ida_mem, long int *nniters); +SUNDIALS_EXPORT int IDAGetNumNonlinSolvConvFails(void *ida_mem, long int *nncfails); + +/* + * ---------------------------------------------------------------- + * As a convenience, the following function provides the + * nonlinear solver optional outputs in a group. + * ---------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDAGetNonlinSolvStats(void *ida_mem, long int *nniters, + long int *nncfails); + +/* + * ----------------------------------------------------------------- + * The following function returns the name of the constant + * associated with an IDA return flag + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT char *IDAGetReturnFlagName(int flag); + +/* + * ---------------------------------------------------------------- + * Function : IDAFree + * ---------------------------------------------------------------- + * IDAFree frees the problem memory IDA_mem allocated by + * IDAInit. Its only argument is the pointer idamem + * returned by IDAInit. + * ---------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void IDAFree(void **ida_mem); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/ida/ida_band.h b/odemex/Parser/CVode/ida_src/include/ida/ida_band.h new file mode 100644 index 0000000..acdcd9b --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/ida/ida_band.h @@ -0,0 +1,59 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.5 $ + * $Date: 2008/04/18 19:42:37 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh, and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the IDABAND linear solver module. + * ----------------------------------------------------------------- + */ + +#ifndef _IDABAND_H +#define _IDABAND_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * Function : IDABand + * ----------------------------------------------------------------- + * A call to the IDABand function links the main integrator + * with the IDABAND linear solver module. + * + * ida_mem is the pointer to the integrator memory returned by + * IDACreate. + * + * mupper is the upper bandwidth of the banded Jacobian matrix. + * + * mlower is the lower bandwidth of the banded Jacobian matrix. + * + * The return values of IDABand are: + * IDADLS_SUCCESS = 0 if successful + * IDADLS_LMEM_FAIL = -1 if there was a memory allocation failure + * IDADLS_ILL_INPUT = -2 if the input was illegal or NVECTOR bad. + * + * NOTE: The band linear solver assumes a serial implementation + * of the NVECTOR package. Therefore, IDABand will first + * test for a compatible N_Vector internal representation + * by checking that the N_VGetArrayPointer function exists. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDABand(void *ida_mem, int Neq, int mupper, int mlower); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/ida/ida_bbdpre.h b/odemex/Parser/CVode/ida_src/include/ida/ida_bbdpre.h new file mode 100644 index 0000000..24d2956 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/ida/ida_bbdpre.h @@ -0,0 +1,275 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.7 $ + * $Date: 2007/11/26 16:19:59 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh, Radu Serban and + * Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the IDABBDPRE module, for a + * band-block-diagonal preconditioner, i.e. a block-diagonal + * matrix with banded blocks, for use with IDA and + * IDASPGMR/IDASPBCG/IDASPTFQMR. + * + * Summary: + * + * These routines provide a preconditioner matrix that is + * block-diagonal with banded blocks. The blocking corresponds + * to the distribution of the dependent variable vector y among + * the processors. Each preconditioner block is generated from + * the Jacobian of the local part (on the current processor) of a + * given function G(t,y,y') approximating F(t,y,y'). The blocks + * are generated by a difference quotient scheme on each processor + * independently. This scheme utilizes an assumed banded structure + * with given half-bandwidths, mudq and mldq. However, the banded + * Jacobian block kept by the scheme has half-bandwiths mukeep and + * mlkeep, which may be smaller. + * + * The user's calling program should have the following form: + * + * #include + * #include + * ... + * y0 = N_VNew_Parallel(...); + * yp0 = N_VNew_Parallel(...); + * ... + * ida_mem = IDACreate(...); + * ier = IDAInit(...); + * ... + * flag = IDASptfqmr(ida_mem, maxl); + * -or- + * flag = IDASpgmr(ida_mem, maxl); + * -or- + * flag = IDASpbcg(ida_mem, maxl); + * ... + * flag = IDABBDPrecInit(ida_mem, Nlocal, mudq, mldq, + * mukeep, mlkeep, dq_rel_yy, Gres, Gcomm); + * ... + * ier = IDASolve(...); + * ... + * IDAFree(&ida_mem); + * + * N_VDestroy(y0); + * N_VDestroy(yp0); + * + * The user-supplied routines required are: + * + * res is the function F(t,y,y') defining the DAE system to + * be solved: F(t,y,y') = 0. + * + * Gres is the function defining a local approximation + * G(t,y,y') to F, for the purposes of the preconditioner. + * + * Gcomm is the function performing communication needed + * for Glocal. + * + * Notes: + * + * 1) This header file is included by the user for the definition + * of the IBBDPrecData type and for needed function prototypes. + * + * 2) The IDABBDPrecInit call includes half-bandwidths mudq and + * mldq to be used in the approximate Jacobian. They need + * not be the true half-bandwidths of the Jacobian of the + * local block of G, when smaller values may provide a greater + * efficiency. Similarly, mukeep and mlkeep, specifying the + * bandwidth kept for the approximate Jacobian, need not be + * the true half-bandwidths. Also, mukeep, mlkeep, mudq, and + * mldq need not be the same on every processor. + * + * 3) The actual name of the user's res function is passed to + * IDAInit, and the names of the user's Gres and Gcomm + * functions are passed to IDABBDPrecInit. + * + * 4) The pointer to the user-defined data block user_data, which + * is set through IDASetUserData is also available to the user + * in glocal and gcomm. + * + * 5) Optional outputs specific to this module are available by + * way of routines listed below. These include work space sizes + * and the cumulative number of glocal calls. The costs + * associated with this module also include nsetups banded LU + * factorizations, nsetups gcomm calls, and nps banded + * backsolve calls, where nsetups and nps are integrator + * optional outputs. + * ----------------------------------------------------------------- + */ + +#ifndef _IDABBDPRE_H +#define _IDABBDPRE_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Type : IDABBDLocalFn + * ----------------------------------------------------------------- + * The user must supply a function G(t,y,y') which approximates + * the function F for the system F(t,y,y') = 0, and which is + * computed locally (without interprocess communication). + * (The case where G is mathematically identical to F is allowed.) + * The implementation of this function must have type IDABBDLocalFn. + * + * This function takes as input the independent variable value tt, + * the current solution vector yy, the current solution + * derivative vector yp, and a pointer to the user-defined data + * block user_data. It is to compute the local part of G(t,y,y') + * and store it in the vector gval. (Providing memory for yy and + * gval is handled within this preconditioner module.) It is + * expected that this routine will save communicated data in work + * space defined by the user, and made available to the + * preconditioner function for the problem. The user_data + * parameter is the same as that passed by the user to the + * IDASetRdata routine. + * + * An IDABBDLocalFn Gres is to return an int, defined in the same + * way as for the residual function: 0 (success), +1 or -1 (fail). + * ----------------------------------------------------------------- + */ + +typedef int (*IDABBDLocalFn)(int Nlocal, realtype tt, + N_Vector yy, N_Vector yp, N_Vector gval, + void *user_data); + +/* + * ----------------------------------------------------------------- + * Type : IDABBDCommFn + * ----------------------------------------------------------------- + * The user may supply a function of type IDABBDCommFn which + * performs all interprocess communication necessary to + * evaluate the approximate system function described above. + * + * This function takes as input the solution vectors yy and yp, + * and a pointer to the user-defined data block user_data. The + * user_data parameter is the same as that passed by the user to + * the IDASetUserData routine. + * + * The IDABBDCommFn Gcomm is expected to save communicated data in + * space defined with the structure *user_data. + * + * A IDABBDCommFn Gcomm returns an int value equal to 0 (success), + * > 0 (recoverable error), or < 0 (unrecoverable error). + * + * Each call to the IDABBDCommFn is preceded by a call to the system + * function res with the same vectors yy and yp. Thus the + * IDABBDCommFn gcomm can omit any communications done by res if + * relevant to the evaluation of the local function glocal. + * A NULL communication function can be passed to IDABBDPrecInit + * if all necessary communication was done by res. + * ----------------------------------------------------------------- + */ + +typedef int (*IDABBDCommFn)(int Nlocal, realtype tt, + N_Vector yy, N_Vector yp, + void *user_data); + +/* + * ----------------------------------------------------------------- + * Function : IDABBDPrecInit + * ----------------------------------------------------------------- + * IDABBDPrecInit allocates and initializes the BBD preconditioner. + * + * The parameters of IDABBDPrecInit are as follows: + * + * ida_mem is a pointer to the memory blockreturned by IDACreate. + * + * Nlocal is the length of the local block of the vectors yy etc. + * on the current processor. + * + * mudq, mldq are the upper and lower half-bandwidths to be used + * in the computation of the local Jacobian blocks. + * + * mukeep, mlkeep are the upper and lower half-bandwidths to be + * used in saving the Jacobian elements in the local + * block of the preconditioner matrix PP. + * + * dq_rel_yy is an optional input. It is the relative increment + * to be used in the difference quotient routine for + * Jacobian calculation in the preconditioner. The + * default is sqrt(unit roundoff), and specified by + * passing dq_rel_yy = 0. + * + * Gres is the name of the user-supplied function G(t,y,y') + * that approximates F and whose local Jacobian blocks + * are to form the preconditioner. + * + * Gcomm is the name of the user-defined function that performs + * necessary interprocess communication for the + * execution of glocal. + * + * The return value of IDABBDPrecInit is one of: + * IDASPILS_SUCCESS if no errors occurred + * IDASPILS_MEM_NULL if the integrator memory is NULL + * IDASPILS_LMEM_NULL if the linear solver memory is NULL + * IDASPILS_ILL_INPUT if an input has an illegal value + * IDASPILS_MEM_FAIL if a memory allocation request failed + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDABBDPrecInit(void *ida_mem, int Nlocal, + int mudq, int mldq, + int mukeep, int mlkeep, + realtype dq_rel_yy, + IDABBDLocalFn Gres, IDABBDCommFn Gcomm); + +/* + * ----------------------------------------------------------------- + * Function : IDABBDPrecReInit + * ----------------------------------------------------------------- + * IDABBDPrecReInit reinitializes the IDABBDPRE module when + * solving a sequence of problems of the same size with + * IDASPGMR/IDABBDPRE, IDASPBCG/IDABBDPRE, or IDASPTFQMR/IDABBDPRE + * provided there is no change in Nlocal, mukeep, or mlkeep. After + * solving one problem, and after calling IDAReInit to reinitialize + * the integrator for a subsequent problem, call IDABBDPrecReInit. + * + * All arguments have the same names and meanings as those + * of IDABBDPrecInit. + * + * The return value of IDABBDPrecReInit is one of: + * IDASPILS_SUCCESS if no errors occurred + * IDASPILS_MEM_NULL if the integrator memory is NULL + * IDASPILS_LMEM_NULL if the linear solver memory is NULL + * IDASPILS_PMEM_NULL if the preconditioner memory is NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDABBDPrecReInit(void *ida_mem, + int mudq, int mldq, + realtype dq_rel_yy); + +/* + * ----------------------------------------------------------------- + * Optional outputs for IDABBDPRE + * ----------------------------------------------------------------- + * IDABBDPrecGetWorkSpace returns the real and integer work space + * for IDABBDPRE. + * IDABBDPrecGetNumGfnEvals returns the number of calls to the + * user Gres function. + * + * The return value of IDABBDPrecGet* is one of: + * IDASPILS_SUCCESS if no errors occurred + * IDASPILS_MEM_NULL if the integrator memory is NULL + * IDASPILS_LMEM_NULL if the linear solver memory is NULL + * IDASPILS_PMEM_NULL if the preconditioner memory is NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDABBDPrecGetWorkSpace(void *ida_mem, + long int *lenrwBBDP, long int *leniwBBDP); +SUNDIALS_EXPORT int IDABBDPrecGetNumGfnEvals(void *ida_mem, long int *ngevalsBBDP); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/ida/ida_dense.h b/odemex/Parser/CVode/ida_src/include/ida/ida_dense.h new file mode 100644 index 0000000..92139a2 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/ida/ida_dense.h @@ -0,0 +1,58 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.5 $ + * $Date: 2008/04/18 19:42:37 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the IDADENSE linear solver module. + * ----------------------------------------------------------------- + */ + +#ifndef _IDADENSE_H +#define _IDADENSE_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * Function : IDADense + * ----------------------------------------------------------------- + * A call to the IDADense function links the main integrator + * with the IDADENSE linear solver module. + * + * ida_mem is the pointer to integrator memory returned by + * IDACreate. + * + * Neq is the problem size + * + * IDADense returns: + * IDADLS_SUCCESS = 0 if successful + * IDADLS_LMEM_FAIL = -1 if there was a memory allocation failure + * IDADLS_ILL_INPUT = -2 if NVECTOR found incompatible + * + * NOTE: The dense linear solver assumes a serial implementation + * of the NVECTOR package. Therefore, IDADense will first + * test for a compatible N_Vector internal representation + * by checking that the functions N_VGetArrayPointer and + * N_VSetArrayPointer exist. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDADense(void *ida_mem, int Neq); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/ida/ida_direct.h b/odemex/Parser/CVode/ida_src/include/ida/ida_direct.h new file mode 100644 index 0000000..55ec153 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/ida/ida_direct.h @@ -0,0 +1,300 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2008/04/18 19:42:37 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Common header file for the direct linear solvers in IDA. + * ----------------------------------------------------------------- + */ + +#ifndef _IDADLS_H +#define _IDADLS_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ================================================================= + * I D A D I R E C T C O N S T A N T S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * IDADLS return values + * ----------------------------------------------------------------- + */ + +#define IDADLS_SUCCESS 0 +#define IDADLS_MEM_NULL -1 +#define IDADLS_LMEM_NULL -2 +#define IDADLS_ILL_INPUT -3 +#define IDADLS_MEM_FAIL -4 + +/* Additional last_flag values */ + +#define IDADLS_JACFUNC_UNRECVR -5 +#define IDADLS_JACFUNC_RECVR -6 + +/* + * ================================================================= + * F U N C T I O N T Y P E S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Types : IDADlsDenseJacFn + * ----------------------------------------------------------------- + * + * A dense Jacobian approximation function djac must be of type + * IDADlsDenseJacFn. + * Its parameters are: + * + * N is the problem size, and length of all vector arguments. + * + * t is the current value of the independent variable t. + * + * y is the current value of the dependent variable vector, + * namely the predicted value of y(t). + * + * yp is the current value of the derivative vector y', + * namely the predicted value of y'(t). + * + * f is the residual vector F(tt,yy,yp). + * + * c_j is the scalar in the system Jacobian, proportional to + * the inverse of the step size h. + * + * user_data is a pointer to user Jacobian data - the same as the + * user_data parameter passed to IDASetRdata. + * + * Jac is the dense matrix (of type DlsMat) to be loaded by + * an IDADlsDenseJacFn routine with an approximation to the + * system Jacobian matrix + * J = dF/dy' + gamma*dF/dy + * at the given point (t,y,y'), where the ODE system is + * given by F(t,y,y') = 0. + * Note that Jac is NOT preset to zero! + * + * tmp1, tmp2, tmp3 are pointers to memory allocated for + * N_Vectors which can be used by an IDADlsDenseJacFn routine + * as temporary storage or work space. + * + * A IDADlsDenseJacFn should return + * 0 if successful, + * a positive int if a recoverable error occurred, or + * a negative int if a nonrecoverable error occurred. + * In the case of a recoverable error return, the integrator will + * attempt to recover by reducing the stepsize (which changes cj). + * + * ----------------------------------------------------------------- + * + * NOTE: The following are two efficient ways to load a dense Jac: + * (1) (with macros - no explicit data structure references) + * for (j=0; j < Neq; j++) { + * col_j = LAPACK_DENSE_COL(Jac,j); + * for (i=0; i < Neq; i++) { + * generate J_ij = the (i,j)th Jacobian element + * col_j[i] = J_ij; + * } + * } + * (2) (without macros - explicit data structure references) + * for (j=0; j < Neq; j++) { + * col_j = (Jac->data)[j]; + * for (i=0; i < Neq; i++) { + * generate J_ij = the (i,j)th Jacobian element + * col_j[i] = J_ij; + * } + * } + * A third way, using the LAPACK_DENSE_ELEM(A,i,j) macro, is much less + * efficient in general. It is only appropriate for use in small + * problems in which efficiency of access is NOT a major concern. + * + * NOTE: If the user's Jacobian routine needs other quantities, + * they are accessible as follows: hcur (the current stepsize) + * and ewt (the error weight vector) are accessible through + * IDAGetCurrentStep and IDAGetErrWeights, respectively + * (see ida.h). The unit roundoff is available as + * UNIT_ROUNDOFF defined in sundials_types.h. + * + * ----------------------------------------------------------------- + */ + + +typedef int (*IDADlsDenseJacFn)(int N, realtype t, realtype c_j, + N_Vector y, N_Vector yp, N_Vector r, + DlsMat Jac, void *user_data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +/* + * ----------------------------------------------------------------- + * Types : IDADlsBandJacFn + * ----------------------------------------------------------------- + * A banded Jacobian approximation function bjac must have the + * prototype given below. Its parameters are: + * + * Neq is the problem size, and length of all vector arguments. + * + * mupper is the upper bandwidth of the banded Jacobian matrix. + * + * mlower is the lower bandwidth of the banded Jacobian matrix. + * + * tt is the current value of the independent variable t. + * + * yy is the current value of the dependent variable vector, + * namely the predicted value of y(t). + * + * yp is the current value of the derivative vector y', + * namely the predicted value of y'(t). + * + * rr is the residual vector F(tt,yy,yp). + * + * c_j is the scalar in the system Jacobian, proportional to 1/hh. + * + * user_data is a pointer to user Jacobian data - the same as the + * user_data parameter passed to IDASetRdata. + * + * Jac is the band matrix (of type BandMat) to be loaded by + * an IDADlsBandJacFn routine with an approximation to the + * system Jacobian matrix + * J = dF/dy + cj*dF/dy' + * at the given point (t,y,y'), where the DAE system is + * given by F(t,y,y') = 0. Jac is preset to zero, so only + * the nonzero elements need to be loaded. See note below. + * + * tmp1, tmp2, tmp3 are pointers to memory allocated for + * N_Vectors which can be used by an IDADlsBandJacFn routine + * as temporary storage or work space. + * + * An IDADlsBandJacFn function should return + * 0 if successful, + * a positive int if a recoverable error occurred, or + * a negative int if a nonrecoverable error occurred. + * In the case of a recoverable error return, the integrator will + * attempt to recover by reducing the stepsize (which changes cj). + * + * ----------------------------------------------------------------- + * + * NOTE: The following are two efficient ways to load Jac: + * + * (1) (with macros - no explicit data structure references) + * for (j=0; j < Neq; j++) { + * col_j = BAND_COL(Jac,j); + * for (i=j-mupper; i <= j+mlower; i++) { + * generate J_ij = the (i,j)th Jacobian element + * BAND_COL_ELEM(col_j,i,j) = J_ij; + * } + * } + * + * (2) (with BAND_COL macro, but without BAND_COL_ELEM macro) + * for (j=0; j < Neq; j++) { + * col_j = BAND_COL(Jac,j); + * for (k=-mupper; k <= mlower; k++) { + * generate J_ij = the (i,j)th Jacobian element, i=j+k + * col_j[k] = J_ij; + * } + * } + * + * A third way, using the BAND_ELEM(A,i,j) macro, is much less + * efficient in general. It is only appropriate for use in small + * problems in which efficiency of access is NOT a major concern. + * + * NOTE: If the user's Jacobian routine needs other quantities, + * they are accessible as follows: hcur (the current stepsize) + * and ewt (the error weight vector) are accessible through + * IDAGetCurrentStep and IDAGetErrWeights, respectively (see + * ida.h). The unit roundoff is available as + * UNIT_ROUNDOFF defined in sundials_types.h + * + * ----------------------------------------------------------------- + */ + +typedef int (*IDADlsBandJacFn)(int N, int mupper, int mlower, + realtype t, realtype c_j, + N_Vector y, N_Vector yp, N_Vector r, + DlsMat Jac, void *user_data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +/* + * ================================================================= + * E X P O R T E D F U N C T I O N S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Optional inputs to the IDADLS linear solver + * ----------------------------------------------------------------- + * IDADlsSetDenseJacFn specifies the dense Jacobian approximation + * routine to be used for a direct dense linear solver. + * + * IDADlsSetBandJacFn specifies the band Jacobian approximation + * routine to be used for a direct band linear solver. + * + * By default, a difference quotient approximation, supplied with + * the solver is used. + * + * The return value is one of: + * IDADLS_SUCCESS if successful + * IDADLS_MEM_NULL if the IDA memory was NULL + * IDADLS_LMEM_NULL if the linear solver memory was NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDADlsSetDenseJacFn(void *ida_mem, IDADlsDenseJacFn jac); +SUNDIALS_EXPORT int IDADlsSetBandJacFn(void *ida_mem, IDADlsBandJacFn jac); + +/* + * ----------------------------------------------------------------- + * Optional outputs from the IDADLS linear solver + * ----------------------------------------------------------------- + * + * IDADlsGetWorkSpace returns the real and integer workspace used + * by the direct linear solver. + * IDADlsGetNumJacEvals returns the number of calls made to the + * Jacobian evaluation routine jac. + * IDADlsGetNumResEvals returns the number of calls to the user + * f routine due to finite difference Jacobian + * evaluation. + * IDADlsGetLastFlag returns the last error flag set by any of + * the IDADLS interface functions. + * + * The return value of IDADlsGet* is one of: + * IDADLS_SUCCESS if successful + * IDADLS_MEM_NULL if the IDA memory was NULL + * IDADLS_LMEM_NULL if the linear solver memory was NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDADlsGetWorkSpace(void *ida_mem, long int *lenrwLS, long int *leniwLS); +SUNDIALS_EXPORT int IDADlsGetNumJacEvals(void *ida_mem, long int *njevals); +SUNDIALS_EXPORT int IDADlsGetNumResEvals(void *ida_mem, long int *nfevalsLS); +SUNDIALS_EXPORT int IDADlsGetLastFlag(void *ida_mem, int *flag); + +/* + * ----------------------------------------------------------------- + * The following function returns the name of the constant + * associated with a IDADLS return flag + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT char *IDADlsGetReturnFlagName(int flag); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/ida/ida_lapack.h b/odemex/Parser/CVode/ida_src/include/ida/ida_lapack.h new file mode 100644 index 0000000..a50ed5c --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/ida/ida_lapack.h @@ -0,0 +1,80 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.4 $ + * $Date: 2008/04/18 19:42:37 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Header file for the IDA dense linear solver IDALAPACK. + * ----------------------------------------------------------------- + */ + +#ifndef _IDALAPACK_H +#define _IDALAPACK_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * Function : IDALapackDense + * ----------------------------------------------------------------- + * A call to the IDALapackDense function links the main integrator + * with the IDALAPACK linear solver using dense Jacobians. + * + * ida_mem is the pointer to the integrator memory returned by + * IDACreate. + * + * N is the size of the ODE system. + * + * The return value of IDALapackDense is one of: + * IDADLS_SUCCESS if successful + * IDADLS_MEM_NULL if the IDA memory was NULL + * IDADLS_MEM_FAIL if there was a memory allocation failure + * IDADLS_ILL_INPUT if a required vector operation is missing + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDALapackDense(void *ida_mem, int N); + +/* + * ----------------------------------------------------------------- + * Function : IDALapackBand + * ----------------------------------------------------------------- + * A call to the IDALapackBand function links the main integrator + * with the IDALAPACK linear solver using banded Jacobians. + * + * ida_mem is the pointer to the integrator memory returned by + * IDACreate. + * + * N is the size of the ODE system. + * + * mupper is the upper bandwidth of the band Jacobian approximation. + * + * mlower is the lower bandwidth of the band Jacobian approximation. + * + * The return value of IDALapackBand is one of: + * IDADLS_SUCCESS if successful + * IDADLS_MEM_NULL if the IDA memory was NULL + * IDADLS_MEM_FAIL if there was a memory allocation failure + * IDADLS_ILL_INPUT if a required vector operation is missing + * or if a bandwidth has an illegal value. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDALapackBand(void *ida_mem, int N, int mupper, int mlower); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/ida/ida_spbcgs.h b/odemex/Parser/CVode/ida_src/include/ida/ida_spbcgs.h new file mode 100644 index 0000000..f733a11 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/ida/ida_spbcgs.h @@ -0,0 +1,59 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:06 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2004, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the public header file for the IDA scaled preconditioned + * Bi-CGSTAB linear solver module, IDASPBCG. + * ----------------------------------------------------------------- + */ + +#ifndef _IDASPBCG_H +#define _IDASPBCG_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * Function : IDASpbcg + * ----------------------------------------------------------------- + * A call to the IDASpbcg function links the main integrator with + * the IDASPBCG linear solver module. Its parameters are as + * follows: + * + * IDA_mem is the pointer to memory block returned by IDACreate. + * + * maxl is the maximum Krylov subspace dimension, an + * optional input. Pass 0 to use the default value. + * Otherwise pass a positive integer. + * + * The return values of IDASpbcg are: + * IDASPILS_SUCCESS if successful + * IDASPILS_MEM_NULL if the ida memory was NULL + * IDASPILS_MEM_FAIL if there was a memory allocation failure + * IDASPILS_ILL_INPUT if there was illegal input. + * The above constants are defined in ida_spils.h + * + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDASpbcg(void *ida_mem, int maxl); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/ida/ida_spgmr.h b/odemex/Parser/CVode/ida_src/include/ida/ida_spgmr.h new file mode 100644 index 0000000..3604028 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/ida/ida_spgmr.h @@ -0,0 +1,60 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:06 $ + * ----------------------------------------------------------------- + * Programmers: Alan C. Hindmarsh and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California + * Produced at the Lawrence Livermore National Laboratory + * All rights reserved + * For details, see the LICENSE file + * ----------------------------------------------------------------- + * This is the header file for the IDA Scaled Preconditioned GMRES + * linear solver module, IDASPGMR. + * ----------------------------------------------------------------- + */ + +#ifndef _IDASPGMR_H +#define _IDASPGMR_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * + * Function : IDASpgmr + * ----------------------------------------------------------------- + * A call to the IDASpgmr function links the main integrator with + * the IDASPGMR linear solver module. Its parameters are as + * follows: + * + * IDA_mem is the pointer to memory block returned by IDACreate. + * + * maxl is the maximum Krylov subspace dimension, an + * optional input. Pass 0 to use the default value, + * MIN(Neq, 5). Otherwise pass a positive integer. + * + * The return values of IDASpgmr are: + * IDASPILS_SUCCESS if successful + * IDASPILS_MEM_NULL if the ida memory was NULL + * IDASPILS_MEM_FAIL if there was a memory allocation failure + * IDASPILS_ILL_INPUT if there was illegal input. + * The above constants are defined in ida_spils.h + * + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDASpgmr(void *ida_mem, int maxl); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/ida/ida_spils.h b/odemex/Parser/CVode/ida_src/include/ida/ida_spils.h new file mode 100644 index 0000000..9bb641d --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/ida/ida_spils.h @@ -0,0 +1,321 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.8 $ + * $Date: 2007/11/26 16:19:59 $ + * ----------------------------------------------------------------- + * Programmers: Alan Hindmarsh, Radu Serban and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California + * Produced at the Lawrence Livermore National Laboratory + * All rights reserved + * For details, see the LICENSE file + * ----------------------------------------------------------------- + * This is the common header file for the Scaled and Preconditioned + * Iterative Linear Solvers in IDA. + * ----------------------------------------------------------------- + */ + +#ifndef _IDASPILS_H +#define _IDASPILS_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * IDASPILS return values + * ----------------------------------------------------------------- + */ + +#define IDASPILS_SUCCESS 0 +#define IDASPILS_MEM_NULL -1 +#define IDASPILS_LMEM_NULL -2 +#define IDASPILS_ILL_INPUT -3 +#define IDASPILS_MEM_FAIL -4 +#define IDASPILS_PMEM_NULL -5 + +/* + * ----------------------------------------------------------------- + * Type : IDASpilsPrecSetupFn + * ----------------------------------------------------------------- + * The optional user-supplied functions PrecSetup and PrecSolve + * together must define the left preconditoner matrix P + * approximating the system Jacobian matrix + * J = dF/dy + c_j*dF/dy' + * (where the DAE system is F(t,y,y') = 0), and solve the linear + * systems P z = r. PrecSetup is to do any necessary setup + * operations, and PrecSolve is to compute the solution of + * P z = r. + * + * The preconditioner setup function PrecSetup is to evaluate and + * preprocess any Jacobian-related data needed by the + * preconditioner solve function PrecSolve. This might include + * forming a crude approximate Jacobian, and performing an LU + * factorization on it. This function will not be called in + * advance of every call to PrecSolve, but instead will be called + * only as often as necessary to achieve convergence within the + * Newton iteration. If the PrecSolve function needs no + * preparation, the PrecSetup function can be NULL. + * + * Each call to the PrecSetup function is preceded by a call to + * the system function res with the same (t,y,y') arguments. + * Thus the PrecSetup function can use any auxiliary data that is + * computed and saved by the res function and made accessible + * to PrecSetup. + * + * A preconditioner setup function PrecSetup must have the + * prototype given below. Its parameters are as follows: + * + * tt is the current value of the independent variable t. + * + * yy is the current value of the dependent variable vector, + * namely the predicted value of y(t). + * + * yp is the current value of the derivative vector y', + * namely the predicted value of y'(t). + * + * rr is the current value of the residual vector F(t,y,y'). + * + * c_j is the scalar in the system Jacobian, proportional to 1/hh. + * + * user_data is a pointer to user data, the same as the user_data + * parameter passed to IDASetUserData. + * + * tmp1, tmp2, tmp3 are pointers to vectors of type N_Vector + * which can be used by an IDASpilsPrecSetupFn routine + * as temporary storage or work space. + * + * NOTE: If the user's preconditioner needs other quantities, + * they are accessible as follows: hcur (the current stepsize) + * and ewt (the error weight vector) are accessible through + * IDAGetCurrentStep and IDAGetErrWeights, respectively (see + * ida.h). The unit roundoff is available as + * UNIT_ROUNDOFF defined in sundials_types.h + * + * The IDASpilsPrecSetupFn should return + * 0 if successful, + * a positive int if a recoverable error occurred, or + * a negative int if a nonrecoverable error occurred. + * In the case of a recoverable error return, the integrator will + * attempt to recover by reducing the stepsize (which changes cj). + * ----------------------------------------------------------------- + */ + +typedef int (*IDASpilsPrecSetupFn)(realtype tt, + N_Vector yy, N_Vector yp, N_Vector rr, + realtype c_j, void *user_data, + N_Vector tmp1, N_Vector tmp2, + N_Vector tmp3); + +/* + * ----------------------------------------------------------------- + * Type : IDASpilsPrecSolveFn + * ----------------------------------------------------------------- + * The optional user-supplied function PrecSolve must compute a + * solution to the linear system P z = r, where P is the left + * preconditioner defined by the user. If no preconditioning + * is desired, pass NULL for PrecSolve to IDASp*. + * + * A preconditioner solve function PrecSolve must have the + * prototype given below. Its parameters are as follows: + * + * tt is the current value of the independent variable t. + * + * yy is the current value of the dependent variable vector y. + * + * yp is the current value of the derivative vector y'. + * + * rr is the current value of the residual vector F(t,y,y'). + * + * rvec is the input right-hand side vector r. + * + * zvec is the computed solution vector z. + * + * c_j is the scalar in the system Jacobian, proportional to 1/hh. + * + * delta is an input tolerance for use by PrecSolve if it uses an + * iterative method in its solution. In that case, the + * the residual vector r - P z of the system should be + * made less than delta in weighted L2 norm, i.e., + * sqrt [ Sum (Res[i]*ewt[i])^2 ] < delta . + * Note: the error weight vector ewt can be obtained + * through a call to the routine IDAGetErrWeights. + * + * user_data is a pointer to user data, the same as the user_data + * parameter passed to IDASetUserData. + * + * tmp is an N_Vector which can be used by the PrecSolve + * routine as temporary storage or work space. + * + * The IDASpilsPrecSolveFn should return + * 0 if successful, + * a positive int if a recoverable error occurred, or + * a negative int if a nonrecoverable error occurred. + * Following a recoverable error, the integrator will attempt to + * recover by updating the preconditioner and/or reducing the + * stepsize. + * ----------------------------------------------------------------- + */ + +typedef int (*IDASpilsPrecSolveFn)(realtype tt, + N_Vector yy, N_Vector yp, N_Vector rr, + N_Vector rvec, N_Vector zvec, + realtype c_j, realtype delta, void *user_data, + N_Vector tmp); + +/* + * ----------------------------------------------------------------- + * Type : IDASpilsJacTimesVecFn + * ----------------------------------------------------------------- + * The user-supplied function jtimes is to generate the product + * J*v for given v, where J is the Jacobian matrix + * J = dF/dy + c_j*dF/dy' + * or an approximation to it, and v is a given vector. + * It should return 0 if successful and a nonzero int otherwise. + * + * A function jtimes must have the prototype given below. Its + * parameters are as follows: + * + * tt is the current value of the independent variable. + * + * yy is the current value of the dependent variable vector, + * namely the predicted value of y(t). + * + * yp is the current value of the derivative vector y', + * namely the predicted value of y'(t). + * + * rr is the current value of the residual vector F(t,y,y'). + * + * v is the N_Vector to be multiplied by J. + * + * Jv is the output N_Vector containing J*v. + * + * c_j is the scalar in the system Jacobian, proportional + * to 1/hh. + * + * user_data is a pointer to user data, the same as the + * pointer passed to IDASetUserData. + * + * tmp1, tmp2 are two N_Vectors which can be used by Jtimes for + * work space. + * ----------------------------------------------------------------- + */ + +typedef int (*IDASpilsJacTimesVecFn)(realtype tt, + N_Vector yy, N_Vector yp, N_Vector rr, + N_Vector v, N_Vector Jv, + realtype c_j, void *user_data, + N_Vector tmp1, N_Vector tmp2); + + +/* + * ----------------------------------------------------------------- + * Optional inputs to the IDASPILS linear solver + * ----------------------------------------------------------------- + * + * IDASpilsSetPreconditioner specifies the PrecSetup and PrecSolve + * functions. + * Default is NULL for both arguments. + * IDASpilsSetJacTimesVecFn specifies the jtimes function. + * Default is to use an internal finite difference + * approximation routine. + * IDASpilsSetGSType specifies the type of Gram-Schmidt + * orthogonalization to be used. This must be one of + * the two enumeration constants MODIFIED_GS or + * CLASSICAL_GS defined in iterativ.h. These correspond + * to using modified Gram-Schmidt and classical + * Gram-Schmidt, respectively. + * Default value is MODIFIED_GS. + * Only for IDASPGMR. + * IDASpilsSetMaxRestarts specifies the maximum number of restarts + * to be used in the GMRES algorithm. maxrs must be a + * non-negative integer. Pass 0 to specify no restarts. + * Default is 5. + * Only for IDASPGMR. + * IDASpbcgSetMaxl specifies the maximum Krylov subspace size. + * Default is 5. + * Only for IDASPBCG and IDASPTFQMR. + * IDASpilsSetEpsLin specifies the factor in the linear iteration + * convergence test constant. + * Default is 0.05 + * IDASpilsSetIncrementFactor specifies a factor in the increments + * to yy used in the difference quotient approximations + * to matrix-vector products Jv. + * Default is 1.0 + * + * The return value of IDASpilsSet* is one of: + * IDASPILS_SUCCESS if successful + * IDASPILS_MEM_NULL if the ida memory was NULL + * IDASPILS_LMEM_NULL if the linear solver memory was NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDASpilsSetPreconditioner(void *ida_mem, + IDASpilsPrecSetupFn pset, + IDASpilsPrecSolveFn psolve); +SUNDIALS_EXPORT int IDASpilsSetJacTimesVecFn(void *ida_mem, + IDASpilsJacTimesVecFn jtv); + +SUNDIALS_EXPORT int IDASpilsSetGSType(void *ida_mem, int gstype); +SUNDIALS_EXPORT int IDASpilsSetMaxRestarts(void *ida_mem, int maxrs); +SUNDIALS_EXPORT int IDASpilsSetMaxl(void *ida_mem, int maxl); +SUNDIALS_EXPORT int IDASpilsSetEpsLin(void *ida_mem, realtype eplifac); +SUNDIALS_EXPORT int IDASpilsSetIncrementFactor(void *ida_mem, realtype dqincfac); + +/* + * ----------------------------------------------------------------- + * Optional outputs from the IDASPILS linear solver + *---------------------------------------------------------------- + * + * IDASpilsGetWorkSpace returns the real and integer workspace used + * by IDASPILS. + * IDASpilsGetNumPrecEvals returns the number of preconditioner + * evaluations, i.e. the number of calls made to PrecSetup + * with jok==FALSE. + * IDASpilsGetNumPrecSolves returns the number of calls made to + * PrecSolve. + * IDASpilsGetNumLinIters returns the number of linear iterations. + * IDASpilsGetNumConvFails returns the number of linear + * convergence failures. + * IDASpilsGetNumJtimesEvals returns the number of calls to jtimes + * IDASpilsGetNumResEvals returns the number of calls to the user + * res routine due to finite difference Jacobian times vector + * evaluation. + * IDASpilsGetLastFlag returns the last error flag set by any of + * the IDASPILS interface functions. + * + * The return value of IDASpilsGet* is one of: + * IDASPILS_SUCCESS if successful + * IDASPILS_MEM_NULL if the ida memory was NULL + * IDASPILS_LMEM_NULL if the linear solver memory was NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDASpilsGetWorkSpace(void *ida_mem, long int *lenrwLS, long int *leniwLS); +SUNDIALS_EXPORT int IDASpilsGetNumPrecEvals(void *ida_mem, long int *npevals); +SUNDIALS_EXPORT int IDASpilsGetNumPrecSolves(void *ida_mem, long int *npsolves); +SUNDIALS_EXPORT int IDASpilsGetNumLinIters(void *ida_mem, long int *nliters); +SUNDIALS_EXPORT int IDASpilsGetNumConvFails(void *ida_mem, long int *nlcfails); +SUNDIALS_EXPORT int IDASpilsGetNumJtimesEvals(void *ida_mem, long int *njvevals); +SUNDIALS_EXPORT int IDASpilsGetNumResEvals(void *ida_mem, long int *nrevalsLS); +SUNDIALS_EXPORT int IDASpilsGetLastFlag(void *ida_mem, int *flag); + +/* + * ----------------------------------------------------------------- + * The following function returns the name of the constant + * associated with an IDASPILS return flag + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT char *IDASpilsGetReturnFlagName(int flag); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/ida/ida_sptfqmr.h b/odemex/Parser/CVode/ida_src/include/ida/ida_sptfqmr.h new file mode 100644 index 0000000..a7a32b5 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/ida/ida_sptfqmr.h @@ -0,0 +1,59 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the public header file for the IDA scaled preconditioned + * TFQMR linear solver module, IDASPTFQMR. + * ----------------------------------------------------------------- + */ + +#ifndef _IDASPTFQMR_H +#define _IDASPTFQMR_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * Function : IDASptfqmr + * ----------------------------------------------------------------- + * A call to the IDASptfqmr function links the main integrator with + * the IDASPTFQMR linear solver module. Its parameters are as + * follows: + * + * IDA_mem is the pointer to memory block returned by IDACreate. + * + * maxl is the maximum Krylov subspace dimension, an + * optional input. Pass 0 to use the default value. + * Otherwise pass a positive integer. + * + * The return values of IDASptfqmr are: + * IDASPILS_SUCCESS if successful + * IDASPILS_MEM_NULL if the ida memory was NULL + * IDASPILS_MEM_FAIL if there was a memory allocation failure + * IDASPILS_ILL_INPUT if there was illegal input. + * The above constants are defined in ida_spils.h + * + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDASptfqmr(void *ida_mem, int maxl); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/ida_band.h b/odemex/Parser/CVode/ida_src/include/ida_band.h new file mode 100644 index 0000000..acdcd9b --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/ida_band.h @@ -0,0 +1,59 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.5 $ + * $Date: 2008/04/18 19:42:37 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh, and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the IDABAND linear solver module. + * ----------------------------------------------------------------- + */ + +#ifndef _IDABAND_H +#define _IDABAND_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * Function : IDABand + * ----------------------------------------------------------------- + * A call to the IDABand function links the main integrator + * with the IDABAND linear solver module. + * + * ida_mem is the pointer to the integrator memory returned by + * IDACreate. + * + * mupper is the upper bandwidth of the banded Jacobian matrix. + * + * mlower is the lower bandwidth of the banded Jacobian matrix. + * + * The return values of IDABand are: + * IDADLS_SUCCESS = 0 if successful + * IDADLS_LMEM_FAIL = -1 if there was a memory allocation failure + * IDADLS_ILL_INPUT = -2 if the input was illegal or NVECTOR bad. + * + * NOTE: The band linear solver assumes a serial implementation + * of the NVECTOR package. Therefore, IDABand will first + * test for a compatible N_Vector internal representation + * by checking that the N_VGetArrayPointer function exists. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDABand(void *ida_mem, int Neq, int mupper, int mlower); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/ida_bbdpre.h b/odemex/Parser/CVode/ida_src/include/ida_bbdpre.h new file mode 100644 index 0000000..24d2956 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/ida_bbdpre.h @@ -0,0 +1,275 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.7 $ + * $Date: 2007/11/26 16:19:59 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh, Radu Serban and + * Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the IDABBDPRE module, for a + * band-block-diagonal preconditioner, i.e. a block-diagonal + * matrix with banded blocks, for use with IDA and + * IDASPGMR/IDASPBCG/IDASPTFQMR. + * + * Summary: + * + * These routines provide a preconditioner matrix that is + * block-diagonal with banded blocks. The blocking corresponds + * to the distribution of the dependent variable vector y among + * the processors. Each preconditioner block is generated from + * the Jacobian of the local part (on the current processor) of a + * given function G(t,y,y') approximating F(t,y,y'). The blocks + * are generated by a difference quotient scheme on each processor + * independently. This scheme utilizes an assumed banded structure + * with given half-bandwidths, mudq and mldq. However, the banded + * Jacobian block kept by the scheme has half-bandwiths mukeep and + * mlkeep, which may be smaller. + * + * The user's calling program should have the following form: + * + * #include + * #include + * ... + * y0 = N_VNew_Parallel(...); + * yp0 = N_VNew_Parallel(...); + * ... + * ida_mem = IDACreate(...); + * ier = IDAInit(...); + * ... + * flag = IDASptfqmr(ida_mem, maxl); + * -or- + * flag = IDASpgmr(ida_mem, maxl); + * -or- + * flag = IDASpbcg(ida_mem, maxl); + * ... + * flag = IDABBDPrecInit(ida_mem, Nlocal, mudq, mldq, + * mukeep, mlkeep, dq_rel_yy, Gres, Gcomm); + * ... + * ier = IDASolve(...); + * ... + * IDAFree(&ida_mem); + * + * N_VDestroy(y0); + * N_VDestroy(yp0); + * + * The user-supplied routines required are: + * + * res is the function F(t,y,y') defining the DAE system to + * be solved: F(t,y,y') = 0. + * + * Gres is the function defining a local approximation + * G(t,y,y') to F, for the purposes of the preconditioner. + * + * Gcomm is the function performing communication needed + * for Glocal. + * + * Notes: + * + * 1) This header file is included by the user for the definition + * of the IBBDPrecData type and for needed function prototypes. + * + * 2) The IDABBDPrecInit call includes half-bandwidths mudq and + * mldq to be used in the approximate Jacobian. They need + * not be the true half-bandwidths of the Jacobian of the + * local block of G, when smaller values may provide a greater + * efficiency. Similarly, mukeep and mlkeep, specifying the + * bandwidth kept for the approximate Jacobian, need not be + * the true half-bandwidths. Also, mukeep, mlkeep, mudq, and + * mldq need not be the same on every processor. + * + * 3) The actual name of the user's res function is passed to + * IDAInit, and the names of the user's Gres and Gcomm + * functions are passed to IDABBDPrecInit. + * + * 4) The pointer to the user-defined data block user_data, which + * is set through IDASetUserData is also available to the user + * in glocal and gcomm. + * + * 5) Optional outputs specific to this module are available by + * way of routines listed below. These include work space sizes + * and the cumulative number of glocal calls. The costs + * associated with this module also include nsetups banded LU + * factorizations, nsetups gcomm calls, and nps banded + * backsolve calls, where nsetups and nps are integrator + * optional outputs. + * ----------------------------------------------------------------- + */ + +#ifndef _IDABBDPRE_H +#define _IDABBDPRE_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Type : IDABBDLocalFn + * ----------------------------------------------------------------- + * The user must supply a function G(t,y,y') which approximates + * the function F for the system F(t,y,y') = 0, and which is + * computed locally (without interprocess communication). + * (The case where G is mathematically identical to F is allowed.) + * The implementation of this function must have type IDABBDLocalFn. + * + * This function takes as input the independent variable value tt, + * the current solution vector yy, the current solution + * derivative vector yp, and a pointer to the user-defined data + * block user_data. It is to compute the local part of G(t,y,y') + * and store it in the vector gval. (Providing memory for yy and + * gval is handled within this preconditioner module.) It is + * expected that this routine will save communicated data in work + * space defined by the user, and made available to the + * preconditioner function for the problem. The user_data + * parameter is the same as that passed by the user to the + * IDASetRdata routine. + * + * An IDABBDLocalFn Gres is to return an int, defined in the same + * way as for the residual function: 0 (success), +1 or -1 (fail). + * ----------------------------------------------------------------- + */ + +typedef int (*IDABBDLocalFn)(int Nlocal, realtype tt, + N_Vector yy, N_Vector yp, N_Vector gval, + void *user_data); + +/* + * ----------------------------------------------------------------- + * Type : IDABBDCommFn + * ----------------------------------------------------------------- + * The user may supply a function of type IDABBDCommFn which + * performs all interprocess communication necessary to + * evaluate the approximate system function described above. + * + * This function takes as input the solution vectors yy and yp, + * and a pointer to the user-defined data block user_data. The + * user_data parameter is the same as that passed by the user to + * the IDASetUserData routine. + * + * The IDABBDCommFn Gcomm is expected to save communicated data in + * space defined with the structure *user_data. + * + * A IDABBDCommFn Gcomm returns an int value equal to 0 (success), + * > 0 (recoverable error), or < 0 (unrecoverable error). + * + * Each call to the IDABBDCommFn is preceded by a call to the system + * function res with the same vectors yy and yp. Thus the + * IDABBDCommFn gcomm can omit any communications done by res if + * relevant to the evaluation of the local function glocal. + * A NULL communication function can be passed to IDABBDPrecInit + * if all necessary communication was done by res. + * ----------------------------------------------------------------- + */ + +typedef int (*IDABBDCommFn)(int Nlocal, realtype tt, + N_Vector yy, N_Vector yp, + void *user_data); + +/* + * ----------------------------------------------------------------- + * Function : IDABBDPrecInit + * ----------------------------------------------------------------- + * IDABBDPrecInit allocates and initializes the BBD preconditioner. + * + * The parameters of IDABBDPrecInit are as follows: + * + * ida_mem is a pointer to the memory blockreturned by IDACreate. + * + * Nlocal is the length of the local block of the vectors yy etc. + * on the current processor. + * + * mudq, mldq are the upper and lower half-bandwidths to be used + * in the computation of the local Jacobian blocks. + * + * mukeep, mlkeep are the upper and lower half-bandwidths to be + * used in saving the Jacobian elements in the local + * block of the preconditioner matrix PP. + * + * dq_rel_yy is an optional input. It is the relative increment + * to be used in the difference quotient routine for + * Jacobian calculation in the preconditioner. The + * default is sqrt(unit roundoff), and specified by + * passing dq_rel_yy = 0. + * + * Gres is the name of the user-supplied function G(t,y,y') + * that approximates F and whose local Jacobian blocks + * are to form the preconditioner. + * + * Gcomm is the name of the user-defined function that performs + * necessary interprocess communication for the + * execution of glocal. + * + * The return value of IDABBDPrecInit is one of: + * IDASPILS_SUCCESS if no errors occurred + * IDASPILS_MEM_NULL if the integrator memory is NULL + * IDASPILS_LMEM_NULL if the linear solver memory is NULL + * IDASPILS_ILL_INPUT if an input has an illegal value + * IDASPILS_MEM_FAIL if a memory allocation request failed + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDABBDPrecInit(void *ida_mem, int Nlocal, + int mudq, int mldq, + int mukeep, int mlkeep, + realtype dq_rel_yy, + IDABBDLocalFn Gres, IDABBDCommFn Gcomm); + +/* + * ----------------------------------------------------------------- + * Function : IDABBDPrecReInit + * ----------------------------------------------------------------- + * IDABBDPrecReInit reinitializes the IDABBDPRE module when + * solving a sequence of problems of the same size with + * IDASPGMR/IDABBDPRE, IDASPBCG/IDABBDPRE, or IDASPTFQMR/IDABBDPRE + * provided there is no change in Nlocal, mukeep, or mlkeep. After + * solving one problem, and after calling IDAReInit to reinitialize + * the integrator for a subsequent problem, call IDABBDPrecReInit. + * + * All arguments have the same names and meanings as those + * of IDABBDPrecInit. + * + * The return value of IDABBDPrecReInit is one of: + * IDASPILS_SUCCESS if no errors occurred + * IDASPILS_MEM_NULL if the integrator memory is NULL + * IDASPILS_LMEM_NULL if the linear solver memory is NULL + * IDASPILS_PMEM_NULL if the preconditioner memory is NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDABBDPrecReInit(void *ida_mem, + int mudq, int mldq, + realtype dq_rel_yy); + +/* + * ----------------------------------------------------------------- + * Optional outputs for IDABBDPRE + * ----------------------------------------------------------------- + * IDABBDPrecGetWorkSpace returns the real and integer work space + * for IDABBDPRE. + * IDABBDPrecGetNumGfnEvals returns the number of calls to the + * user Gres function. + * + * The return value of IDABBDPrecGet* is one of: + * IDASPILS_SUCCESS if no errors occurred + * IDASPILS_MEM_NULL if the integrator memory is NULL + * IDASPILS_LMEM_NULL if the linear solver memory is NULL + * IDASPILS_PMEM_NULL if the preconditioner memory is NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDABBDPrecGetWorkSpace(void *ida_mem, + long int *lenrwBBDP, long int *leniwBBDP); +SUNDIALS_EXPORT int IDABBDPrecGetNumGfnEvals(void *ida_mem, long int *ngevalsBBDP); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/ida_dense.h b/odemex/Parser/CVode/ida_src/include/ida_dense.h new file mode 100644 index 0000000..92139a2 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/ida_dense.h @@ -0,0 +1,58 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.5 $ + * $Date: 2008/04/18 19:42:37 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the IDADENSE linear solver module. + * ----------------------------------------------------------------- + */ + +#ifndef _IDADENSE_H +#define _IDADENSE_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * Function : IDADense + * ----------------------------------------------------------------- + * A call to the IDADense function links the main integrator + * with the IDADENSE linear solver module. + * + * ida_mem is the pointer to integrator memory returned by + * IDACreate. + * + * Neq is the problem size + * + * IDADense returns: + * IDADLS_SUCCESS = 0 if successful + * IDADLS_LMEM_FAIL = -1 if there was a memory allocation failure + * IDADLS_ILL_INPUT = -2 if NVECTOR found incompatible + * + * NOTE: The dense linear solver assumes a serial implementation + * of the NVECTOR package. Therefore, IDADense will first + * test for a compatible N_Vector internal representation + * by checking that the functions N_VGetArrayPointer and + * N_VSetArrayPointer exist. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDADense(void *ida_mem, int Neq); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/ida_direct.h b/odemex/Parser/CVode/ida_src/include/ida_direct.h new file mode 100644 index 0000000..55ec153 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/ida_direct.h @@ -0,0 +1,300 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2008/04/18 19:42:37 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Common header file for the direct linear solvers in IDA. + * ----------------------------------------------------------------- + */ + +#ifndef _IDADLS_H +#define _IDADLS_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ================================================================= + * I D A D I R E C T C O N S T A N T S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * IDADLS return values + * ----------------------------------------------------------------- + */ + +#define IDADLS_SUCCESS 0 +#define IDADLS_MEM_NULL -1 +#define IDADLS_LMEM_NULL -2 +#define IDADLS_ILL_INPUT -3 +#define IDADLS_MEM_FAIL -4 + +/* Additional last_flag values */ + +#define IDADLS_JACFUNC_UNRECVR -5 +#define IDADLS_JACFUNC_RECVR -6 + +/* + * ================================================================= + * F U N C T I O N T Y P E S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Types : IDADlsDenseJacFn + * ----------------------------------------------------------------- + * + * A dense Jacobian approximation function djac must be of type + * IDADlsDenseJacFn. + * Its parameters are: + * + * N is the problem size, and length of all vector arguments. + * + * t is the current value of the independent variable t. + * + * y is the current value of the dependent variable vector, + * namely the predicted value of y(t). + * + * yp is the current value of the derivative vector y', + * namely the predicted value of y'(t). + * + * f is the residual vector F(tt,yy,yp). + * + * c_j is the scalar in the system Jacobian, proportional to + * the inverse of the step size h. + * + * user_data is a pointer to user Jacobian data - the same as the + * user_data parameter passed to IDASetRdata. + * + * Jac is the dense matrix (of type DlsMat) to be loaded by + * an IDADlsDenseJacFn routine with an approximation to the + * system Jacobian matrix + * J = dF/dy' + gamma*dF/dy + * at the given point (t,y,y'), where the ODE system is + * given by F(t,y,y') = 0. + * Note that Jac is NOT preset to zero! + * + * tmp1, tmp2, tmp3 are pointers to memory allocated for + * N_Vectors which can be used by an IDADlsDenseJacFn routine + * as temporary storage or work space. + * + * A IDADlsDenseJacFn should return + * 0 if successful, + * a positive int if a recoverable error occurred, or + * a negative int if a nonrecoverable error occurred. + * In the case of a recoverable error return, the integrator will + * attempt to recover by reducing the stepsize (which changes cj). + * + * ----------------------------------------------------------------- + * + * NOTE: The following are two efficient ways to load a dense Jac: + * (1) (with macros - no explicit data structure references) + * for (j=0; j < Neq; j++) { + * col_j = LAPACK_DENSE_COL(Jac,j); + * for (i=0; i < Neq; i++) { + * generate J_ij = the (i,j)th Jacobian element + * col_j[i] = J_ij; + * } + * } + * (2) (without macros - explicit data structure references) + * for (j=0; j < Neq; j++) { + * col_j = (Jac->data)[j]; + * for (i=0; i < Neq; i++) { + * generate J_ij = the (i,j)th Jacobian element + * col_j[i] = J_ij; + * } + * } + * A third way, using the LAPACK_DENSE_ELEM(A,i,j) macro, is much less + * efficient in general. It is only appropriate for use in small + * problems in which efficiency of access is NOT a major concern. + * + * NOTE: If the user's Jacobian routine needs other quantities, + * they are accessible as follows: hcur (the current stepsize) + * and ewt (the error weight vector) are accessible through + * IDAGetCurrentStep and IDAGetErrWeights, respectively + * (see ida.h). The unit roundoff is available as + * UNIT_ROUNDOFF defined in sundials_types.h. + * + * ----------------------------------------------------------------- + */ + + +typedef int (*IDADlsDenseJacFn)(int N, realtype t, realtype c_j, + N_Vector y, N_Vector yp, N_Vector r, + DlsMat Jac, void *user_data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +/* + * ----------------------------------------------------------------- + * Types : IDADlsBandJacFn + * ----------------------------------------------------------------- + * A banded Jacobian approximation function bjac must have the + * prototype given below. Its parameters are: + * + * Neq is the problem size, and length of all vector arguments. + * + * mupper is the upper bandwidth of the banded Jacobian matrix. + * + * mlower is the lower bandwidth of the banded Jacobian matrix. + * + * tt is the current value of the independent variable t. + * + * yy is the current value of the dependent variable vector, + * namely the predicted value of y(t). + * + * yp is the current value of the derivative vector y', + * namely the predicted value of y'(t). + * + * rr is the residual vector F(tt,yy,yp). + * + * c_j is the scalar in the system Jacobian, proportional to 1/hh. + * + * user_data is a pointer to user Jacobian data - the same as the + * user_data parameter passed to IDASetRdata. + * + * Jac is the band matrix (of type BandMat) to be loaded by + * an IDADlsBandJacFn routine with an approximation to the + * system Jacobian matrix + * J = dF/dy + cj*dF/dy' + * at the given point (t,y,y'), where the DAE system is + * given by F(t,y,y') = 0. Jac is preset to zero, so only + * the nonzero elements need to be loaded. See note below. + * + * tmp1, tmp2, tmp3 are pointers to memory allocated for + * N_Vectors which can be used by an IDADlsBandJacFn routine + * as temporary storage or work space. + * + * An IDADlsBandJacFn function should return + * 0 if successful, + * a positive int if a recoverable error occurred, or + * a negative int if a nonrecoverable error occurred. + * In the case of a recoverable error return, the integrator will + * attempt to recover by reducing the stepsize (which changes cj). + * + * ----------------------------------------------------------------- + * + * NOTE: The following are two efficient ways to load Jac: + * + * (1) (with macros - no explicit data structure references) + * for (j=0; j < Neq; j++) { + * col_j = BAND_COL(Jac,j); + * for (i=j-mupper; i <= j+mlower; i++) { + * generate J_ij = the (i,j)th Jacobian element + * BAND_COL_ELEM(col_j,i,j) = J_ij; + * } + * } + * + * (2) (with BAND_COL macro, but without BAND_COL_ELEM macro) + * for (j=0; j < Neq; j++) { + * col_j = BAND_COL(Jac,j); + * for (k=-mupper; k <= mlower; k++) { + * generate J_ij = the (i,j)th Jacobian element, i=j+k + * col_j[k] = J_ij; + * } + * } + * + * A third way, using the BAND_ELEM(A,i,j) macro, is much less + * efficient in general. It is only appropriate for use in small + * problems in which efficiency of access is NOT a major concern. + * + * NOTE: If the user's Jacobian routine needs other quantities, + * they are accessible as follows: hcur (the current stepsize) + * and ewt (the error weight vector) are accessible through + * IDAGetCurrentStep and IDAGetErrWeights, respectively (see + * ida.h). The unit roundoff is available as + * UNIT_ROUNDOFF defined in sundials_types.h + * + * ----------------------------------------------------------------- + */ + +typedef int (*IDADlsBandJacFn)(int N, int mupper, int mlower, + realtype t, realtype c_j, + N_Vector y, N_Vector yp, N_Vector r, + DlsMat Jac, void *user_data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +/* + * ================================================================= + * E X P O R T E D F U N C T I O N S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Optional inputs to the IDADLS linear solver + * ----------------------------------------------------------------- + * IDADlsSetDenseJacFn specifies the dense Jacobian approximation + * routine to be used for a direct dense linear solver. + * + * IDADlsSetBandJacFn specifies the band Jacobian approximation + * routine to be used for a direct band linear solver. + * + * By default, a difference quotient approximation, supplied with + * the solver is used. + * + * The return value is one of: + * IDADLS_SUCCESS if successful + * IDADLS_MEM_NULL if the IDA memory was NULL + * IDADLS_LMEM_NULL if the linear solver memory was NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDADlsSetDenseJacFn(void *ida_mem, IDADlsDenseJacFn jac); +SUNDIALS_EXPORT int IDADlsSetBandJacFn(void *ida_mem, IDADlsBandJacFn jac); + +/* + * ----------------------------------------------------------------- + * Optional outputs from the IDADLS linear solver + * ----------------------------------------------------------------- + * + * IDADlsGetWorkSpace returns the real and integer workspace used + * by the direct linear solver. + * IDADlsGetNumJacEvals returns the number of calls made to the + * Jacobian evaluation routine jac. + * IDADlsGetNumResEvals returns the number of calls to the user + * f routine due to finite difference Jacobian + * evaluation. + * IDADlsGetLastFlag returns the last error flag set by any of + * the IDADLS interface functions. + * + * The return value of IDADlsGet* is one of: + * IDADLS_SUCCESS if successful + * IDADLS_MEM_NULL if the IDA memory was NULL + * IDADLS_LMEM_NULL if the linear solver memory was NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDADlsGetWorkSpace(void *ida_mem, long int *lenrwLS, long int *leniwLS); +SUNDIALS_EXPORT int IDADlsGetNumJacEvals(void *ida_mem, long int *njevals); +SUNDIALS_EXPORT int IDADlsGetNumResEvals(void *ida_mem, long int *nfevalsLS); +SUNDIALS_EXPORT int IDADlsGetLastFlag(void *ida_mem, int *flag); + +/* + * ----------------------------------------------------------------- + * The following function returns the name of the constant + * associated with a IDADLS return flag + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT char *IDADlsGetReturnFlagName(int flag); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/ida_lapack.h b/odemex/Parser/CVode/ida_src/include/ida_lapack.h new file mode 100644 index 0000000..a50ed5c --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/ida_lapack.h @@ -0,0 +1,80 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.4 $ + * $Date: 2008/04/18 19:42:37 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Header file for the IDA dense linear solver IDALAPACK. + * ----------------------------------------------------------------- + */ + +#ifndef _IDALAPACK_H +#define _IDALAPACK_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * Function : IDALapackDense + * ----------------------------------------------------------------- + * A call to the IDALapackDense function links the main integrator + * with the IDALAPACK linear solver using dense Jacobians. + * + * ida_mem is the pointer to the integrator memory returned by + * IDACreate. + * + * N is the size of the ODE system. + * + * The return value of IDALapackDense is one of: + * IDADLS_SUCCESS if successful + * IDADLS_MEM_NULL if the IDA memory was NULL + * IDADLS_MEM_FAIL if there was a memory allocation failure + * IDADLS_ILL_INPUT if a required vector operation is missing + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDALapackDense(void *ida_mem, int N); + +/* + * ----------------------------------------------------------------- + * Function : IDALapackBand + * ----------------------------------------------------------------- + * A call to the IDALapackBand function links the main integrator + * with the IDALAPACK linear solver using banded Jacobians. + * + * ida_mem is the pointer to the integrator memory returned by + * IDACreate. + * + * N is the size of the ODE system. + * + * mupper is the upper bandwidth of the band Jacobian approximation. + * + * mlower is the lower bandwidth of the band Jacobian approximation. + * + * The return value of IDALapackBand is one of: + * IDADLS_SUCCESS if successful + * IDADLS_MEM_NULL if the IDA memory was NULL + * IDADLS_MEM_FAIL if there was a memory allocation failure + * IDADLS_ILL_INPUT if a required vector operation is missing + * or if a bandwidth has an illegal value. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDALapackBand(void *ida_mem, int N, int mupper, int mlower); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/ida_spbcgs.h b/odemex/Parser/CVode/ida_src/include/ida_spbcgs.h new file mode 100644 index 0000000..f733a11 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/ida_spbcgs.h @@ -0,0 +1,59 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:06 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2004, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the public header file for the IDA scaled preconditioned + * Bi-CGSTAB linear solver module, IDASPBCG. + * ----------------------------------------------------------------- + */ + +#ifndef _IDASPBCG_H +#define _IDASPBCG_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * Function : IDASpbcg + * ----------------------------------------------------------------- + * A call to the IDASpbcg function links the main integrator with + * the IDASPBCG linear solver module. Its parameters are as + * follows: + * + * IDA_mem is the pointer to memory block returned by IDACreate. + * + * maxl is the maximum Krylov subspace dimension, an + * optional input. Pass 0 to use the default value. + * Otherwise pass a positive integer. + * + * The return values of IDASpbcg are: + * IDASPILS_SUCCESS if successful + * IDASPILS_MEM_NULL if the ida memory was NULL + * IDASPILS_MEM_FAIL if there was a memory allocation failure + * IDASPILS_ILL_INPUT if there was illegal input. + * The above constants are defined in ida_spils.h + * + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDASpbcg(void *ida_mem, int maxl); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/ida_spgmr.h b/odemex/Parser/CVode/ida_src/include/ida_spgmr.h new file mode 100644 index 0000000..3604028 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/ida_spgmr.h @@ -0,0 +1,60 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:06 $ + * ----------------------------------------------------------------- + * Programmers: Alan C. Hindmarsh and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California + * Produced at the Lawrence Livermore National Laboratory + * All rights reserved + * For details, see the LICENSE file + * ----------------------------------------------------------------- + * This is the header file for the IDA Scaled Preconditioned GMRES + * linear solver module, IDASPGMR. + * ----------------------------------------------------------------- + */ + +#ifndef _IDASPGMR_H +#define _IDASPGMR_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * + * Function : IDASpgmr + * ----------------------------------------------------------------- + * A call to the IDASpgmr function links the main integrator with + * the IDASPGMR linear solver module. Its parameters are as + * follows: + * + * IDA_mem is the pointer to memory block returned by IDACreate. + * + * maxl is the maximum Krylov subspace dimension, an + * optional input. Pass 0 to use the default value, + * MIN(Neq, 5). Otherwise pass a positive integer. + * + * The return values of IDASpgmr are: + * IDASPILS_SUCCESS if successful + * IDASPILS_MEM_NULL if the ida memory was NULL + * IDASPILS_MEM_FAIL if there was a memory allocation failure + * IDASPILS_ILL_INPUT if there was illegal input. + * The above constants are defined in ida_spils.h + * + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDASpgmr(void *ida_mem, int maxl); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/ida_spils.h b/odemex/Parser/CVode/ida_src/include/ida_spils.h new file mode 100644 index 0000000..9bb641d --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/ida_spils.h @@ -0,0 +1,321 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.8 $ + * $Date: 2007/11/26 16:19:59 $ + * ----------------------------------------------------------------- + * Programmers: Alan Hindmarsh, Radu Serban and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California + * Produced at the Lawrence Livermore National Laboratory + * All rights reserved + * For details, see the LICENSE file + * ----------------------------------------------------------------- + * This is the common header file for the Scaled and Preconditioned + * Iterative Linear Solvers in IDA. + * ----------------------------------------------------------------- + */ + +#ifndef _IDASPILS_H +#define _IDASPILS_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * IDASPILS return values + * ----------------------------------------------------------------- + */ + +#define IDASPILS_SUCCESS 0 +#define IDASPILS_MEM_NULL -1 +#define IDASPILS_LMEM_NULL -2 +#define IDASPILS_ILL_INPUT -3 +#define IDASPILS_MEM_FAIL -4 +#define IDASPILS_PMEM_NULL -5 + +/* + * ----------------------------------------------------------------- + * Type : IDASpilsPrecSetupFn + * ----------------------------------------------------------------- + * The optional user-supplied functions PrecSetup and PrecSolve + * together must define the left preconditoner matrix P + * approximating the system Jacobian matrix + * J = dF/dy + c_j*dF/dy' + * (where the DAE system is F(t,y,y') = 0), and solve the linear + * systems P z = r. PrecSetup is to do any necessary setup + * operations, and PrecSolve is to compute the solution of + * P z = r. + * + * The preconditioner setup function PrecSetup is to evaluate and + * preprocess any Jacobian-related data needed by the + * preconditioner solve function PrecSolve. This might include + * forming a crude approximate Jacobian, and performing an LU + * factorization on it. This function will not be called in + * advance of every call to PrecSolve, but instead will be called + * only as often as necessary to achieve convergence within the + * Newton iteration. If the PrecSolve function needs no + * preparation, the PrecSetup function can be NULL. + * + * Each call to the PrecSetup function is preceded by a call to + * the system function res with the same (t,y,y') arguments. + * Thus the PrecSetup function can use any auxiliary data that is + * computed and saved by the res function and made accessible + * to PrecSetup. + * + * A preconditioner setup function PrecSetup must have the + * prototype given below. Its parameters are as follows: + * + * tt is the current value of the independent variable t. + * + * yy is the current value of the dependent variable vector, + * namely the predicted value of y(t). + * + * yp is the current value of the derivative vector y', + * namely the predicted value of y'(t). + * + * rr is the current value of the residual vector F(t,y,y'). + * + * c_j is the scalar in the system Jacobian, proportional to 1/hh. + * + * user_data is a pointer to user data, the same as the user_data + * parameter passed to IDASetUserData. + * + * tmp1, tmp2, tmp3 are pointers to vectors of type N_Vector + * which can be used by an IDASpilsPrecSetupFn routine + * as temporary storage or work space. + * + * NOTE: If the user's preconditioner needs other quantities, + * they are accessible as follows: hcur (the current stepsize) + * and ewt (the error weight vector) are accessible through + * IDAGetCurrentStep and IDAGetErrWeights, respectively (see + * ida.h). The unit roundoff is available as + * UNIT_ROUNDOFF defined in sundials_types.h + * + * The IDASpilsPrecSetupFn should return + * 0 if successful, + * a positive int if a recoverable error occurred, or + * a negative int if a nonrecoverable error occurred. + * In the case of a recoverable error return, the integrator will + * attempt to recover by reducing the stepsize (which changes cj). + * ----------------------------------------------------------------- + */ + +typedef int (*IDASpilsPrecSetupFn)(realtype tt, + N_Vector yy, N_Vector yp, N_Vector rr, + realtype c_j, void *user_data, + N_Vector tmp1, N_Vector tmp2, + N_Vector tmp3); + +/* + * ----------------------------------------------------------------- + * Type : IDASpilsPrecSolveFn + * ----------------------------------------------------------------- + * The optional user-supplied function PrecSolve must compute a + * solution to the linear system P z = r, where P is the left + * preconditioner defined by the user. If no preconditioning + * is desired, pass NULL for PrecSolve to IDASp*. + * + * A preconditioner solve function PrecSolve must have the + * prototype given below. Its parameters are as follows: + * + * tt is the current value of the independent variable t. + * + * yy is the current value of the dependent variable vector y. + * + * yp is the current value of the derivative vector y'. + * + * rr is the current value of the residual vector F(t,y,y'). + * + * rvec is the input right-hand side vector r. + * + * zvec is the computed solution vector z. + * + * c_j is the scalar in the system Jacobian, proportional to 1/hh. + * + * delta is an input tolerance for use by PrecSolve if it uses an + * iterative method in its solution. In that case, the + * the residual vector r - P z of the system should be + * made less than delta in weighted L2 norm, i.e., + * sqrt [ Sum (Res[i]*ewt[i])^2 ] < delta . + * Note: the error weight vector ewt can be obtained + * through a call to the routine IDAGetErrWeights. + * + * user_data is a pointer to user data, the same as the user_data + * parameter passed to IDASetUserData. + * + * tmp is an N_Vector which can be used by the PrecSolve + * routine as temporary storage or work space. + * + * The IDASpilsPrecSolveFn should return + * 0 if successful, + * a positive int if a recoverable error occurred, or + * a negative int if a nonrecoverable error occurred. + * Following a recoverable error, the integrator will attempt to + * recover by updating the preconditioner and/or reducing the + * stepsize. + * ----------------------------------------------------------------- + */ + +typedef int (*IDASpilsPrecSolveFn)(realtype tt, + N_Vector yy, N_Vector yp, N_Vector rr, + N_Vector rvec, N_Vector zvec, + realtype c_j, realtype delta, void *user_data, + N_Vector tmp); + +/* + * ----------------------------------------------------------------- + * Type : IDASpilsJacTimesVecFn + * ----------------------------------------------------------------- + * The user-supplied function jtimes is to generate the product + * J*v for given v, where J is the Jacobian matrix + * J = dF/dy + c_j*dF/dy' + * or an approximation to it, and v is a given vector. + * It should return 0 if successful and a nonzero int otherwise. + * + * A function jtimes must have the prototype given below. Its + * parameters are as follows: + * + * tt is the current value of the independent variable. + * + * yy is the current value of the dependent variable vector, + * namely the predicted value of y(t). + * + * yp is the current value of the derivative vector y', + * namely the predicted value of y'(t). + * + * rr is the current value of the residual vector F(t,y,y'). + * + * v is the N_Vector to be multiplied by J. + * + * Jv is the output N_Vector containing J*v. + * + * c_j is the scalar in the system Jacobian, proportional + * to 1/hh. + * + * user_data is a pointer to user data, the same as the + * pointer passed to IDASetUserData. + * + * tmp1, tmp2 are two N_Vectors which can be used by Jtimes for + * work space. + * ----------------------------------------------------------------- + */ + +typedef int (*IDASpilsJacTimesVecFn)(realtype tt, + N_Vector yy, N_Vector yp, N_Vector rr, + N_Vector v, N_Vector Jv, + realtype c_j, void *user_data, + N_Vector tmp1, N_Vector tmp2); + + +/* + * ----------------------------------------------------------------- + * Optional inputs to the IDASPILS linear solver + * ----------------------------------------------------------------- + * + * IDASpilsSetPreconditioner specifies the PrecSetup and PrecSolve + * functions. + * Default is NULL for both arguments. + * IDASpilsSetJacTimesVecFn specifies the jtimes function. + * Default is to use an internal finite difference + * approximation routine. + * IDASpilsSetGSType specifies the type of Gram-Schmidt + * orthogonalization to be used. This must be one of + * the two enumeration constants MODIFIED_GS or + * CLASSICAL_GS defined in iterativ.h. These correspond + * to using modified Gram-Schmidt and classical + * Gram-Schmidt, respectively. + * Default value is MODIFIED_GS. + * Only for IDASPGMR. + * IDASpilsSetMaxRestarts specifies the maximum number of restarts + * to be used in the GMRES algorithm. maxrs must be a + * non-negative integer. Pass 0 to specify no restarts. + * Default is 5. + * Only for IDASPGMR. + * IDASpbcgSetMaxl specifies the maximum Krylov subspace size. + * Default is 5. + * Only for IDASPBCG and IDASPTFQMR. + * IDASpilsSetEpsLin specifies the factor in the linear iteration + * convergence test constant. + * Default is 0.05 + * IDASpilsSetIncrementFactor specifies a factor in the increments + * to yy used in the difference quotient approximations + * to matrix-vector products Jv. + * Default is 1.0 + * + * The return value of IDASpilsSet* is one of: + * IDASPILS_SUCCESS if successful + * IDASPILS_MEM_NULL if the ida memory was NULL + * IDASPILS_LMEM_NULL if the linear solver memory was NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDASpilsSetPreconditioner(void *ida_mem, + IDASpilsPrecSetupFn pset, + IDASpilsPrecSolveFn psolve); +SUNDIALS_EXPORT int IDASpilsSetJacTimesVecFn(void *ida_mem, + IDASpilsJacTimesVecFn jtv); + +SUNDIALS_EXPORT int IDASpilsSetGSType(void *ida_mem, int gstype); +SUNDIALS_EXPORT int IDASpilsSetMaxRestarts(void *ida_mem, int maxrs); +SUNDIALS_EXPORT int IDASpilsSetMaxl(void *ida_mem, int maxl); +SUNDIALS_EXPORT int IDASpilsSetEpsLin(void *ida_mem, realtype eplifac); +SUNDIALS_EXPORT int IDASpilsSetIncrementFactor(void *ida_mem, realtype dqincfac); + +/* + * ----------------------------------------------------------------- + * Optional outputs from the IDASPILS linear solver + *---------------------------------------------------------------- + * + * IDASpilsGetWorkSpace returns the real and integer workspace used + * by IDASPILS. + * IDASpilsGetNumPrecEvals returns the number of preconditioner + * evaluations, i.e. the number of calls made to PrecSetup + * with jok==FALSE. + * IDASpilsGetNumPrecSolves returns the number of calls made to + * PrecSolve. + * IDASpilsGetNumLinIters returns the number of linear iterations. + * IDASpilsGetNumConvFails returns the number of linear + * convergence failures. + * IDASpilsGetNumJtimesEvals returns the number of calls to jtimes + * IDASpilsGetNumResEvals returns the number of calls to the user + * res routine due to finite difference Jacobian times vector + * evaluation. + * IDASpilsGetLastFlag returns the last error flag set by any of + * the IDASPILS interface functions. + * + * The return value of IDASpilsGet* is one of: + * IDASPILS_SUCCESS if successful + * IDASPILS_MEM_NULL if the ida memory was NULL + * IDASPILS_LMEM_NULL if the linear solver memory was NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDASpilsGetWorkSpace(void *ida_mem, long int *lenrwLS, long int *leniwLS); +SUNDIALS_EXPORT int IDASpilsGetNumPrecEvals(void *ida_mem, long int *npevals); +SUNDIALS_EXPORT int IDASpilsGetNumPrecSolves(void *ida_mem, long int *npsolves); +SUNDIALS_EXPORT int IDASpilsGetNumLinIters(void *ida_mem, long int *nliters); +SUNDIALS_EXPORT int IDASpilsGetNumConvFails(void *ida_mem, long int *nlcfails); +SUNDIALS_EXPORT int IDASpilsGetNumJtimesEvals(void *ida_mem, long int *njvevals); +SUNDIALS_EXPORT int IDASpilsGetNumResEvals(void *ida_mem, long int *nrevalsLS); +SUNDIALS_EXPORT int IDASpilsGetLastFlag(void *ida_mem, int *flag); + +/* + * ----------------------------------------------------------------- + * The following function returns the name of the constant + * associated with an IDASPILS return flag + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT char *IDASpilsGetReturnFlagName(int flag); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/ida_sptfqmr.h b/odemex/Parser/CVode/ida_src/include/ida_sptfqmr.h new file mode 100644 index 0000000..a7a32b5 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/ida_sptfqmr.h @@ -0,0 +1,59 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the public header file for the IDA scaled preconditioned + * TFQMR linear solver module, IDASPTFQMR. + * ----------------------------------------------------------------- + */ + +#ifndef _IDASPTFQMR_H +#define _IDASPTFQMR_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * Function : IDASptfqmr + * ----------------------------------------------------------------- + * A call to the IDASptfqmr function links the main integrator with + * the IDASPTFQMR linear solver module. Its parameters are as + * follows: + * + * IDA_mem is the pointer to memory block returned by IDACreate. + * + * maxl is the maximum Krylov subspace dimension, an + * optional input. Pass 0 to use the default value. + * Otherwise pass a positive integer. + * + * The return values of IDASptfqmr are: + * IDASPILS_SUCCESS if successful + * IDASPILS_MEM_NULL if the ida memory was NULL + * IDASPILS_MEM_FAIL if there was a memory allocation failure + * IDASPILS_ILL_INPUT if there was illegal input. + * The above constants are defined in ida_spils.h + * + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int IDASptfqmr(void *ida_mem, int maxl); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/nvector/nvector_parallel.h b/odemex/Parser/CVode/ida_src/include/nvector/nvector_parallel.h new file mode 100644 index 0000000..f8a006c --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/nvector/nvector_parallel.h @@ -0,0 +1,314 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban, + * and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the main header file for the MPI-enabled implementation + * of the NVECTOR module. + * + * Part I contains declarations specific to the parallel + * implementation of the supplied NVECTOR module. + * + * Part II defines accessor macros that allow the user to efficiently + * use the type N_Vector without making explicit references to the + * underlying data structure. + * + * Part III contains the prototype for the constructor + * N_VNew_Parallel as well as implementation-specific prototypes + * for various useful vector operations. + * + * Notes: + * + * - The definition of the generic N_Vector structure can be + * found in the header file sundials_nvector.h. + * + * - The definition of the type realtype can be found in the + * header file sundials_types.h, and it may be changed (at the + * configuration stage) according to the user's needs. + * The sundials_types.h file also contains the definition + * for the type booleantype. + * + * - N_Vector arguments to arithmetic vector operations need not + * be distinct. For example, the following call: + * + * N_VLinearSum_Parallel(a,x,b,y,y); + * + * (which stores the result of the operation a*x+b*y in y) + * is legal. + * ----------------------------------------------------------------- + */ + +#ifndef _NVECTOR_PARALLEL_H +#define _NVECTOR_PARALLEL_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +#include + + +/* + * ----------------------------------------------------------------- + * PART I: PARALLEL implementation of N_Vector + * ----------------------------------------------------------------- + */ + +/* define MPI data types */ + +#if defined(SUNDIALS_SINGLE_PRECISION) + +#define PVEC_REAL_MPI_TYPE MPI_FLOAT + +#elif defined(SUNDIALS_DOUBLE_PRECISION) + +#define PVEC_REAL_MPI_TYPE MPI_DOUBLE + +#elif defined(SUNDIALS_EXTENDED_PRECISION) + +#define PVEC_REAL_MPI_TYPE MPI_LONG_DOUBLE + +#endif + +#define PVEC_INTEGER_MPI_TYPE MPI_LONG + +/* parallel implementation of the N_Vector 'content' structure + contains the global and local lengths of the vector, a pointer + to an array of 'realtype components', the MPI communicator, + and a flag indicating ownership of the data */ + +struct _N_VectorContent_Parallel { + long int local_length; /* local vector length */ + long int global_length; /* global vector length */ + booleantype own_data; /* ownership of data */ + realtype *data; /* local data array */ + MPI_Comm comm; /* pointer to MPI communicator */ +}; + +typedef struct _N_VectorContent_Parallel *N_VectorContent_Parallel; + +/* + * ----------------------------------------------------------------- + * PART II: macros NV_CONTENT_P, NV_DATA_P, NV_OWN_DATA_P, + * NV_LOCLENGTH_P, NV_GLOBLENGTH_P,NV_COMM_P, and NV_Ith_P + * ----------------------------------------------------------------- + * In the descriptions below, the following user declarations + * are assumed: + * + * N_Vector v; + * long int v_len, s_len, i; + * + * (1) NV_CONTENT_P + * + * This routines gives access to the contents of the parallel + * vector N_Vector. + * + * The assignment v_cont = NV_CONTENT_P(v) sets v_cont to be + * a pointer to the parallel N_Vector content structure. + * + * (2) NV_DATA_P, NV_OWN_DATA_P, NV_LOCLENGTH_P, NV_GLOBLENGTH_P, + * and NV_COMM_P + * + * These routines give access to the individual parts of + * the content structure of a parallel N_Vector. + * + * The assignment v_data = NV_DATA_P(v) sets v_data to be + * a pointer to the first component of the local data for + * the vector v. The assignment NV_DATA_P(v) = data_v sets + * the component array of v to be data_V by storing the + * pointer data_v. + * + * The assignment v_llen = NV_LOCLENGTH_P(v) sets v_llen to + * be the length of the local part of the vector v. The call + * NV_LOCLENGTH_P(v) = llen_v sets the local length + * of v to be llen_v. + * + * The assignment v_glen = NV_GLOBLENGTH_P(v) sets v_glen to + * be the global length of the vector v. The call + * NV_GLOBLENGTH_P(v) = glen_v sets the global length of v to + * be glen_v. + * + * The assignment v_comm = NV_COMM_P(v) sets v_comm to be the + * MPI communicator of the vector v. The assignment + * NV_COMM_C(v) = comm_v sets the MPI communicator of v to be + * comm_v. + * + * (3) NV_Ith_P + * + * In the following description, the components of the + * local part of an N_Vector are numbered 0..n-1, where n + * is the local length of (the local part of) v. + * + * The assignment r = NV_Ith_P(v,i) sets r to be the value + * of the ith component of the local part of the vector v. + * The assignment NV_Ith_P(v,i) = r sets the value of the + * ith local component of v to be r. + * + * Note: When looping over the components of an N_Vector v, it is + * more efficient to first obtain the component array via + * v_data = NV_DATA_P(v) and then access v_data[i] within the + * loop than it is to use NV_Ith_P(v,i) within the loop. + * ----------------------------------------------------------------- + */ + +#define NV_CONTENT_P(v) ( (N_VectorContent_Parallel)(v->content) ) + +#define NV_LOCLENGTH_P(v) ( NV_CONTENT_P(v)->local_length ) + +#define NV_GLOBLENGTH_P(v) ( NV_CONTENT_P(v)->global_length ) + +#define NV_OWN_DATA_P(v) ( NV_CONTENT_P(v)->own_data ) + +#define NV_DATA_P(v) ( NV_CONTENT_P(v)->data ) + +#define NV_COMM_P(v) ( NV_CONTENT_P(v)->comm ) + +#define NV_Ith_P(v,i) ( NV_DATA_P(v)[i] ) + +/* + * ----------------------------------------------------------------- + * PART III: functions exported by nvector_parallel + * + * CONSTRUCTORS: + * N_VNew_Parallel + * N_VNewEmpty_Parallel + * N_VMake_Parallel + * N_VCloneVectorArray_Parallel + * N_VCloneVectorArrayEmpty_Parallel + * DESTRUCTORS: + * N_VDestroy_Parallel + * N_VDestroyVectorArray_Parallel + * OTHER: + * N_VPrint_Parallel + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Function : N_VNew_Parallel + * ----------------------------------------------------------------- + * This function creates and allocates memory for a parallel vector. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VNew_Parallel(MPI_Comm comm, + long int local_length, + long int global_length); + +/* + * ----------------------------------------------------------------- + * Function : N_VNewEmpty_Parallel + * ----------------------------------------------------------------- + * This function creates a new parallel N_Vector with an empty + * (NULL) data array. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VNewEmpty_Parallel(MPI_Comm comm, + long int local_length, + long int global_length); + +/* + * ----------------------------------------------------------------- + * Function : N_VMake_Parallel + * ----------------------------------------------------------------- + * This function creates and allocates memory for a parallel vector + * with a user-supplied data array. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VMake_Parallel(MPI_Comm comm, + long int local_length, + long int global_length, + realtype *v_data); + +/* + * ----------------------------------------------------------------- + * Function : N_VCloneVectorArray_Parallel + * ----------------------------------------------------------------- + * This function creates an array of 'count' PARALLEL vectors by + * cloning a given vector w. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector *N_VCloneVectorArray_Parallel(int count, N_Vector w); + +/* + * ----------------------------------------------------------------- + * Function : N_VCloneVectorArrayEmpty_Parallel + * ----------------------------------------------------------------- + * This function creates an array of 'count' PARALLEL vectors each + * with an empty (NULL) data array by cloning w. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector *N_VCloneVectorArrayEmpty_Parallel(int count, N_Vector w); + +/* + * ----------------------------------------------------------------- + * Function : N_VDestroyVectorArray_Parallel + * ----------------------------------------------------------------- + * This function frees an array of N_Vector created with + * N_VCloneVectorArray_Parallel or N_VCloneVectorArrayEmpty_Parallel. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void N_VDestroyVectorArray_Parallel(N_Vector *vs, int count); + +/* + * ----------------------------------------------------------------- + * Function : N_VPrint_Parallel + * ----------------------------------------------------------------- + * This function prints the content of a parallel vector to stdout. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void N_VPrint_Parallel(N_Vector v); + +/* + * ----------------------------------------------------------------- + * parallel implementations of the vector operations + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VCloneEmpty_Parallel(N_Vector w); +SUNDIALS_EXPORT N_Vector N_VClone_Parallel(N_Vector w); +SUNDIALS_EXPORT void N_VDestroy_Parallel(N_Vector v); +SUNDIALS_EXPORT void N_VSpace_Parallel(N_Vector v, long int *lrw, long int *liw); +SUNDIALS_EXPORT realtype *N_VGetArrayPointer_Parallel(N_Vector v); +SUNDIALS_EXPORT void N_VSetArrayPointer_Parallel(realtype *v_data, N_Vector v); +SUNDIALS_EXPORT void N_VLinearSum_Parallel(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VConst_Parallel(realtype c, N_Vector z); +SUNDIALS_EXPORT void N_VProd_Parallel(N_Vector x, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VDiv_Parallel(N_Vector x, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VScale_Parallel(realtype c, N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VAbs_Parallel(N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VInv_Parallel(N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VAddConst_Parallel(N_Vector x, realtype b, N_Vector z); +SUNDIALS_EXPORT realtype N_VDotProd_Parallel(N_Vector x, N_Vector y); +SUNDIALS_EXPORT realtype N_VMaxNorm_Parallel(N_Vector x); +SUNDIALS_EXPORT realtype N_VWrmsNorm_Parallel(N_Vector x, N_Vector w); +SUNDIALS_EXPORT realtype N_VWrmsNormMask_Parallel(N_Vector x, N_Vector w, N_Vector id); +SUNDIALS_EXPORT realtype N_VMin_Parallel(N_Vector x); +SUNDIALS_EXPORT realtype N_VWL2Norm_Parallel(N_Vector x, N_Vector w); +SUNDIALS_EXPORT realtype N_VL1Norm_Parallel(N_Vector x); +SUNDIALS_EXPORT void N_VCompare_Parallel(realtype c, N_Vector x, N_Vector z); +SUNDIALS_EXPORT booleantype N_VInvTest_Parallel(N_Vector x, N_Vector z); +SUNDIALS_EXPORT booleantype N_VConstrMask_Parallel(N_Vector c, N_Vector x, N_Vector m); +SUNDIALS_EXPORT realtype N_VMinQuotient_Parallel(N_Vector num, N_Vector denom); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/nvector/nvector_serial.h b/odemex/Parser/CVode/ida_src/include/nvector/nvector_serial.h new file mode 100644 index 0000000..4301a68 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/nvector/nvector_serial.h @@ -0,0 +1,265 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban, + * and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the serial implementation of the + * NVECTOR module. + * + * Part I contains declarations specific to the serial + * implementation of the supplied NVECTOR module. + * + * Part II defines accessor macros that allow the user to + * efficiently use the type N_Vector without making explicit + * references to the underlying data structure. + * + * Part III contains the prototype for the constructor N_VNew_Serial + * as well as implementation-specific prototypes for various useful + * vector operations. + * + * Notes: + * + * - The definition of the generic N_Vector structure can be found + * in the header file sundials_nvector.h. + * + * - The definition of the type 'realtype' can be found in the + * header file sundials_types.h, and it may be changed (at the + * configuration stage) according to the user's needs. + * The sundials_types.h file also contains the definition + * for the type 'booleantype'. + * + * - N_Vector arguments to arithmetic vector operations need not + * be distinct. For example, the following call: + * + * N_VLinearSum_Serial(a,x,b,y,y); + * + * (which stores the result of the operation a*x+b*y in y) + * is legal. + * ----------------------------------------------------------------- + */ + +#ifndef _NVECTOR_SERIAL_H +#define _NVECTOR_SERIAL_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * PART I: SERIAL implementation of N_Vector + * ----------------------------------------------------------------- + */ + +/* serial implementation of the N_Vector 'content' structure + contains the length of the vector, a pointer to an array + of 'realtype' components, and a flag indicating ownership of + the data */ + +struct _N_VectorContent_Serial { + long int length; + booleantype own_data; + realtype *data; +}; + +typedef struct _N_VectorContent_Serial *N_VectorContent_Serial; + +/* + * ----------------------------------------------------------------- + * PART II: macros NV_CONTENT_S, NV_DATA_S, NV_OWN_DATA_S, + * NV_LENGTH_S, and NV_Ith_S + * ----------------------------------------------------------------- + * In the descriptions below, the following user declarations + * are assumed: + * + * N_Vector v; + * long int i; + * + * (1) NV_CONTENT_S + * + * This routines gives access to the contents of the serial + * vector N_Vector. + * + * The assignment v_cont = NV_CONTENT_S(v) sets v_cont to be + * a pointer to the serial N_Vector content structure. + * + * (2) NV_DATA_S NV_OWN_DATA_S and NV_LENGTH_S + * + * These routines give access to the individual parts of + * the content structure of a serial N_Vector. + * + * The assignment v_data = NV_DATA_S(v) sets v_data to be + * a pointer to the first component of v. The assignment + * NV_DATA_S(v) = data_V sets the component array of v to + * be data_v by storing the pointer data_v. + * + * The assignment v_len = NV_LENGTH_S(v) sets v_len to be + * the length of v. The call NV_LENGTH_S(v) = len_v sets + * the length of v to be len_v. + * + * (3) NV_Ith_S + * + * In the following description, the components of an + * N_Vector are numbered 0..n-1, where n is the length of v. + * + * The assignment r = NV_Ith_S(v,i) sets r to be the value of + * the ith component of v. The assignment NV_Ith_S(v,i) = r + * sets the value of the ith component of v to be r. + * + * Note: When looping over the components of an N_Vector v, it is + * more efficient to first obtain the component array via + * v_data = NV_DATA_S(v) and then access v_data[i] within the + * loop than it is to use NV_Ith_S(v,i) within the loop. + * ----------------------------------------------------------------- + */ + +#define NV_CONTENT_S(v) ( (N_VectorContent_Serial)(v->content) ) + +#define NV_LENGTH_S(v) ( NV_CONTENT_S(v)->length ) + +#define NV_OWN_DATA_S(v) ( NV_CONTENT_S(v)->own_data ) + +#define NV_DATA_S(v) ( NV_CONTENT_S(v)->data ) + +#define NV_Ith_S(v,i) ( NV_DATA_S(v)[i] ) + +/* + * ----------------------------------------------------------------- + * PART III: functions exported by nvector_serial + * + * CONSTRUCTORS: + * N_VNew_Serial + * N_VNewEmpty_Serial + * N_VMake_Serial + * N_VCloneVectorArray_Serial + * N_VCloneVectorArrayEmpty_Serial + * DESTRUCTORS: + * N_VDestroy_Serial + * N_VDestroyVectorArray_Serial + * OTHER: + * N_VPrint_Serial + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Function : N_VNew_Serial + * ----------------------------------------------------------------- + * This function creates and allocates memory for a serial vector. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VNew_Serial(long int vec_length); + +/* + * ----------------------------------------------------------------- + * Function : N_VNewEmpty_Serial + * ----------------------------------------------------------------- + * This function creates a new serial N_Vector with an empty (NULL) + * data array. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VNewEmpty_Serial(long int vec_length); + +/* + * ----------------------------------------------------------------- + * Function : N_VMake_Serial + * ----------------------------------------------------------------- + * This function creates and allocates memory for a serial vector + * with a user-supplied data array. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VMake_Serial(long int vec_length, realtype *v_data); + +/* + * ----------------------------------------------------------------- + * Function : N_VCloneVectorArray_Serial + * ----------------------------------------------------------------- + * This function creates an array of 'count' SERIAL vectors by + * cloning a given vector w. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector *N_VCloneVectorArray_Serial(int count, N_Vector w); + +/* + * ----------------------------------------------------------------- + * Function : N_VCloneVectorArrayEmpty_Serial + * ----------------------------------------------------------------- + * This function creates an array of 'count' SERIAL vectors each + * with an empty (NULL) data array by cloning w. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector *N_VCloneVectorArrayEmpty_Serial(int count, N_Vector w); + +/* + * ----------------------------------------------------------------- + * Function : N_VDestroyVectorArray_Serial + * ----------------------------------------------------------------- + * This function frees an array of SERIAL vectors created with + * N_VCloneVectorArray_Serial or N_VCloneVectorArrayEmpty_Serial. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void N_VDestroyVectorArray_Serial(N_Vector *vs, int count); + +/* + * ----------------------------------------------------------------- + * Function : N_VPrint_Serial + * ----------------------------------------------------------------- + * This function prints the content of a serial vector to stdout. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void N_VPrint_Serial(N_Vector v); + +/* + * ----------------------------------------------------------------- + * serial implementations of various useful vector operations + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VCloneEmpty_Serial(N_Vector w); +SUNDIALS_EXPORT N_Vector N_VClone_Serial(N_Vector w); +SUNDIALS_EXPORT void N_VDestroy_Serial(N_Vector v); +SUNDIALS_EXPORT void N_VSpace_Serial(N_Vector v, long int *lrw, long int *liw); +SUNDIALS_EXPORT realtype *N_VGetArrayPointer_Serial(N_Vector v); +SUNDIALS_EXPORT void N_VSetArrayPointer_Serial(realtype *v_data, N_Vector v); +SUNDIALS_EXPORT void N_VLinearSum_Serial(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VConst_Serial(realtype c, N_Vector z); +SUNDIALS_EXPORT void N_VProd_Serial(N_Vector x, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VDiv_Serial(N_Vector x, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VScale_Serial(realtype c, N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VAbs_Serial(N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VInv_Serial(N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VAddConst_Serial(N_Vector x, realtype b, N_Vector z); +SUNDIALS_EXPORT realtype N_VDotProd_Serial(N_Vector x, N_Vector y); +SUNDIALS_EXPORT realtype N_VMaxNorm_Serial(N_Vector x); +SUNDIALS_EXPORT realtype N_VWrmsNorm_Serial(N_Vector x, N_Vector w); +SUNDIALS_EXPORT realtype N_VWrmsNormMask_Serial(N_Vector x, N_Vector w, N_Vector id); +SUNDIALS_EXPORT realtype N_VMin_Serial(N_Vector x); +SUNDIALS_EXPORT realtype N_VWL2Norm_Serial(N_Vector x, N_Vector w); +SUNDIALS_EXPORT realtype N_VL1Norm_Serial(N_Vector x); +SUNDIALS_EXPORT void N_VCompare_Serial(realtype c, N_Vector x, N_Vector z); +SUNDIALS_EXPORT booleantype N_VInvTest_Serial(N_Vector x, N_Vector z); +SUNDIALS_EXPORT booleantype N_VConstrMask_Serial(N_Vector c, N_Vector x, N_Vector m); +SUNDIALS_EXPORT realtype N_VMinQuotient_Serial(N_Vector num, N_Vector denom); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/sundials/sundials_band.h b/odemex/Parser/CVode/ida_src/include/sundials/sundials_band.h new file mode 100644 index 0000000..95ee54c --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/sundials/sundials_band.h @@ -0,0 +1,153 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.5 $ + * $Date: 2009/02/17 02:39:26 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for a generic BAND linear solver + * package, based on the DlsMat type defined in sundials_direct.h. + * + * There are two sets of band solver routines listed in + * this file: one set uses type DlsMat defined below and the + * other set uses the type realtype ** for band matrix arguments. + * Routines that work with the type DlsMat begin with "Band". + * Routines that work with realtype ** begin with "band" + * ----------------------------------------------------------------- + */ + +#ifndef _SUNDIALS_BAND_H +#define _SUNDIALS_BAND_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Function : BandGBTRF + * ----------------------------------------------------------------- + * Usage : ier = BandGBTRF(A, p); + * if (ier != 0) ... A is singular + * ----------------------------------------------------------------- + * BandGBTRF performs the LU factorization of the N by N band + * matrix A. This is done using standard Gaussian elimination + * with partial pivoting. + * + * A successful LU factorization leaves the "matrix" A and the + * pivot array p with the following information: + * + * (1) p[k] contains the row number of the pivot element chosen + * at the beginning of elimination step k, k=0, 1, ..., N-1. + * + * (2) If the unique LU factorization of A is given by PA = LU, + * where P is a permutation matrix, L is a lower triangular + * matrix with all 1's on the diagonal, and U is an upper + * triangular matrix, then the upper triangular part of A + * (including its diagonal) contains U and the strictly lower + * triangular part of A contains the multipliers, I-L. + * + * BandGBTRF returns 0 if successful. Otherwise it encountered + * a zero diagonal element during the factorization. In this case + * it returns the column index (numbered from one) at which + * it encountered the zero. + * + * Important Note: A must be allocated to accommodate the increase + * in upper bandwidth that occurs during factorization. If + * mathematically, A is a band matrix with upper bandwidth mu and + * lower bandwidth ml, then the upper triangular factor U can + * have upper bandwidth as big as smu = MIN(n-1,mu+ml). The lower + * triangular factor L has lower bandwidth ml. Allocate A with + * call A = BandAllocMat(N,mu,ml,smu), where mu, ml, and smu are + * as defined above. The user does not have to zero the "extra" + * storage allocated for the purpose of factorization. This will + * handled by the BandGBTRF routine. + * + * BandGBTRF is only a wrapper around bandGBTRF. All work is done + * in bandGBTRF works directly on the data in the DlsMat A (i.e., + * the field cols). + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int BandGBTRF(DlsMat A, int *p); +SUNDIALS_EXPORT int bandGBTRF(realtype **a, int n, int mu, int ml, int smu, int *p); + +/* + * ----------------------------------------------------------------- + * Function : BandGBTRS + * ----------------------------------------------------------------- + * Usage : BandGBTRS(A, p, b); + * ----------------------------------------------------------------- + * BandGBTRS solves the N-dimensional system A x = b using + * the LU factorization in A and the pivot information in p + * computed in BandGBTRF. The solution x is returned in b. This + * routine cannot fail if the corresponding call to BandGBTRF + * did not fail. + * + * BandGBTRS is only a wrapper around bandGBTRS which does all the + * work directly on the data in the DlsMat A (i.e., the field cols). + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void BandGBTRS(DlsMat A, int *p, realtype *b); +SUNDIALS_EXPORT void bandGBTRS(realtype **a, int n, int smu, int ml, int *p, realtype *b); + +/* + * ----------------------------------------------------------------- + * Function : BandCopy + * ----------------------------------------------------------------- + * Usage : BandCopy(A, B, copymu, copyml); + * ----------------------------------------------------------------- + * BandCopy copies the submatrix with upper and lower bandwidths + * copymu, copyml of the N by N band matrix A into the N by N + * band matrix B. + * + * BandCopy is a wrapper around bandCopy which accesses the data + * in the DlsMat A and B (i.e. the fields cols) + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void BandCopy(DlsMat A, DlsMat B, int copymu, int copyml); +SUNDIALS_EXPORT void bandCopy(realtype **a, realtype **b, int n, int a_smu, int b_smu, + int copymu, int copyml); + +/* + * ----------------------------------------------------------------- + * Function: BandScale + * ----------------------------------------------------------------- + * Usage : BandScale(c, A); + * ----------------------------------------------------------------- + * A(i,j) <- c*A(i,j), j-(A->mu) <= i <= j+(A->ml). + * + * BandScale is a wrapper around bandScale which performs the actual + * scaling by accessing the data in the DlsMat A (i.e. the field + * cols). + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void BandScale(realtype c, DlsMat A); +SUNDIALS_EXPORT void bandScale(realtype c, realtype **a, int n, int mu, int ml, int smu); + +/* + * ----------------------------------------------------------------- + * Function: bandAddIdentity + * ----------------------------------------------------------------- + * bandAddIdentity adds the identity matrix to the n-by-n matrix + * stored in the realtype** arrays. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void bandAddIdentity(realtype **a, int n, int smu); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/sundials/sundials_config.h b/odemex/Parser/CVode/ida_src/include/sundials/sundials_config.h new file mode 100644 index 0000000..3ba4096 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/sundials/sundials_config.h @@ -0,0 +1,80 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.4 $ + * $Date: 2007/12/19 20:34:00 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + *------------------------------------------------------------------ + * SUNDIALS configuration header file + *------------------------------------------------------------------ + */ + +#include "winDefine.h" + +/* Define SUNDIALS version number */ +#define SUNDIALS_PACKAGE_VERSION "2.4.0" + +/* FCMIX: Define Fortran name-mangling macro for C identifiers. + * Depending on the inferred scheme, one of the following six + * macros will be defined: + * #define SUNDIALS_F77_FUNC(name,NAME) name + * #define SUNDIALS_F77_FUNC(name,NAME) name ## _ + * #define SUNDIALS_F77_FUNC(name,NAME) name ## __ + * #define SUNDIALS_F77_FUNC(name,NAME) NAME + * #define SUNDIALS_F77_FUNC(name,NAME) NAME ## _ + * #define SUNDIALS_F77_FUNC(name,NAME) NAME ## __ + */ + + +/* FCMIX: Define Fortran name-mangling macro for C identifiers + * which contain underscores. + */ + + +/* Define precision of SUNDIALS data type 'realtype' + * Depending on the precision level, one of the following + * three macros will be defined: + * #define SUNDIALS_SINGLE_PRECISION 1 + * #define SUNDIALS_DOUBLE_PRECISION 1 + * #define SUNDIALS_EXTENDED_PRECISION 1 + */ +#define SUNDIALS_DOUBLE_PRECISION 1 + +/* Use generic math functions + * If it was decided that generic math functions can be used, then + * #define SUNDIALS_USE_GENERIC_MATH 1 + * otherwise + * #define SUNDIALS_USE_GENERIC_MATH 0 + */ + + +/* Blas/Lapack available + * If working libraries for Blas/lapack support were found, then + * #define SUNDIALS_BLAS_LAPACK 1 + * otherwise + * #define SUNDIALS_BLAS_LAPACK 0 + */ +#define SUNDIALS_BLAS_LAPACK 1 + +/* FNVECTOR: Allow user to specify different MPI communicator + * If it was found that the MPI implementation supports MPI_Comm_f2c, then + * #define SUNDIALS_MPI_COMM_F2C 1 + * otherwise + * #define SUNDIALS_MPI_COMM_F2C 0 + */ + + +/* Mark SUNDIALS API functions for export/import + * When building shared SUNDIALS libraries under Windows, use + * #define SUNDIALS_EXPORT __declspec(dllexport) + * When linking to shared SUNDIALS libraries under Windows, use + * #define SUNDIALS_EXPORT __declspec(dllimport) + * In all other cases (other platforms or static libraries under + * Windows), the SUNDIALS_EXPORT macro is empty + */ +#define SUNDIALS_EXPORT diff --git a/odemex/Parser/CVode/ida_src/include/sundials/sundials_config.in b/odemex/Parser/CVode/ida_src/include/sundials/sundials_config.in new file mode 100644 index 0000000..f43aeae --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/sundials/sundials_config.in @@ -0,0 +1,78 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.4 $ + * $Date: 2007/12/19 20:34:00 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + *------------------------------------------------------------------ + * SUNDIALS configuration header file + *------------------------------------------------------------------ + */ + +/* Define SUNDIALS version number */ +#define SUNDIALS_PACKAGE_VERSION "@PACKAGE_VERSION@" + +/* FCMIX: Define Fortran name-mangling macro for C identifiers. + * Depending on the inferred scheme, one of the following six + * macros will be defined: + * #define SUNDIALS_F77_FUNC(name,NAME) name + * #define SUNDIALS_F77_FUNC(name,NAME) name ## _ + * #define SUNDIALS_F77_FUNC(name,NAME) name ## __ + * #define SUNDIALS_F77_FUNC(name,NAME) NAME + * #define SUNDIALS_F77_FUNC(name,NAME) NAME ## _ + * #define SUNDIALS_F77_FUNC(name,NAME) NAME ## __ + */ +@F77_MANGLE_MACRO1@ + +/* FCMIX: Define Fortran name-mangling macro for C identifiers + * which contain underscores. + */ +@F77_MANGLE_MACRO2@ + +/* Define precision of SUNDIALS data type 'realtype' + * Depending on the precision level, one of the following + * three macros will be defined: + * #define SUNDIALS_SINGLE_PRECISION 1 + * #define SUNDIALS_DOUBLE_PRECISION 1 + * #define SUNDIALS_EXTENDED_PRECISION 1 + */ +@PRECISION_LEVEL@ + +/* Use generic math functions + * If it was decided that generic math functions can be used, then + * #define SUNDIALS_USE_GENERIC_MATH 1 + * otherwise + * #define SUNDIALS_USE_GENERIC_MATH 0 + */ +@GENERIC_MATH_LIB@ + +/* Blas/Lapack available + * If working libraries for Blas/lapack support were found, then + * #define SUNDIALS_BLAS_LAPACK 1 + * otherwise + * #define SUNDIALS_BLAS_LAPACK 0 + */ +@BLAS_LAPACK_MACRO@ + +/* FNVECTOR: Allow user to specify different MPI communicator + * If it was found that the MPI implementation supports MPI_Comm_f2c, then + * #define SUNDIALS_MPI_COMM_F2C 1 + * otherwise + * #define SUNDIALS_MPI_COMM_F2C 0 + */ +@F77_MPI_COMM_F2C@ + +/* Mark SUNDIALS API functions for export/import + * When building shared SUNDIALS libraries under Windows, use + * #define SUNDIALS_EXPORT __declspec(dllexport) + * When linking to shared SUNDIALS libraries under Windows, use + * #define SUNDIALS_EXPORT __declspec(dllimport) + * In all other cases (other platforms or static libraries under + * Windows), the SUNDIALS_EXPORT macro is empty + */ +@SUNDIALS_EXPORT@ diff --git a/odemex/Parser/CVode/ida_src/include/sundials/sundials_dense.h b/odemex/Parser/CVode/ida_src/include/sundials/sundials_dense.h new file mode 100644 index 0000000..a3b1431 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/sundials/sundials_dense.h @@ -0,0 +1,187 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.7 $ + * $Date: 2009/02/17 02:39:26 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for a generic package of DENSE matrix + * operations, based on the DlsMat type defined in sundials_direct.h. + * + * There are two sets of dense solver routines listed in + * this file: one set uses type DlsMat defined below and the + * other set uses the type realtype ** for dense matrix arguments. + * Routines that work with the type DlsMat begin with "Dense". + * Routines that work with realtype** begin with "dense". + * ----------------------------------------------------------------- + */ + +#ifndef _SUNDIALS_DENSE_H +#define _SUNDIALS_DENSE_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Functions: DenseGETRF and DenseGETRS + * ----------------------------------------------------------------- + * DenseGETRF performs the LU factorization of the M by N dense + * matrix A. This is done using standard Gaussian elimination + * with partial (row) pivoting. Note that this applies only + * to matrices with M >= N and full column rank. + * + * A successful LU factorization leaves the matrix A and the + * pivot array p with the following information: + * + * (1) p[k] contains the row number of the pivot element chosen + * at the beginning of elimination step k, k=0, 1, ..., N-1. + * + * (2) If the unique LU factorization of A is given by PA = LU, + * where P is a permutation matrix, L is a lower trapezoidal + * matrix with all 1's on the diagonal, and U is an upper + * triangular matrix, then the upper triangular part of A + * (including its diagonal) contains U and the strictly lower + * trapezoidal part of A contains the multipliers, I-L. + * + * For square matrices (M=N), L is unit lower triangular. + * + * DenseGETRF returns 0 if successful. Otherwise it encountered + * a zero diagonal element during the factorization. In this case + * it returns the column index (numbered from one) at which + * it encountered the zero. + * + * DenseGETRS solves the N-dimensional system A x = b using + * the LU factorization in A and the pivot information in p + * computed in DenseGETRF. The solution x is returned in b. This + * routine cannot fail if the corresponding call to DenseGETRF + * did not fail. + * DenseGETRS does NOT check for a square matrix! + * + * ----------------------------------------------------------------- + * DenseGETRF and DenseGETRS are simply wrappers around denseGETRF + * and denseGETRS, respectively, which perform all the work by + * directly accessing the data in the DlsMat A (i.e. the field cols) + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int DenseGETRF(DlsMat A, int *p); +SUNDIALS_EXPORT void DenseGETRS(DlsMat A, int *p, realtype *b); + +SUNDIALS_EXPORT int denseGETRF(realtype **a, int m, int n, int *p); +SUNDIALS_EXPORT void denseGETRS(realtype **a, int n, int *p, realtype *b); + +/* + * ----------------------------------------------------------------- + * Functions : DensePOTRF and DensePOTRS + * ----------------------------------------------------------------- + * DensePOTRF computes the Cholesky factorization of a real symmetric + * positive definite matrix A. + * ----------------------------------------------------------------- + * DensePOTRS solves a system of linear equations A*X = B with a + * symmetric positive definite matrix A using the Cholesky factorization + * A = L*L**T computed by DensePOTRF. + * + * ----------------------------------------------------------------- + * DensePOTRF and DensePOTRS are simply wrappers around densePOTRF + * and densePOTRS, respectively, which perform all the work by + * directly accessing the data in the DlsMat A (i.e. the field cols) + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int DensePOTRF(DlsMat A); +SUNDIALS_EXPORT void DensePOTRS(DlsMat A, realtype *b); + +SUNDIALS_EXPORT int densePOTRF(realtype **a, int m); +SUNDIALS_EXPORT void densePOTRS(realtype **a, int m, realtype *b); + +/* + * ----------------------------------------------------------------- + * Functions : DenseGEQRF and DenseORMQR + * ----------------------------------------------------------------- + * DenseGEQRF computes a QR factorization of a real M-by-N matrix A: + * A = Q * R (with M>= N). + * + * DenseGEQRF requires a temporary work vector wrk of length M. + * ----------------------------------------------------------------- + * DenseORMQR computes the product w = Q * v where Q is a real + * orthogonal matrix defined as the product of k elementary reflectors + * + * Q = H(1) H(2) . . . H(k) + * + * as returned by DenseGEQRF. Q is an M-by-N matrix, v is a vector + * of length N and w is a vector of length M (with M>=N). + * + * DenseORMQR requires a temporary work vector wrk of length M. + * + * ----------------------------------------------------------------- + * DenseGEQRF and DenseORMQR are simply wrappers around denseGEQRF + * and denseORMQR, respectively, which perform all the work by + * directly accessing the data in the DlsMat A (i.e. the field cols) + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int DenseGEQRF(DlsMat A, realtype *beta, realtype *wrk); +SUNDIALS_EXPORT int DenseORMQR(DlsMat A, realtype *beta, realtype *vn, realtype *vm, + realtype *wrk); + +SUNDIALS_EXPORT int denseGEQRF(realtype **a, int m, int n, realtype *beta, realtype *v); +SUNDIALS_EXPORT int denseORMQR(realtype **a, int m, int n, realtype *beta, + realtype *v, realtype *w, realtype *wrk); + +/* + * ----------------------------------------------------------------- + * Function : DenseCopy + * ----------------------------------------------------------------- + * DenseCopy copies the contents of the M-by-N matrix A into the + * M-by-N matrix B. + * + * DenseCopy is a wrapper around denseCopy which accesses the data + * in the DlsMat A and B (i.e. the fields cols) + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void DenseCopy(DlsMat A, DlsMat B); +SUNDIALS_EXPORT void denseCopy(realtype **a, realtype **b, int m, int n); + +/* + * ----------------------------------------------------------------- + * Function: DenseScale + * ----------------------------------------------------------------- + * DenseScale scales the elements of the M-by-N matrix A by the + * constant c and stores the result back in A. + * + * DenseScale is a wrapper around denseScale which performs the actual + * scaling by accessing the data in the DlsMat A (i.e. the field + * cols). + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void DenseScale(realtype c, DlsMat A); +SUNDIALS_EXPORT void denseScale(realtype c, realtype **a, int m, int n); + + +/* + * ----------------------------------------------------------------- + * Function: denseAddIdentity + * ----------------------------------------------------------------- + * denseAddIdentity adds the identity matrix to the n-by-n matrix + * stored in the realtype** arrays. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void denseAddIdentity(realtype **a, int n); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/sundials/sundials_direct.h b/odemex/Parser/CVode/ida_src/include/sundials/sundials_direct.h new file mode 100644 index 0000000..f3d823b --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/sundials/sundials_direct.h @@ -0,0 +1,323 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.3 $ + * $Date: 2009/02/17 02:39:26 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This header file contains definitions and declarations for use by + * generic direct linear solvers for Ax = b. It defines types for + * dense and banded matrices and corresponding accessor macros. + * ----------------------------------------------------------------- + */ + +#ifndef _SUNDIALS_DIRECT_H +#define _SUNDIALS_DIRECT_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ================================================================= + * C O N S T A N T S + * ================================================================= + */ + +/* + * SUNDIALS_DENSE: dense matrix + * SUNDIALS_BAND: banded matrix + */ + +#define SUNDIALS_DENSE 1 +#define SUNDIALS_BAND 2 + +/* + * ================================================================== + * Type definitions + * ================================================================== + */ + +/* + * ----------------------------------------------------------------- + * Type : DlsMat + * ----------------------------------------------------------------- + * The type DlsMat is defined to be a pointer to a structure + * with various sizes, a data field, and an array of pointers to + * the columns which defines a dense or band matrix for use in + * direct linear solvers. The M and N fields indicates the number + * of rows and columns, respectively. The data field is a one + * dimensional array used for component storage. The cols field + * stores the pointers in data for the beginning of each column. + * ----------------------------------------------------------------- + * For DENSE matrices, the relevant fields in DlsMat are: + * type = SUNDIALS_DENSE + * M - number of rows + * N - number of columns + * ldim - leading dimension (ldim >= M) + * data - pointer to a contiguous block of realtype variables + * ldata - length of the data array =ldim*N + * cols - array of pointers. cols[j] points to the first element + * of the j-th column of the matrix in the array data. + * + * The elements of a dense matrix are stored columnwise (i.e columns + * are stored one on top of the other in memory). + * If A is of type DlsMat, then the (i,j)th element of A (with + * 0 <= i < M and 0 <= j < N) is given by (A->data)[j*n+i]. + * + * The DENSE_COL and DENSE_ELEM macros below allow a user to access + * efficiently individual matrix elements without writing out explicit + * data structure references and without knowing too much about the + * underlying element storage. The only storage assumption needed is + * that elements are stored columnwise and that a pointer to the + * jth column of elements can be obtained via the DENSE_COL macro. + * ----------------------------------------------------------------- + * For BAND matrices, the relevant fields in DlsMat are: + * type = SUNDIALS_BAND + * M - number of rows + * N - number of columns + * mu - upper bandwidth, 0 <= mu <= min(M,N) + * ml - lower bandwidth, 0 <= ml <= min(M,N) + * s_mu - storage upper bandwidth, mu <= s_mu <= N-1. + * The dgbtrf routine writes the LU factors into the storage + * for A. The upper triangular factor U, however, may have + * an upper bandwidth as big as MIN(N-1,mu+ml) because of + * partial pivoting. The s_mu field holds the upper + * bandwidth allocated for A. + * ldim - leading dimension (ldim >= s_mu) + * data - pointer to a contiguous block of realtype variables + * ldata - length of the data array =ldim*(s_mu+ml+1) + * cols - array of pointers. cols[j] points to the first element + * of the j-th column of the matrix in the array data. + * + * The BAND_COL, BAND_COL_ELEM, and BAND_ELEM macros below allow a + * user to access individual matrix elements without writing out + * explicit data structure references and without knowing too much + * about the underlying element storage. The only storage assumption + * needed is that elements are stored columnwise and that a pointer + * into the jth column of elements can be obtained via the BAND_COL + * macro. The BAND_COL_ELEM macro selects an element from a column + * which has already been isolated via BAND_COL. The macro + * BAND_COL_ELEM allows the user to avoid the translation + * from the matrix location (i,j) to the index in the array returned + * by BAND_COL at which the (i,j)th element is stored. + * ----------------------------------------------------------------- + */ + +typedef struct _DlsMat { + int type; + int M; + int N; + int ldim; + int mu; + int ml; + int s_mu; + realtype *data; + int ldata; + realtype **cols; +} *DlsMat; + +/* + * ================================================================== + * Data accessor macros + * ================================================================== + */ + +/* + * ----------------------------------------------------------------- + * DENSE_COL and DENSE_ELEM + * ----------------------------------------------------------------- + * + * DENSE_COL(A,j) references the jth column of the M-by-N dense + * matrix A, 0 <= j < N. The type of the expression DENSE_COL(A,j) + * is (realtype *). After the assignment in the usage above, col_j + * may be treated as an array indexed from 0 to M-1. The (i,j)-th + * element of A is thus referenced by col_j[i]. + * + * DENSE_ELEM(A,i,j) references the (i,j)th element of the dense + * M-by-N matrix A, 0 <= i < M ; 0 <= j < N. + * + * ----------------------------------------------------------------- + */ + +#define DENSE_COL(A,j) ((A->cols)[j]) +#define DENSE_ELEM(A,i,j) ((A->cols)[j][i]) + +/* + * ----------------------------------------------------------------- + * BAND_COL, BAND_COL_ELEM, and BAND_ELEM + * ----------------------------------------------------------------- + * + * BAND_COL(A,j) references the diagonal element of the jth column + * of the N by N band matrix A, 0 <= j <= N-1. The type of the + * expression BAND_COL(A,j) is realtype *. The pointer returned by + * the call BAND_COL(A,j) can be treated as an array which is + * indexed from -(A->mu) to (A->ml). + * + * BAND_COL_ELEM references the (i,j)th entry of the band matrix A + * when used in conjunction with BAND_COL. The index (i,j) should + * satisfy j-(A->mu) <= i <= j+(A->ml). + * + * BAND_ELEM(A,i,j) references the (i,j)th element of the M-by-N + * band matrix A, where 0 <= i,j <= N-1. The location (i,j) should + * further satisfy j-(A->mu) <= i <= j+(A->ml). + * + * ----------------------------------------------------------------- + */ + +#define BAND_COL(A,j) (((A->cols)[j])+(A->s_mu)) +#define BAND_COL_ELEM(col_j,i,j) (col_j[(i)-(j)]) +#define BAND_ELEM(A,i,j) ((A->cols)[j][(i)-(j)+(A->s_mu)]) + +/* + * ================================================================== + * Exported function prototypes (functions working on dlsMat) + * ================================================================== + */ + +/* + * ----------------------------------------------------------------- + * Function: NewDenseMat + * ----------------------------------------------------------------- + * NewDenseMat allocates memory for an M-by-N dense matrix and + * returns the storage allocated (type DlsMat). NewDenseMat + * returns NULL if the request for matrix storage cannot be + * satisfied. See the above documentation for the type DlsMat + * for matrix storage details. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT DlsMat NewDenseMat(int M, int N); + +/* + * ----------------------------------------------------------------- + * Function: NewBandMat + * ----------------------------------------------------------------- + * NewBandMat allocates memory for an M-by-N band matrix + * with upper bandwidth mu, lower bandwidth ml, and storage upper + * bandwidth smu. Pass smu as follows depending on whether A will + * be LU factored: + * + * (1) Pass smu = mu if A will not be factored. + * + * (2) Pass smu = MIN(N-1,mu+ml) if A will be factored. + * + * NewBandMat returns the storage allocated (type DlsMat) or + * NULL if the request for matrix storage cannot be satisfied. + * See the documentation for the type DlsMat for matrix storage + * details. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT DlsMat NewBandMat(int N, int mu, int ml, int smu); + +/* + * ----------------------------------------------------------------- + * Functions: DestroyMat + * ----------------------------------------------------------------- + * DestroyMat frees the memory allocated by NewDenseMat or NewBandMat + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void DestroyMat(DlsMat A); + +/* + * ----------------------------------------------------------------- + * Function: NewIntArray + * ----------------------------------------------------------------- + * NewIntArray allocates memory an array of N integers and returns + * the pointer to the memory it allocates. If the request for + * memory storage cannot be satisfied, it returns NULL. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int *NewIntArray(int N); + +/* + * ----------------------------------------------------------------- + * Function: NewRealArray + * ----------------------------------------------------------------- + * NewRealArray allocates memory an array of N realtype and returns + * the pointer to the memory it allocates. If the request for + * memory storage cannot be satisfied, it returns NULL. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT realtype *NewRealArray(int N); + +/* + * ----------------------------------------------------------------- + * Function: DestroyArray + * ----------------------------------------------------------------- + * DestroyArray frees memory allocated by NewIntArray or by + * NewRealArray. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void DestroyArray(void *p); + +/* + * ----------------------------------------------------------------- + * Function : AddIdentity + * ----------------------------------------------------------------- + * AddIdentity adds 1.0 to the main diagonal (A_ii, i=1,2,...,N-1) of + * the M-by-N matrix A (M>= N) and stores the result back in A. + * AddIdentity is typically used with square matrices. + * AddIdentity does not check for M >= N and therefore a segmentation + * fault will occur if M < N! + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void AddIdentity(DlsMat A); + +/* + * ----------------------------------------------------------------- + * Function : SetToZero + * ----------------------------------------------------------------- + * SetToZero sets all the elements of the M-by-N matrix A to 0.0. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void SetToZero(DlsMat A); + +/* + * ----------------------------------------------------------------- + * Functions: PrintMat + * ----------------------------------------------------------------- + * This function prints the M-by-N (dense or band) matrix A to + * standard output as it would normally appear on paper. + * It is intended as debugging tools with small values of M and N. + * The elements are printed using the %g/%lg/%Lg option. + * A blank line is printed before and after the matrix. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void PrintMat(DlsMat A); + + +/* + * ================================================================== + * Exported function prototypes (functions working on realtype**) + * ================================================================== + */ + +SUNDIALS_EXPORT realtype **newDenseMat(int m, int n); +SUNDIALS_EXPORT realtype **newBandMat(int n, int smu, int ml); +SUNDIALS_EXPORT void destroyMat(realtype **a); +SUNDIALS_EXPORT int *newIntArray(int n); +SUNDIALS_EXPORT realtype *newRealArray(int m); +SUNDIALS_EXPORT void destroyArray(void *v); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/sundials/sundials_fnvector.h b/odemex/Parser/CVode/ida_src/include/sundials/sundials_fnvector.h new file mode 100644 index 0000000..bbc9a95 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/sundials/sundials_fnvector.h @@ -0,0 +1,41 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.1 $ + * $Date: 2006/07/05 15:27:52 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This file (companion of nvector.h) contains definitions + * needed for the initialization of vector operations in Fortran. + * ----------------------------------------------------------------- + */ + + +#ifndef _FNVECTOR_H +#define _FNVECTOR_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#ifndef _SUNDIALS_CONFIG_H +#define _SUNDIALS_CONFIG_H +#include +#endif + +/* SUNDIALS solver IDs */ + +#define FCMIX_CVODE 1 +#define FCMIX_IDA 2 +#define FCMIX_KINSOL 3 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/sundials/sundials_iterative.h b/odemex/Parser/CVode/ida_src/include/sundials/sundials_iterative.h new file mode 100644 index 0000000..5e7e4bf --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/sundials/sundials_iterative.h @@ -0,0 +1,242 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen and Alan C. Hindmarsh @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This header file contains declarations intended for use by + * generic iterative solvers of Ax = b. The enumeration gives + * symbolic names for the type of preconditioning to be used. + * The function type declarations give the prototypes for the + * functions to be called within an iterative linear solver, that + * are responsible for + * multiplying A by a given vector v (ATimesFn), and + * solving the preconditioner equation Pz = r (PSolveFn). + * ----------------------------------------------------------------- + */ + +#ifndef _ITERATIVE_H +#define _ITERATIVE_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + + +/* + * ----------------------------------------------------------------- + * enum : types of preconditioning + * ----------------------------------------------------------------- + * PREC_NONE : The iterative linear solver should not use + * preconditioning. + * + * PREC_LEFT : The iterative linear solver uses preconditioning on + * the left only. + * + * PREC_RIGHT : The iterative linear solver uses preconditioning on + * the right only. + * + * PREC_BOTH : The iterative linear solver uses preconditioning on + * both the left and the right. + * ----------------------------------------------------------------- + */ + +enum { PREC_NONE, PREC_LEFT, PREC_RIGHT, PREC_BOTH }; + +/* + * ----------------------------------------------------------------- + * enum : types of Gram-Schmidt routines + * ----------------------------------------------------------------- + * MODIFIED_GS : The iterative solver uses the modified + * Gram-Schmidt routine ModifiedGS listed in this + * file. + * + * CLASSICAL_GS : The iterative solver uses the classical + * Gram-Schmidt routine ClassicalGS listed in this + * file. + * ----------------------------------------------------------------- + */ + +enum { MODIFIED_GS = 1, CLASSICAL_GS = 2 }; + +/* + * ----------------------------------------------------------------- + * Type: ATimesFn + * ----------------------------------------------------------------- + * An ATimesFn multiplies Av and stores the result in z. The + * caller is responsible for allocating memory for the z vector. + * The parameter A_data is a pointer to any information about A + * which the function needs in order to do its job. The vector v + * is unchanged. An ATimesFn returns 0 if successful and a + * non-zero value if unsuccessful. + * ----------------------------------------------------------------- + */ + +typedef int (*ATimesFn)(void *A_data, N_Vector v, N_Vector z); + +/* + * ----------------------------------------------------------------- + * Type: PSolveFn + * ----------------------------------------------------------------- + * A PSolveFn solves the preconditioner equation Pz = r for the + * vector z. The caller is responsible for allocating memory for + * the z vector. The parameter P_data is a pointer to any + * information about P which the function needs in order to do + * its job. The parameter lr is input, and indicates whether P + * is to be taken as the left preconditioner or the right + * preconditioner: lr = 1 for left and lr = 2 for right. + * If preconditioning is on one side only, lr can be ignored. + * The vector r is unchanged. + * A PSolveFn returns 0 if successful and a non-zero value if + * unsuccessful. On a failure, a negative return value indicates + * an unrecoverable condition, while a positive value indicates + * a recoverable one, in which the calling routine may reattempt + * the solution after updating preconditioner data. + * ----------------------------------------------------------------- + */ + +typedef int (*PSolveFn)(void *P_data, N_Vector r, N_Vector z, int lr); + +/* + * ----------------------------------------------------------------- + * Function: ModifiedGS + * ----------------------------------------------------------------- + * ModifiedGS performs a modified Gram-Schmidt orthogonalization + * of the N_Vector v[k] against the p unit N_Vectors at + * v[k-1], v[k-2], ..., v[k-p]. + * + * v is an array of (k+1) N_Vectors v[i], i=0, 1, ..., k. + * v[k-1], v[k-2], ..., v[k-p] are assumed to have L2-norm + * equal to 1. + * + * h is the output k by k Hessenberg matrix of inner products. + * This matrix must be allocated row-wise so that the (i,j)th + * entry is h[i][j]. The inner products (v[i],v[k]), + * i=i0, i0+1, ..., k-1, are stored at h[i][k-1]. Here + * i0=MAX(0,k-p). + * + * k is the index of the vector in the v array that needs to be + * orthogonalized against previous vectors in the v array. + * + * p is the number of previous vectors in the v array against + * which v[k] is to be orthogonalized. + * + * new_vk_norm is a pointer to memory allocated by the caller to + * hold the Euclidean norm of the orthogonalized vector v[k]. + * + * If (k-p) < 0, then ModifiedGS uses p=k. The orthogonalized + * v[k] is NOT normalized and is stored over the old v[k]. Once + * the orthogonalization has been performed, the Euclidean norm + * of v[k] is stored in (*new_vk_norm). + * + * ModifiedGS returns 0 to indicate success. It cannot fail. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int ModifiedGS(N_Vector *v, realtype **h, int k, int p, + realtype *new_vk_norm); + +/* + * ----------------------------------------------------------------- + * Function: ClassicalGS + * ----------------------------------------------------------------- + * ClassicalGS performs a classical Gram-Schmidt + * orthogonalization of the N_Vector v[k] against the p unit + * N_Vectors at v[k-1], v[k-2], ..., v[k-p]. The parameters v, h, + * k, p, and new_vk_norm are as described in the documentation + * for ModifiedGS. + * + * temp is an N_Vector which can be used as workspace by the + * ClassicalGS routine. + * + * s is a length k array of realtype which can be used as + * workspace by the ClassicalGS routine. + * + * ClassicalGS returns 0 to indicate success. It cannot fail. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int ClassicalGS(N_Vector *v, realtype **h, int k, int p, + realtype *new_vk_norm, N_Vector temp, realtype *s); + +/* + * ----------------------------------------------------------------- + * Function: QRfact + * ----------------------------------------------------------------- + * QRfact performs a QR factorization of the Hessenberg matrix H. + * + * n is the problem size; the matrix H is (n+1) by n. + * + * h is the (n+1) by n Hessenberg matrix H to be factored. It is + * stored row-wise. + * + * q is an array of length 2*n containing the Givens rotations + * computed by this function. A Givens rotation has the form: + * | c -s | + * | s c |. + * The components of the Givens rotations are stored in q as + * (c, s, c, s, ..., c, s). + * + * job is a control flag. If job==0, then a new QR factorization + * is performed. If job!=0, then it is assumed that the first + * n-1 columns of h have already been factored and only the last + * column needs to be updated. + * + * QRfact returns 0 if successful. If a zero is encountered on + * the diagonal of the triangular factor R, then QRfact returns + * the equation number of the zero entry, where the equations are + * numbered from 1, not 0. If QRsol is subsequently called in + * this situation, it will return an error because it could not + * divide by the zero diagonal entry. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int QRfact(int n, realtype **h, realtype *q, int job); + +/* + * ----------------------------------------------------------------- + * Function: QRsol + * ----------------------------------------------------------------- + * QRsol solves the linear least squares problem + * + * min (b - H*x, b - H*x), x in R^n, + * + * where H is a Hessenberg matrix, and b is in R^(n+1). + * It uses the QR factors of H computed by QRfact. + * + * n is the problem size; the matrix H is (n+1) by n. + * + * h is a matrix (computed by QRfact) containing the upper + * triangular factor R of the original Hessenberg matrix H. + * + * q is an array of length 2*n (computed by QRfact) containing + * the Givens rotations used to factor H. + * + * b is the (n+1)-vector appearing in the least squares problem + * above. + * + * On return, b contains the solution x of the least squares + * problem, if QRsol was successful. + * + * QRsol returns a 0 if successful. Otherwise, a zero was + * encountered on the diagonal of the triangular factor R. + * In this case, QRsol returns the equation number (numbered + * from 1, not 0) of the zero entry. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int QRsol(int n, realtype **h, realtype *q, realtype *b); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/sundials/sundials_lapack.h b/odemex/Parser/CVode/ida_src/include/sundials/sundials_lapack.h new file mode 100644 index 0000000..4af89df --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/sundials/sundials_lapack.h @@ -0,0 +1,126 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2009/02/17 02:39:26 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for a generic package of direct matrix + * operations for use with BLAS/LAPACK. + * ----------------------------------------------------------------- + */ + +#ifndef _SUNDIALS_LAPACK_H +#define _SUNDIALS_LAPACK_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +/* + * ================================================================== + * Blas and Lapack functions + * ================================================================== + */ + +#if defined(SUNDIALS_F77_FUNC) + +#define dcopy_f77 SUNDIALS_F77_FUNC(dcopy, DCOPY) +#define dscal_f77 SUNDIALS_F77_FUNC(dscal, DSCAL) +#define dgemv_f77 SUNDIALS_F77_FUNC(dgemv, DGEMV) +#define dtrsv_f77 SUNDIALS_F77_FUNC(dtrsv, DTRSV) +#define dsyrk_f77 SUNDIALS_F77_FUNC(dsyrk, DSKYR) + +#define dgbtrf_f77 SUNDIALS_F77_FUNC(dgbtrf, DGBTRF) +#define dgbtrs_f77 SUNDIALS_F77_FUNC(dgbtrs, DGBTRS) +#define dgetrf_f77 SUNDIALS_F77_FUNC(dgetrf, DGETRF) +#define dgetrs_f77 SUNDIALS_F77_FUNC(dgetrs, DGETRS) +#define dgeqp3_f77 SUNDIALS_F77_FUNC(dgeqp3, DGEQP3) +#define dgeqrf_f77 SUNDIALS_F77_FUNC(dgeqrf, DGEQRF) +#define dormqr_f77 SUNDIALS_F77_FUNC(dormqr, DORMQR) +#define dpotrf_f77 SUNDIALS_F77_FUNC(dpotrf, DPOTRF) +#define dpotrs_f77 SUNDIALS_F77_FUNC(dpotrs, DPOTRS) + +#else + +#define dcopy_f77 dcopy_ +#define dscal_f77 dscal_ +#define dgemv_f77 dgemv_ +#define dtrsv_f77 dtrsv_ +#define dsyrk_f77 dsyrk_ + +#define dgbtrf_f77 dgbtrf_ +#define dgbtrs_f77 dgbtrs_ +#define dgeqp3_f77 dgeqp3_ +#define dgeqrf_f77 dgeqrf_ +#define dgetrf_f77 dgetrf_ +#define dgetrs_f77 dgetrs_ +#define dormqr_f77 dormqr_ +#define dpotrf_f77 dpotrf_ +#define dpotrs_f77 dpotrs_ + +#endif + +/* Level-1 BLAS */ + +extern void dcopy_f77(int *n, const double *x, const int *inc_x, double *y, const int *inc_y); +extern void dscal_f77(int *n, const double *alpha, double *x, const int *inc_x); + +/* Level-2 BLAS */ + +extern void dgemv_f77(const char *trans, int *m, int *n, const double *alpha, const double *a, + int *lda, const double *x, int *inc_x, const double *beta, double *y, int *inc_y, + int len_trans); + +extern void dtrsv_f77(const char *uplo, const char *trans, const char *diag, const int *n, + const double *a, const int *lda, double *x, const int *inc_x, + int len_uplo, int len_trans, int len_diag); + +/* Level-3 BLAS */ + +extern void dsyrk_f77(const char *uplo, const char *trans, const int *n, const int *k, + const double *alpha, const double *a, const int *lda, const double *beta, + const double *c, const int *ldc, int len_uplo, int len_trans); + +/* LAPACK */ + +extern void dgbtrf_f77(const int *m, const int *n, const int *kl, const int *ku, + double *ab, int *ldab, int *ipiv, int *info); + +extern void dgbtrs_f77(const char *trans, const int *n, const int *kl, const int *ku, const int *nrhs, + double *ab, const int *ldab, int *ipiv, double *b, const int *ldb, + int *info, int len_trans); + + +extern void dgeqp3_f77(const int *m, const int *n, double *a, const int *lda, int *jpvt, double *tau, + double *work, const int *lwork, int *info); + +extern void dgeqrf_f77(const int *m, const int *n, double *a, const int *lda, double *tau, double *work, + const int *lwork, int *info); + +extern void dgetrf_f77(const int *m, const int *n, double *a, int *lda, int *ipiv, int *info); + +extern void dgetrs_f77(const char *trans, const int *n, const int *nrhs, double *a, const int *lda, + int *ipiv, double *b, const int *ldb, int *info, int len_trans); + + +extern void dormqr_f77(const char *side, const char *trans, const int *m, const int *n, const int *k, + double *a, const int *lda, double *tau, double *c, const int *ldc, + double *work, const int *lwork, int *info, int len_side, int len_trans); + +extern void dpotrf_f77(const char *uplo, const int *n, double *a, int *lda, int *info, int len_uplo); + +extern void dpotrs_f77(const char *uplo, const int *n, const int *nrhs, double *a, const int *lda, + double *b, const int *ldb, int * info, int len_uplo); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/sundials/sundials_math.h b/odemex/Parser/CVode/ida_src/include/sundials/sundials_math.h new file mode 100644 index 0000000..99de085 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/sundials/sundials_math.h @@ -0,0 +1,139 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for a simple C-language math library. The + * routines listed here work with the type realtype as defined in + * the header file sundials_types.h. + * ----------------------------------------------------------------- + */ + +#ifndef _SUNDIALSMATH_H +#define _SUNDIALSMATH_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Macros : MIN and MAX + * ----------------------------------------------------------------- + * MIN(A,B) returns the minimum of A and B + * + * MAX(A,B) returns the maximum of A and B + * + * SQR(A) returns A^2 + * ----------------------------------------------------------------- + */ + +#ifndef MIN +#define MIN(A, B) ((A) < (B) ? (A) : (B)) +#endif + +#ifndef MAX +#define MAX(A, B) ((A) > (B) ? (A) : (B)) +#endif + +#ifndef SQR +#define SQR(A) ((A)*(A)) +#endif + +#ifndef ABS +#define ABS RAbs +#endif + +#ifndef SQRT +#define SQRT RSqrt +#endif + +#ifndef EXP +#define EXP RExp +#endif + +/* + * ----------------------------------------------------------------- + * Function : RPowerI + * ----------------------------------------------------------------- + * Usage : int exponent; + * realtype base, ans; + * ans = RPowerI(base,exponent); + * ----------------------------------------------------------------- + * RPowerI returns the value of base^exponent, where base is of type + * realtype and exponent is of type int. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT realtype RPowerI(realtype base, int exponent); + +/* + * ----------------------------------------------------------------- + * Function : RPowerR + * ----------------------------------------------------------------- + * Usage : realtype base, exponent, ans; + * ans = RPowerR(base,exponent); + * ----------------------------------------------------------------- + * RPowerR returns the value of base^exponent, where both base and + * exponent are of type realtype. If base < ZERO, then RPowerR + * returns ZERO. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT realtype RPowerR(realtype base, realtype exponent); + +/* + * ----------------------------------------------------------------- + * Function : RSqrt + * ----------------------------------------------------------------- + * Usage : realtype sqrt_x; + * sqrt_x = RSqrt(x); + * ----------------------------------------------------------------- + * RSqrt(x) returns the square root of x. If x < ZERO, then RSqrt + * returns ZERO. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT realtype RSqrt(realtype x); + +/* + * ----------------------------------------------------------------- + * Function : RAbs (a.k.a. ABS) + * ----------------------------------------------------------------- + * Usage : realtype abs_x; + * abs_x = RAbs(x); + * ----------------------------------------------------------------- + * RAbs(x) returns the absolute value of x. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT realtype RAbs(realtype x); + +/* + * ----------------------------------------------------------------- + * Function : RExp (a.k.a. EXP) + * ----------------------------------------------------------------- + * Usage : realtype exp_x; + * exp_x = RExp(x); + * ----------------------------------------------------------------- + * RExp(x) returns e^x (base-e exponential function). + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT realtype RExp(realtype x); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/sundials/sundials_nvector.h b/odemex/Parser/CVode/ida_src/include/sundials/sundials_nvector.h new file mode 100644 index 0000000..6142b32 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/sundials/sundials_nvector.h @@ -0,0 +1,373 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for a generic NVECTOR package. + * It defines the N_Vector structure (_generic_N_Vector) which + * contains the following fields: + * - an implementation-dependent 'content' field which contains + * the description and actual data of the vector + * - an 'ops' filed which contains a structure listing operations + * acting on such vectors + * + * Part I of this file contains type declarations for the + * _generic_N_Vector and _generic_N_Vector_Ops structures, as well + * as references to pointers to such structures (N_Vector). + * + * Part II of this file contains the prototypes for the vector + * functions which operate on N_Vector. + * + * At a minimum, a particular implementation of an NVECTOR must + * do the following: + * - specify the 'content' field of N_Vector, + * - implement the operations on those N_Vectors, + * - provide a constructor routine for new vectors + * + * Additionally, an NVECTOR implementation may provide the following: + * - macros to access the underlying N_Vector data + * - a constructor for an array of N_Vectors + * - a constructor for an empty N_Vector (i.e., a new N_Vector with + * a NULL data pointer). + * - a routine to print the content of an N_Vector + * ----------------------------------------------------------------- + */ + +#ifndef _NVECTOR_H +#define _NVECTOR_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Generic definition of N_Vector + * ----------------------------------------------------------------- + */ + +/* Forward reference for pointer to N_Vector_Ops object */ +typedef struct _generic_N_Vector_Ops *N_Vector_Ops; + +/* Forward reference for pointer to N_Vector object */ +typedef struct _generic_N_Vector *N_Vector; + +/* Define array of N_Vectors */ +typedef N_Vector *N_Vector_S; + +/* Structure containing function pointers to vector operations */ +struct _generic_N_Vector_Ops { + N_Vector (*nvclone)(N_Vector); + N_Vector (*nvcloneempty)(N_Vector); + void (*nvdestroy)(N_Vector); + void (*nvspace)(N_Vector, long int *, long int *); + realtype* (*nvgetarraypointer)(N_Vector); + void (*nvsetarraypointer)(realtype *, N_Vector); + void (*nvlinearsum)(realtype, N_Vector, realtype, N_Vector, N_Vector); + void (*nvconst)(realtype, N_Vector); + void (*nvprod)(N_Vector, N_Vector, N_Vector); + void (*nvdiv)(N_Vector, N_Vector, N_Vector); + void (*nvscale)(realtype, N_Vector, N_Vector); + void (*nvabs)(N_Vector, N_Vector); + void (*nvinv)(N_Vector, N_Vector); + void (*nvaddconst)(N_Vector, realtype, N_Vector); + realtype (*nvdotprod)(N_Vector, N_Vector); + realtype (*nvmaxnorm)(N_Vector); + realtype (*nvwrmsnorm)(N_Vector, N_Vector); + realtype (*nvwrmsnormmask)(N_Vector, N_Vector, N_Vector); + realtype (*nvmin)(N_Vector); + realtype (*nvwl2norm)(N_Vector, N_Vector); + realtype (*nvl1norm)(N_Vector); + void (*nvcompare)(realtype, N_Vector, N_Vector); + booleantype (*nvinvtest)(N_Vector, N_Vector); + booleantype (*nvconstrmask)(N_Vector, N_Vector, N_Vector); + realtype (*nvminquotient)(N_Vector, N_Vector); +}; + +/* + * ----------------------------------------------------------------- + * A vector is a structure with an implementation-dependent + * 'content' field, and a pointer to a structure of vector + * operations corresponding to that implementation. + * ----------------------------------------------------------------- + */ + +struct _generic_N_Vector { + void *content; + struct _generic_N_Vector_Ops *ops; +}; + +/* + * ----------------------------------------------------------------- + * Functions exported by NVECTOR module + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * N_VClone + * Creates a new vector of the same type as an existing vector. + * It does not copy the vector, but rather allocates storage for + * the new vector. + * + * N_VCloneEmpty + * Creates a new vector of the same type as an existing vector, + * but does not allocate storage. + * + * N_VDestroy + * Destroys a vector created with N_VClone. + * + * N_VSpace + * Returns space requirements for one N_Vector (type 'realtype' in + * lrw and type 'long int' in liw). + * + * N_VGetArrayPointer + * Returns a pointer to the data component of the given N_Vector. + * NOTE: This function assumes that the internal data is stored + * as a contiguous 'realtype' array. This routine is only used in + * the solver-specific interfaces to the dense and banded linear + * solvers, as well as the interfaces to the banded preconditioners + * distributed with SUNDIALS. + * + * N_VSetArrayPointer + * Overwrites the data field in the given N_Vector with a user-supplied + * array of type 'realtype'. + * NOTE: This function assumes that the internal data is stored + * as a contiguous 'realtype' array. This routine is only used in + * the interfaces to the dense linear solver. + * + * N_VLinearSum + * Performs the operation z = a*x + b*y + * + * N_VConst + * Performs the operation z[i] = c for i = 0, 1, ..., N-1 + * + * N_VProd + * Performs the operation z[i] = x[i]*y[i] for i = 0, 1, ..., N-1 + * + * N_VDiv + * Performs the operation z[i] = x[i]/y[i] for i = 0, 1, ..., N-1 + * + * N_VScale + * Performs the operation z = c*x + * + * N_VAbs + * Performs the operation z[i] = |x[i]| for i = 0, 1, ..., N-1 + * + * N_VInv + * Performs the operation z[i] = 1/x[i] for i = 0, 1, ..., N-1 + * This routine does not check for division by 0. It should be + * called only with an N_Vector x which is guaranteed to have + * all non-zero components. + * + * N_VAddConst + * Performs the operation z[i] = x[i] + b for i = 0, 1, ..., N-1 + * + * N_VDotProd + * Returns the dot product of two vectors: + * sum (i = 0 to N-1) {x[i]*y[i]} + * + * N_VMaxNorm + * Returns the maximum norm of x: + * max (i = 0 to N-1) ABS(x[i]) + * + * N_VWrmsNorm + * Returns the weighted root mean square norm of x with weight + * vector w: + * sqrt [(sum (i = 0 to N-1) {(x[i]*w[i])^2})/N] + * + * N_VWrmsNormMask + * Returns the weighted root mean square norm of x with weight + * vector w, masked by the elements of id: + * sqrt [(sum (i = 0 to N-1) {(x[i]*w[i]*msk[i])^2})/N] + * where msk[i] = 1.0 if id[i] > 0 and + * msk[i] = 0.0 if id[i] < 0 + * + * N_VMin + * Returns the smallest element of x: + * min (i = 0 to N-1) x[i] + * + * N_VWL2Norm + * Returns the weighted Euclidean L2 norm of x with weight + * vector w: + * sqrt [(sum (i = 0 to N-1) {(x[i]*w[i])^2})] + * + * N_VL1Norm + * Returns the L1 norm of x: + * sum (i = 0 to N-1) {ABS(x[i])} + * + * N_VCompare + * Performs the operation + * z[i] = 1.0 if ABS(x[i]) >= c i = 0, 1, ..., N-1 + * 0.0 otherwise + * + * N_VInvTest + * Performs the operation z[i] = 1/x[i] with a test for + * x[i] == 0.0 before inverting x[i]. + * This routine returns TRUE if all components of x are non-zero + * (successful inversion) and returns FALSE otherwise. + * + * N_VConstrMask + * Performs the operation : + * m[i] = 1.0 if constraint test fails for x[i] + * m[i] = 0.0 if constraint test passes for x[i] + * where the constraint tests are as follows: + * If c[i] = +2.0, then x[i] must be > 0.0. + * If c[i] = +1.0, then x[i] must be >= 0.0. + * If c[i] = -1.0, then x[i] must be <= 0.0. + * If c[i] = -2.0, then x[i] must be < 0.0. + * This routine returns a boolean FALSE if any element failed + * the constraint test, TRUE if all passed. It also sets a + * mask vector m, with elements equal to 1.0 where the + * corresponding constraint test failed, and equal to 0.0 + * where the constraint test passed. + * This routine is specialized in that it is used only for + * constraint checking. + * + * N_VMinQuotient + * Performs the operation : + * minq = min ( num[i]/denom[i]) over all i such that + * denom[i] != 0. + * This routine returns the minimum of the quotients obtained + * by term-wise dividing num[i] by denom[i]. A zero element + * in denom will be skipped. If no such quotients are found, + * then the large value BIG_REAL is returned. + * + * ----------------------------------------------------------------- + * + * The following table lists the vector functions used by + * different modules in SUNDIALS. The symbols in the table + * have the following meaning: + * S - called by the solver; + * D - called by the dense linear solver module + * B - called by the band linear solver module + * Di - called by the diagonal linear solver module + * I - called by the iterative linear solver module + * BP - called by the band preconditioner module + * BBDP - called by the band-block diagonal preconditioner module + * F - called by the Fortran-to-C interface + * + * ------------------------------------------------ + * MODULES + * NVECTOR ------------------------------------------------ + * FUNCTIONS CVODE/CVODES IDA KINSOL + * ----------------------------------------------------------------- + * N_VClone S Di I S I BBDP S I BBDP + * ----------------------------------------------------------------- + * N_VCloneEmpty F F F + * ----------------------------------------------------------------- + * N_VDestroy S Di I S I BBDP S I BBDP + * ----------------------------------------------------------------- + * N_VSpace S S S + * ----------------------------------------------------------------- + * N_VGetArrayPointer D B BP BBDP F D B BBDP BBDP F + * ----------------------------------------------------------------- + * N_VSetArrayPointer D F D F + * ----------------------------------------------------------------- + * N_VLinearSum S D Di I S D I S I + * ----------------------------------------------------------------- + * N_VConst S I S I I + * ----------------------------------------------------------------- + * N_VProd S Di I S I S I + * ----------------------------------------------------------------- + * N_VDiv S Di I S I S I + * ----------------------------------------------------------------- + * N_VScale S D B Di I BP BBDP S D B I BBDP S I BBDP + * ----------------------------------------------------------------- + * N_VAbs S S S + * ----------------------------------------------------------------- + * N_VInv S Di S S + * ----------------------------------------------------------------- + * N_VAddConst S Di S + * ----------------------------------------------------------------- + * N_VDotProd I I I + * ----------------------------------------------------------------- + * N_VMaxNorm S S S + * ----------------------------------------------------------------- + * N_VWrmsNorm S D B I BP BBDP S + * ----------------------------------------------------------------- + * N_VWrmsNormMask S + * ----------------------------------------------------------------- + * N_VMin S S S + * ----------------------------------------------------------------- + * N_VWL2Norm S I + * ----------------------------------------------------------------- + * N_VL1Norm I + * ----------------------------------------------------------------- + * N_VCompare Di S + * ----------------------------------------------------------------- + * N_VInvTest Di + * ----------------------------------------------------------------- + * N_VConstrMask S S + * ----------------------------------------------------------------- + * N_VMinQuotient S S + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VClone(N_Vector w); +SUNDIALS_EXPORT N_Vector N_VCloneEmpty(N_Vector w); +SUNDIALS_EXPORT void N_VDestroy(N_Vector v); +SUNDIALS_EXPORT void N_VSpace(N_Vector v, long int *lrw, long int *liw); +SUNDIALS_EXPORT realtype *N_VGetArrayPointer(N_Vector v); +SUNDIALS_EXPORT void N_VSetArrayPointer(realtype *v_data, N_Vector v); +SUNDIALS_EXPORT void N_VLinearSum(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VConst(realtype c, N_Vector z); +SUNDIALS_EXPORT void N_VProd(N_Vector x, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VDiv(N_Vector x, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VScale(realtype c, N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VAbs(N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VInv(N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VAddConst(N_Vector x, realtype b, N_Vector z); +SUNDIALS_EXPORT realtype N_VDotProd(N_Vector x, N_Vector y); +SUNDIALS_EXPORT realtype N_VMaxNorm(N_Vector x); +SUNDIALS_EXPORT realtype N_VWrmsNorm(N_Vector x, N_Vector w); +SUNDIALS_EXPORT realtype N_VWrmsNormMask(N_Vector x, N_Vector w, N_Vector id); +SUNDIALS_EXPORT realtype N_VMin(N_Vector x); +SUNDIALS_EXPORT realtype N_VWL2Norm(N_Vector x, N_Vector w); +SUNDIALS_EXPORT realtype N_VL1Norm(N_Vector x); +SUNDIALS_EXPORT void N_VCompare(realtype c, N_Vector x, N_Vector z); +SUNDIALS_EXPORT booleantype N_VInvTest(N_Vector x, N_Vector z); +SUNDIALS_EXPORT booleantype N_VConstrMask(N_Vector c, N_Vector x, N_Vector m); +SUNDIALS_EXPORT realtype N_VMinQuotient(N_Vector num, N_Vector denom); + +/* + * ----------------------------------------------------------------- + * Additional functions exported by NVECTOR module + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * N_VCloneEmptyVectorArray + * Creates (by cloning 'w') an array of 'count' empty N_Vectors + * + * N_VCloneVectorArray + * Creates (by cloning 'w') an array of 'count' N_Vectors + * + * N_VDestroyVectorArray + * Frees memory for an array of 'count' N_Vectors that was + * created by a call to N_VCloneVectorArray + * + * These functions are used by the SPGMR iterative linear solver + * module and by the CVODES and IDAS solvers. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector *N_VCloneEmptyVectorArray(int count, N_Vector w); +SUNDIALS_EXPORT N_Vector *N_VCloneVectorArray(int count, N_Vector w); +SUNDIALS_EXPORT void N_VDestroyVectorArray(N_Vector *vs, int count); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/sundials/sundials_spbcgs.h b/odemex/Parser/CVode/ida_src/include/sundials/sundials_spbcgs.h new file mode 100644 index 0000000..d569d1d --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/sundials/sundials_spbcgs.h @@ -0,0 +1,199 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Peter Brown and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2004, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the implementation of the scaled, + * preconditioned Bi-CGSTAB (SPBCG) iterative linear solver. + * ----------------------------------------------------------------- + */ + +#ifndef _SPBCG_H +#define _SPBCG_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Types: struct SpbcgMemRec and struct *SpbcgMem + * ----------------------------------------------------------------- + * A variable declaration of type struct *SpbcgMem denotes a pointer + * to a data structure of type struct SpbcgMemRec. The SpbcgMemRec + * structure contains numerous fields that must be accessed by the + * SPBCG linear solver module. + * + * l_max maximum Krylov subspace dimension that SpbcgSolve will + * be permitted to use + * + * r vector (type N_Vector) which holds the scaled, preconditioned + * linear system residual + * + * r_star vector (type N_Vector) which holds the initial scaled, + * preconditioned linear system residual + * + * p, q, u and Ap vectors (type N_Vector) used for workspace by + * the SPBCG algorithm + * + * vtemp scratch vector (type N_Vector) used as temporary vector + * storage + * ----------------------------------------------------------------- + */ + +typedef struct { + + int l_max; + + N_Vector r_star; + N_Vector r; + N_Vector p; + N_Vector q; + N_Vector u; + N_Vector Ap; + N_Vector vtemp; + +} SpbcgMemRec, *SpbcgMem; + +/* + * ----------------------------------------------------------------- + * Function : SpbcgMalloc + * ----------------------------------------------------------------- + * SpbcgMalloc allocates additional memory needed by the SPBCG + * linear solver module. + * + * l_max maximum Krylov subspace dimension that SpbcgSolve will + * be permitted to use + * + * vec_tmpl implementation-specific template vector (type N_Vector) + * (created using either N_VNew_Serial or N_VNew_Parallel) + * + * If successful, SpbcgMalloc returns a non-NULL memory pointer. If + * an error occurs, then a NULL pointer is returned. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT SpbcgMem SpbcgMalloc(int l_max, N_Vector vec_tmpl); + +/* + * ----------------------------------------------------------------- + * Function : SpbcgSolve + * ----------------------------------------------------------------- + * SpbcgSolve solves the linear system Ax = b by means of a scaled + * preconditioned Bi-CGSTAB (SPBCG) iterative method. + * + * mem pointer to an internal memory block allocated during a + * prior call to SpbcgMalloc + * + * A_data pointer to a data structure containing information + * about the coefficient matrix A (passed to user-supplied + * function referenced by atimes (function pointer)) + * + * x vector (type N_Vector) containing initial guess x_0 upon + * entry, but which upon return contains an approximate solution + * of the linear system Ax = b (solution only valid if return + * value is either SPBCG_SUCCESS or SPBCG_RES_REDUCED) + * + * b vector (type N_Vector) set to the right-hand side vector b + * of the linear system (undisturbed by function) + * + * pretype variable (type int) indicating the type of + * preconditioning to be used (see sundials_iterative.h) + * + * delta tolerance on the L2 norm of the scaled, preconditioned + * residual (if return value == SPBCG_SUCCESS, then + * ||sb*P1_inv*(b-Ax)||_L2 <= delta) + * + * P_data pointer to a data structure containing preconditioner + * information (passed to user-supplied function referenced + * by psolve (function pointer)) + * + * sx vector (type N_Vector) containing positive scaling factors + * for x (pass sx == NULL if scaling NOT required) + * + * sb vector (type N_Vector) containing positive scaling factors + * for b (pass sb == NULL if scaling NOT required) + * + * atimes user-supplied routine responsible for computing the + * matrix-vector product Ax (see sundials_iterative.h) + * + * psolve user-supplied routine responsible for solving the + * preconditioned linear system Pz = r (ignored if + * pretype == PREC_NONE) (see sundials_iterative.h) + * + * res_norm pointer (type realtype*) to the L2 norm of the + * scaled, preconditioned residual (if return value + * is either SPBCG_SUCCESS or SPBCG_RES_REDUCED, then + * *res_norm = ||sb*P1_inv*(b-Ax)||_L2, where x is + * the computed approximate solution, sb is the diagonal + * scaling matrix for the right-hand side b, and P1_inv + * is the inverse of the left-preconditioner matrix) + * + * nli pointer (type int*) to the total number of linear + * iterations performed + * + * nps pointer (type int*) to the total number of calls made + * to the psolve routine + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int SpbcgSolve(SpbcgMem mem, void *A_data, N_Vector x, N_Vector b, + int pretype, realtype delta, void *P_data, N_Vector sx, + N_Vector sb, ATimesFn atimes, PSolveFn psolve, + realtype *res_norm, int *nli, int *nps); + +/* Return values for SpbcgSolve */ + +#define SPBCG_SUCCESS 0 /* SPBCG algorithm converged */ +#define SPBCG_RES_REDUCED 1 /* SPBCG did NOT converge, but the + residual was reduced */ +#define SPBCG_CONV_FAIL 2 /* SPBCG algorithm failed to converge */ +#define SPBCG_PSOLVE_FAIL_REC 3 /* psolve failed recoverably */ +#define SPBCG_ATIMES_FAIL_REC 4 /* atimes failed recoverably */ +#define SPBCG_PSET_FAIL_REC 5 /* pset faild recoverably */ + +#define SPBCG_MEM_NULL -1 /* mem argument is NULL */ +#define SPBCG_ATIMES_FAIL_UNREC -2 /* atimes returned failure flag */ +#define SPBCG_PSOLVE_FAIL_UNREC -3 /* psolve failed unrecoverably */ +#define SPBCG_PSET_FAIL_UNREC -4 /* pset failed unrecoverably */ + +/* + * ----------------------------------------------------------------- + * Function : SpbcgFree + * ----------------------------------------------------------------- + * SpbcgFree frees the memory allocated by a call to SpbcgMalloc. + * It is illegal to use the pointer mem after a call to SpbcgFree. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void SpbcgFree(SpbcgMem mem); + +/* + * ----------------------------------------------------------------- + * Macro : SPBCG_VTEMP + * ----------------------------------------------------------------- + * This macro provides access to the vector r in the + * memory block of the SPBCG module. The argument mem is the + * memory pointer returned by SpbcgMalloc, of type SpbcgMem, + * and the macro value is of type N_Vector. + * + * Note: Only used by IDA (r contains P_inverse F if nli_inc == 0). + * ----------------------------------------------------------------- + */ + +#define SPBCG_VTEMP(mem) (mem->r) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/sundials/sundials_spgmr.h b/odemex/Parser/CVode/ida_src/include/sundials/sundials_spgmr.h new file mode 100644 index 0000000..c557acd --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/sundials/sundials_spgmr.h @@ -0,0 +1,296 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the implementation of SPGMR Krylov + * iterative linear solver. The SPGMR algorithm is based on the + * Scaled Preconditioned GMRES (Generalized Minimal Residual) + * method. + * + * The SPGMR algorithm solves a linear system A x = b. + * Preconditioning is allowed on the left, right, or both. + * Scaling is allowed on both sides, and restarts are also allowed. + * We denote the preconditioner and scaling matrices as follows: + * P1 = left preconditioner + * P2 = right preconditioner + * S1 = diagonal matrix of scale factors for P1-inverse b + * S2 = diagonal matrix of scale factors for P2 x + * The matrices A, P1, and P2 are not required explicitly; only + * routines that provide A, P1-inverse, and P2-inverse as + * operators are required. + * + * In this notation, SPGMR applies the underlying GMRES method to + * the equivalent transformed system + * Abar xbar = bbar , where + * Abar = S1 (P1-inverse) A (P2-inverse) (S2-inverse) , + * bbar = S1 (P1-inverse) b , and xbar = S2 P2 x . + * + * The scaling matrices must be chosen so that vectors S1 + * P1-inverse b and S2 P2 x have dimensionless components. + * If preconditioning is done on the left only (P2 = I), by a + * matrix P, then S2 must be a scaling for x, while S1 is a + * scaling for P-inverse b, and so may also be taken as a scaling + * for x. Similarly, if preconditioning is done on the right only + * (P1 = I, P2 = P), then S1 must be a scaling for b, while S2 is + * a scaling for P x, and may also be taken as a scaling for b. + * + * The stopping test for the SPGMR iterations is on the L2 norm of + * the scaled preconditioned residual: + * || bbar - Abar xbar ||_2 < delta + * with an input test constant delta. + * + * The usage of this SPGMR solver involves supplying two routines + * and making three calls. The user-supplied routines are + * atimes (A_data, x, y) to compute y = A x, given x, + * and + * psolve (P_data, x, y, lr) + * to solve P1 x = y or P2 x = y for x, given y. + * The three user calls are: + * mem = SpgmrMalloc(lmax, vec_tmpl); + * to initialize memory, + * flag = SpgmrSolve(mem,A_data,x,b,..., + * P_data,s1,s2,atimes,psolve,...); + * to solve the system, and + * SpgmrFree(mem); + * to free the memory created by SpgmrMalloc. + * Complete details for specifying atimes and psolve and for the + * usage calls are given in the paragraphs below and in iterative.h. + * ----------------------------------------------------------------- + */ + +#ifndef _SPGMR_H +#define _SPGMR_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Types: SpgmrMemRec, SpgmrMem + * ----------------------------------------------------------------- + * SpgmrMem is a pointer to an SpgmrMemRec which contains + * the memory needed by SpgmrSolve. The SpgmrMalloc routine + * returns a pointer of type SpgmrMem which should then be passed + * in subsequent calls to SpgmrSolve. The SpgmrFree routine frees + * the memory allocated by SpgmrMalloc. + * + * l_max is the maximum Krylov dimension that SpgmrSolve will be + * permitted to use. + * + * V is the array of Krylov basis vectors v_1, ..., v_(l_max+1), + * stored in V[0], ..., V[l_max], where l_max is the second + * parameter to SpgmrMalloc. Each v_i is a vector of type + * N_Vector. + * + * Hes is the (l_max+1) x l_max Hessenberg matrix. It is stored + * row-wise so that the (i,j)th element is given by Hes[i][j]. + * + * givens is a length 2*l_max array which represents the + * Givens rotation matrices that arise in the algorithm. The + * Givens rotation matrices F_0, F_1, ..., F_j, where F_i is + * + * 1 + * 1 + * c_i -s_i <--- row i + * s_i c_i + * 1 + * 1 + * + * are represented in the givens vector as + * givens[0]=c_0, givens[1]=s_0, givens[2]=c_1, givens[3]=s_1, + * ..., givens[2j]=c_j, givens[2j+1]=s_j. + * + * xcor is a vector (type N_Vector) which holds the scaled, + * preconditioned correction to the initial guess. + * + * yg is a length (l_max+1) array of realtype used to hold "short" + * vectors (e.g. y and g). + * + * vtemp is a vector (type N_Vector) used as temporary vector + * storage during calculations. + * ----------------------------------------------------------------- + */ + +typedef struct _SpgmrMemRec { + + int l_max; + + N_Vector *V; + realtype **Hes; + realtype *givens; + N_Vector xcor; + realtype *yg; + N_Vector vtemp; + +} SpgmrMemRec, *SpgmrMem; + +/* + * ----------------------------------------------------------------- + * Function : SpgmrMalloc + * ----------------------------------------------------------------- + * SpgmrMalloc allocates the memory used by SpgmrSolve. It + * returns a pointer of type SpgmrMem which the user of the + * SPGMR package should pass to SpgmrSolve. The parameter l_max + * is the maximum Krylov dimension that SpgmrSolve will be + * permitted to use. The parameter vec_tmpl is a pointer to an + * N_Vector used as a template to create new vectors by duplication. + * This routine returns NULL if there is a memory request failure. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT SpgmrMem SpgmrMalloc(int l_max, N_Vector vec_tmpl); + +/* + * ----------------------------------------------------------------- + * Function : SpgmrSolve + * ----------------------------------------------------------------- + * SpgmrSolve solves the linear system Ax = b using the SPGMR + * method. The return values are given by the symbolic constants + * below. The first SpgmrSolve parameter is a pointer to memory + * allocated by a prior call to SpgmrMalloc. + * + * mem is the pointer returned by SpgmrMalloc to the structure + * containing the memory needed by SpgmrSolve. + * + * A_data is a pointer to information about the coefficient + * matrix A. This pointer is passed to the user-supplied function + * atimes. + * + * x is the initial guess x_0 upon entry and the solution + * N_Vector upon exit with return value SPGMR_SUCCESS or + * SPGMR_RES_REDUCED. For all other return values, the output x + * is undefined. + * + * b is the right hand side N_Vector. It is undisturbed by this + * function. + * + * pretype is the type of preconditioning to be used. Its + * legal possible values are enumerated in iterativ.h. These + * values are PREC_NONE=0, PREC_LEFT=1, PREC_RIGHT=2, and + * PREC_BOTH=3. + * + * gstype is the type of Gram-Schmidt orthogonalization to be + * used. Its legal values are enumerated in iterativ.h. These + * values are MODIFIED_GS=0 and CLASSICAL_GS=1. + * + * delta is the tolerance on the L2 norm of the scaled, + * preconditioned residual. On return with value SPGMR_SUCCESS, + * this residual satisfies || s1 P1_inv (b - Ax) ||_2 <= delta. + * + * max_restarts is the maximum number of times the algorithm is + * allowed to restart. + * + * P_data is a pointer to preconditioner information. This + * pointer is passed to the user-supplied function psolve. + * + * s1 is an N_Vector of positive scale factors for P1-inv b, where + * P1 is the left preconditioner. (Not tested for positivity.) + * Pass NULL if no scaling on P1-inv b is required. + * + * s2 is an N_Vector of positive scale factors for P2 x, where + * P2 is the right preconditioner. (Not tested for positivity.) + * Pass NULL if no scaling on P2 x is required. + * + * atimes is the user-supplied function which performs the + * operation of multiplying A by a given vector. Its description + * is given in iterative.h. + * + * psolve is the user-supplied function which solves a + * preconditioner system Pz = r, where P is P1 or P2. Its full + * description is given in iterativ.h. The psolve function will + * not be called if pretype is NONE; in that case, the user + * should pass NULL for psolve. + * + * res_norm is a pointer to the L2 norm of the scaled, + * preconditioned residual. On return with value SPGMR_SUCCESS or + * SPGMR_RES_REDUCED, (*res_norm) contains the value + * || s1 P1_inv (b - Ax) ||_2 for the computed solution x. + * For all other return values, (*res_norm) is undefined. The + * caller is responsible for allocating the memory (*res_norm) + * to be filled in by SpgmrSolve. + * + * nli is a pointer to the number of linear iterations done in + * the execution of SpgmrSolve. The caller is responsible for + * allocating the memory (*nli) to be filled in by SpgmrSolve. + * + * nps is a pointer to the number of calls made to psolve during + * the execution of SpgmrSolve. The caller is responsible for + * allocating the memory (*nps) to be filled in by SpgmrSolve. + * + * Note: Repeated calls can be made to SpgmrSolve with varying + * input arguments. If, however, the problem size N or the + * maximum Krylov dimension l_max changes, then a call to + * SpgmrMalloc must be made to obtain new memory for SpgmrSolve + * to use. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int SpgmrSolve(SpgmrMem mem, void *A_data, N_Vector x, N_Vector b, + int pretype, int gstype, realtype delta, + int max_restarts, void *P_data, N_Vector s1, + N_Vector s2, ATimesFn atimes, PSolveFn psolve, + realtype *res_norm, int *nli, int *nps); + + +/* Return values for SpgmrSolve */ + +#define SPGMR_SUCCESS 0 /* Converged */ +#define SPGMR_RES_REDUCED 1 /* Did not converge, but reduced + norm of residual */ +#define SPGMR_CONV_FAIL 2 /* Failed to converge */ +#define SPGMR_QRFACT_FAIL 3 /* QRfact found singular matrix */ +#define SPGMR_PSOLVE_FAIL_REC 4 /* psolve failed recoverably */ +#define SPGMR_ATIMES_FAIL_REC 5 /* atimes failed recoverably */ +#define SPGMR_PSET_FAIL_REC 6 /* pset faild recoverably */ + +#define SPGMR_MEM_NULL -1 /* mem argument is NULL */ +#define SPGMR_ATIMES_FAIL_UNREC -2 /* atimes returned failure flag */ +#define SPGMR_PSOLVE_FAIL_UNREC -3 /* psolve failed unrecoverably */ +#define SPGMR_GS_FAIL -4 /* Gram-Schmidt routine faiuled */ +#define SPGMR_QRSOL_FAIL -5 /* QRsol found singular R */ +#define SPGMR_PSET_FAIL_UNREC -6 /* pset failed unrecoverably */ + +/* + * ----------------------------------------------------------------- + * Function : SpgmrFree + * ----------------------------------------------------------------- + * SpgmrMalloc frees the memory allocated by SpgmrMalloc. It is + * illegal to use the pointer mem after a call to SpgmrFree. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void SpgmrFree(SpgmrMem mem); + +/* + * ----------------------------------------------------------------- + * Macro: SPGMR_VTEMP + * ----------------------------------------------------------------- + * This macro provides access to the work vector vtemp in the + * memory block of the SPGMR module. The argument mem is the + * memory pointer returned by SpgmrMalloc, of type SpgmrMem, + * and the macro value is of type N_Vector. + * On a return from SpgmrSolve with *nli = 0, this vector + * contains the scaled preconditioned initial residual, + * s1 * P1_inverse * (b - A x_0). + * ----------------------------------------------------------------- + */ + +#define SPGMR_VTEMP(mem) (mem->vtemp) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/sundials/sundials_sptfqmr.h b/odemex/Parser/CVode/ida_src/include/sundials/sundials_sptfqmr.h new file mode 100644 index 0000000..2ba5c37 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/sundials/sundials_sptfqmr.h @@ -0,0 +1,254 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the implementation of the scaled + * preconditioned Transpose-Free Quasi-Minimal Residual (SPTFQMR) + * linear solver. + * + * The SPTFQMR algorithm solves a linear system of the form Ax = b. + * Preconditioning is allowed on the left (PREC_LEFT), right + * (PREC_RIGHT), or both (PREC_BOTH). Scaling is allowed on both + * sides. We denote the preconditioner and scaling matrices as + * follows: + * P1 = left preconditioner + * P2 = right preconditioner + * S1 = diagonal matrix of scale factors for P1-inverse b + * S2 = diagonal matrix of scale factors for P2 x + * The matrices A, P1, and P2 are not required explicitly; only + * routines that provide A, P1-inverse, and P2-inverse as operators + * are required. + * + * In this notation, SPTFQMR applies the underlying TFQMR method to + * the equivalent transformed system: + * Abar xbar = bbar, where + * Abar = S1 (P1-inverse) A (P2-inverse) (S2-inverse), + * bbar = S1 (P1-inverse) b, and + * xbar = S2 P2 x. + * + * The scaling matrices must be chosen so that vectors + * S1 P1-inverse b and S2 P2 x have dimensionless components. If + * preconditioning is done on the left only (P2 = I), by a matrix P, + * then S2 must be a scaling for x, while S1 is a scaling for + * P-inverse b, and so may also be taken as a scaling for x. + * Similarly, if preconditioning is done on the right only (P1 = I, + * P2 = P), then S1 must be a scaling for b, while S2 is a scaling + * for P x, and may also be taken as a scaling for b. + * + * The stopping test for the SPTFQMR iterations is on the L2-norm of + * the scaled preconditioned residual: + * || bbar - Abar xbar ||_2 < delta + * with an input test constant delta. + * + * The usage of this SPTFQMR solver involves supplying two routines + * and making three calls. The user-supplied routines are: + * atimes(A_data, x, y) to compute y = A x, given x, + * and + * psolve(P_data, x, y, lr) to solve P1 x = y or P2 x = y for x, + * given y. + * The three user calls are: + * mem = SptfqmrMalloc(lmax, vec_tmpl); + * to initialize memory + * flag = SptfqmrSolve(mem, A_data, x, b, pretype, delta, P_data, + * sx, sb, atimes, psolve, res_norm, nli, nps); + * to solve the system, and + * SptfqmrFree(mem); + * to free the memory allocated by SptfqmrMalloc(). + * Complete details for specifying atimes() and psolve() and for the + * usage calls are given in the paragraphs below and in the header + * file sundials_iterative.h. + * ----------------------------------------------------------------- + */ + +#ifndef _SPTFQMR_H +#define _SPTFQMR_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Types: struct SptfqmrMemRec and struct *SptfqmrMem + * ----------------------------------------------------------------- + * A variable declaration of type struct *SptfqmrMem denotes a pointer + * to a data structure of type struct SptfqmrMemRec. The SptfqmrMemRec + * structure contains numerous fields that must be accessed by the + * SPTFQMR linear solver module. + * + * l_max maximum Krylov subspace dimension that SptfqmrSolve will + * be permitted to use + * + * r_star vector (type N_Vector) which holds the initial scaled, + * preconditioned linear system residual + * + * q/d/v/p/u/r vectors (type N_Vector) used for workspace by + * the SPTFQMR algorithm + * + * vtemp1/vtemp2/vtemp3 scratch vectors (type N_Vector) used as + * temporary storage + * ----------------------------------------------------------------- + */ + +typedef struct { + + int l_max; + + N_Vector r_star; + N_Vector q; + N_Vector d; + N_Vector v; + N_Vector p; + N_Vector *r; + N_Vector u; + N_Vector vtemp1; + N_Vector vtemp2; + N_Vector vtemp3; + +} SptfqmrMemRec, *SptfqmrMem; + +/* + * ----------------------------------------------------------------- + * Function : SptfqmrMalloc + * ----------------------------------------------------------------- + * SptfqmrMalloc allocates additional memory needed by the SPTFQMR + * linear solver module. + * + * l_max maximum Krylov subspace dimension that SptfqmrSolve will + * be permitted to use + * + * vec_tmpl implementation-specific template vector (type N_Vector) + * (created using either N_VNew_Serial or N_VNew_Parallel) + * + * If successful, SptfqmrMalloc returns a non-NULL memory pointer. If + * an error occurs, then a NULL pointer is returned. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT SptfqmrMem SptfqmrMalloc(int l_max, N_Vector vec_tmpl); + +/* + * ----------------------------------------------------------------- + * Function : SptfqmrSolve + * ----------------------------------------------------------------- + * SptfqmrSolve solves the linear system Ax = b by means of a scaled + * preconditioned Transpose-Free Quasi-Minimal Residual (SPTFQMR) + * method. + * + * mem pointer to an internal memory block allocated during a + * prior call to SptfqmrMalloc + * + * A_data pointer to a data structure containing information + * about the coefficient matrix A (passed to user-supplied + * function referenced by atimes (function pointer)) + * + * x vector (type N_Vector) containing initial guess x_0 upon + * entry, but which upon return contains an approximate solution + * of the linear system Ax = b (solution only valid if return + * value is either SPTFQMR_SUCCESS or SPTFQMR_RES_REDUCED) + * + * b vector (type N_Vector) set to the right-hand side vector b + * of the linear system (undisturbed by function) + * + * pretype variable (type int) indicating the type of + * preconditioning to be used (see sundials_iterative.h) + * + * delta tolerance on the L2 norm of the scaled, preconditioned + * residual (if return value == SPTFQMR_SUCCESS, then + * ||sb*P1_inv*(b-Ax)||_L2 <= delta) + * + * P_data pointer to a data structure containing preconditioner + * information (passed to user-supplied function referenced + * by psolve (function pointer)) + * + * sx vector (type N_Vector) containing positive scaling factors + * for x (pass sx == NULL if scaling NOT required) + * + * sb vector (type N_Vector) containing positive scaling factors + * for b (pass sb == NULL if scaling NOT required) + * + * atimes user-supplied routine responsible for computing the + * matrix-vector product Ax (see sundials_iterative.h) + * + * psolve user-supplied routine responsible for solving the + * preconditioned linear system Pz = r (ignored if + * pretype == PREC_NONE) (see sundials_iterative.h) + * + * res_norm pointer (type realtype*) to the L2 norm of the + * scaled, preconditioned residual (if return value + * is either SPTFQMR_SUCCESS or SPTFQMR_RES_REDUCED, then + * *res_norm = ||sb*P1_inv*(b-Ax)||_L2, where x is + * the computed approximate solution, sb is the diagonal + * scaling matrix for the right-hand side b, and P1_inv + * is the inverse of the left-preconditioner matrix) + * + * nli pointer (type int*) to the total number of linear + * iterations performed + * + * nps pointer (type int*) to the total number of calls made + * to the psolve routine + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int SptfqmrSolve(SptfqmrMem mem, void *A_data, N_Vector x, N_Vector b, + int pretype, realtype delta, void *P_data, N_Vector sx, + N_Vector sb, ATimesFn atimes, PSolveFn psolve, + realtype *res_norm, int *nli, int *nps); + +/* Return values for SptfqmrSolve */ + +#define SPTFQMR_SUCCESS 0 /* SPTFQMR algorithm converged */ +#define SPTFQMR_RES_REDUCED 1 /* SPTFQMR did NOT converge, but the + residual was reduced */ +#define SPTFQMR_CONV_FAIL 2 /* SPTFQMR algorithm failed to converge */ +#define SPTFQMR_PSOLVE_FAIL_REC 3 /* psolve failed recoverably */ +#define SPTFQMR_ATIMES_FAIL_REC 4 /* atimes failed recoverably */ +#define SPTFQMR_PSET_FAIL_REC 5 /* pset faild recoverably */ + +#define SPTFQMR_MEM_NULL -1 /* mem argument is NULL */ +#define SPTFQMR_ATIMES_FAIL_UNREC -2 /* atimes returned failure flag */ +#define SPTFQMR_PSOLVE_FAIL_UNREC -3 /* psolve failed unrecoverably */ +#define SPTFQMR_PSET_FAIL_UNREC -4 /* pset failed unrecoverably */ + +/* + * ----------------------------------------------------------------- + * Function : SptfqmrFree + * ----------------------------------------------------------------- + * SptfqmrFree frees the memory allocated by a call to SptfqmrMalloc. + * It is illegal to use the pointer mem after a call to SptfqmrFree. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void SptfqmrFree(SptfqmrMem mem); + +/* + * ----------------------------------------------------------------- + * Macro : SPTFQMR_VTEMP + * ----------------------------------------------------------------- + * This macro provides access to the work vector vtemp1 in the + * memory block of the SPTFQMR module. The argument mem is the + * memory pointer returned by SptfqmrMalloc, of type SptfqmrMem, + * and the macro value is of type N_Vector. + * + * Note: Only used by IDA (vtemp1 contains P_inverse F if + * nli_inc == 0). + * ----------------------------------------------------------------- + */ + +#define SPTFQMR_VTEMP(mem) (mem->vtemp1) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/sundials/sundials_types.h b/odemex/Parser/CVode/ida_src/include/sundials/sundials_types.h new file mode 100644 index 0000000..953f6e0 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/sundials/sundials_types.h @@ -0,0 +1,122 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott Cohen, Alan Hindmarsh, Radu Serban, and + * Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + *------------------------------------------------------------------ + * This header file exports two types: realtype and booleantype, + * as well as the constants TRUE and FALSE. + * + * Users should include the header file sundials_types.h in every + * program file and use the exported name realtype instead of + * float, double or long double. + * + * The constants SUNDIALS_SINGLE_PRECISION, SUNDIALS_DOUBLE_PRECISION + * and SUNDIALS_LONG_DOUBLE_PRECISION indicate the underlying data + * type of realtype. It is set at the configuration stage. + * + * The legal types for realtype are float, double and long double. + * + * The macro RCONST gives the user a convenient way to define + * real-valued constants. To use the constant 1.0, for example, + * the user should write the following: + * + * #define ONE RCONST(1.0) + * + * If realtype is defined as a double, then RCONST(1.0) expands + * to 1.0. If realtype is defined as a float, then RCONST(1.0) + * expands to 1.0F. If realtype is defined as a long double, + * then RCONST(1.0) expands to 1.0L. There is never a need to + * explicitly cast 1.0 to (realtype). + *------------------------------------------------------------------ + */ + +#ifndef _SUNDIALSTYPES_H +#define _SUNDIALSTYPES_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#ifndef _SUNDIALS_CONFIG_H +#define _SUNDIALS_CONFIG_H +#include +#endif + +#include + +/* + *------------------------------------------------------------------ + * Type realtype + * Macro RCONST + * Constants BIG_REAL, SMALL_REAL, and UNIT_ROUNDOFF + *------------------------------------------------------------------ + */ + +#if defined(SUNDIALS_SINGLE_PRECISION) + +typedef float realtype; +# define RCONST(x) x##F +# define BIG_REAL FLT_MAX +# define SMALL_REAL FLT_MIN +# define UNIT_ROUNDOFF FLT_EPSILON + +#elif defined(SUNDIALS_DOUBLE_PRECISION) + +typedef double realtype; +# define RCONST(x) x +# define BIG_REAL DBL_MAX +# define SMALL_REAL DBL_MIN +# define UNIT_ROUNDOFF DBL_EPSILON + +#elif defined(SUNDIALS_EXTENDED_PRECISION) + +typedef long double realtype; +# define RCONST(x) x##L +# define BIG_REAL LDBL_MAX +# define SMALL_REAL LDBL_MIN +# define UNIT_ROUNDOFF LDBL_EPSILON + +#endif + +/* + *------------------------------------------------------------------ + * Type : booleantype + *------------------------------------------------------------------ + * Constants : FALSE and TRUE + *------------------------------------------------------------------ + * ANSI C does not have a built-in boolean data type. Below is the + * definition for a new type called booleantype. The advantage of + * using the name booleantype (instead of int) is an increase in + * code readability. It also allows the programmer to make a + * distinction between int and boolean data. Variables of type + * booleantype are intended to have only the two values FALSE and + * TRUE which are defined below to be equal to 0 and 1, + * respectively. + *------------------------------------------------------------------ + */ + +#ifndef booleantype +#define booleantype int +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/include/sundials/winDefine.h b/odemex/Parser/CVode/ida_src/include/sundials/winDefine.h new file mode 100644 index 0000000..dcd0e20 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/include/sundials/winDefine.h @@ -0,0 +1,44 @@ +// +// Joep Vanlier, 2011 +// +// Licensing: +// Copyright (C) 2009-2011 Joep Vanlier. All rights +// reserved. +// +// Contact:joep.vanlier@gmail.com +// +// This file is part of the puaMAT. +// +// puaMAT is free software: you can redistribute it +// and/or modify it under the terms of the GNU General +// Public License as published by the Free Software +// Foundation, either version 3 of the License, or (at +// your option) any later version. +// +// puaMAT is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the +// implied warranty of MERCHANTABILITY or FITNESS FOR A +// PARTICULAR PURPOSE. See the GNU General Public +// License for more details. +// +// You should have received a copy of the GNU General +// Public License along with puaMAT. If not, see +// http://www.gnu.org/licenses/ +// + + + #define dcopy_ dcopy + #define dscal_ dscal + #define dgemv_ dgemv + #define dtrsv_ dtrsv + #define dgetrf_ dgetrf + #define dgetrs_ dgetrs + #define dgbtrs_ dgbtrs + #define dgbtrf_ dgbtrf + #define dsyrk_ dsyrk + #define dgeqp3_ dgeqp3 + #define dormqr_ dormqr + #define dpotrf_ dpotrf_ + #define dgeqrf_ dgeqrf + #define dpotrs_ dpotrs + diff --git a/odemex/Parser/CVode/ida_src/src/ida/CMakeLists.txt b/odemex/Parser/CVode/ida_src/src/ida/CMakeLists.txt new file mode 100644 index 0000000..438ee2d --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/CMakeLists.txt @@ -0,0 +1,125 @@ +# --------------------------------------------------------------- +# $Revision: 1.4 $ +# $Date: 2009/02/17 02:58:48 $ +# --------------------------------------------------------------- +# Programmer: Radu Serban @ LLNL +# --------------------------------------------------------------- +# Copyright (c) 2007, The Regents of the University of California. +# Produced at the Lawrence Livermore National Laboratory. +# All rights reserved. +# For details, see the LICENSE file. +# --------------------------------------------------------------- +# CMakeLists.txt file for the IDA library + +INSTALL(CODE "MESSAGE(\"\nInstall IDA\n\")") + +# Add variable ida_SOURCES with the sources for the IDA library +SET(ida_SOURCES + ida.c + ida_io.c + ida_ic.c + ida_direct.c + ida_band.c + ida_dense.c + ida_spils.c + ida_spbcgs.c + ida_spgmr.c + ida_sptfqmr.c + ida_bbdpre.c + ) + +# Add variable shared_SOURCES with the common SUNDIALS sources which will +# also be included in the IDA library +SET(shared_SOURCES + sundials_nvector.c + sundials_math.c + sundials_direct.c + sundials_band.c + sundials_dense.c + sundials_iterative.c + sundials_spbcgs.c + sundials_spgmr.c + sundials_sptfqmr.c + ) + +# Add prefix with complete path to the common SUNDIALS sources +ADD_PREFIX(${sundials_SOURCE_DIR}/src/sundials/ shared_SOURCES) + +# Add variable ida_HEADERS with the exported IDA header files +SET(ida_HEADERS + ida_band.h + ida_bbdpre.h + ida_dense.h + ida_direct.h + ida.h + ida_spbcgs.h + ida_spgmr.h + ida_spils.h + ida_sptfqmr.h + ) + +# Add prefix with complete path to the IDA header files +ADD_PREFIX(${sundials_SOURCE_DIR}/include/ida/ ida_HEADERS) + +# If Blas/Lapack support was enabled, set-up additional file lists +IF(LAPACK_FOUND) + SET(ida_BL_SOURCES ida_lapack.c) + SET(ida_BL_HEADERS ida_lapack.h) + ADD_PREFIX(${sundials_SOURCE_DIR}/include/ida/ ida_BL_HEADERS) +ELSE(LAPACK_FOUND) + SET(ida_BL_SOURCES "") + SET(ida_BL_HEADERS "") +ENDIF(LAPACK_FOUND) + +# Add source directories to include directories for access to +# implementation only header files. +INCLUDE_DIRECTORIES(.) +INCLUDE_DIRECTORIES(../sundials) + +# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY +ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY) + +# Build the static library +IF(BUILD_STATIC_LIBS) + + # Add the build target for the static IDA library + ADD_LIBRARY(sundials_ida_static STATIC + ${ida_SOURCES} ${ida_BL_SOURCES} ${shared_SOURCES}) + + # Set the library name and make sure it is not deleted + SET_TARGET_PROPERTIES(sundials_ida_static + PROPERTIES OUTPUT_NAME sundials_ida CLEAN_DIRECT_OUTPUT 1) + + # Install the IDA library + INSTALL(TARGETS sundials_ida_static DESTINATION lib) + +ENDIF(BUILD_STATIC_LIBS) + +# Build the shared library +IF(BUILD_SHARED_LIBS) + + # Add the build target for the IDA library + ADD_LIBRARY(sundials_ida_shared SHARED + ${ida_SOURCES} ${ida_BL_SOURCES} ${shared_SOURCES}) + + # Set the library name and make sure it is not deleted + SET_TARGET_PROPERTIES(sundials_ida_shared + PROPERTIES OUTPUT_NAME sundials_ida CLEAN_DIRECT_OUTPUT 1) + + # Set VERSION and SOVERSION for shared libraries + SET_TARGET_PROPERTIES(sundials_ida_shared + PROPERTIES VERSION ${idalib_VERSION} SOVERSION ${idalib_SOVERSION}) + + # Install the IDA library + INSTALL(TARGETS sundials_ida_shared DESTINATION lib) + +ENDIF(BUILD_SHARED_LIBS) + +# Install the IDA header files +INSTALL(FILES ${ida_HEADERS} ${ida_BL_HEADERS} DESTINATION include/ida) + +# Install the IDA implementation header file +INSTALL(FILES ida_impl.h DESTINATION include/ida) + +# +MESSAGE(STATUS "Added IDA module") diff --git a/odemex/Parser/CVode/ida_src/src/ida/LICENSE b/odemex/Parser/CVode/ida_src/src/ida/LICENSE new file mode 100644 index 0000000..d50d177 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/LICENSE @@ -0,0 +1,59 @@ +Copyright (c) 2002, The Regents of the University of California. +Produced at the Lawrence Livermore National Laboratory. +Written by Alan Hindmarsh, Allan Taylor, Radu Serban. +UCRL-CODE-155952 +All rights reserved. + +This file is part of IDA. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the disclaimer below. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the disclaimer (as noted below) +in the documentation and/or other materials provided with the +distribution. + +3. Neither the name of the UC/LLNL nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +REGENTS OF THE UNIVERSITY OF CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Additional BSD Notice +--------------------- +1. This notice is required to be provided under our contract with +the U.S. Department of Energy (DOE). This work was produced at the +University of California, Lawrence Livermore National Laboratory +under Contract No. W-7405-ENG-48 with the DOE. + +2. Neither the United States Government nor the University of +California nor any of their employees, makes any warranty, express +or implied, or assumes any liability or responsibility for the +accuracy, completeness, or usefulness of any information, apparatus, +product, or process disclosed, or represents that its use would not +infringe privately-owned rights. + +3. Also, reference herein to any specific commercial products, +process, or services by trade name, trademark, manufacturer or +otherwise does not necessarily constitute or imply its endorsement, +recommendation, or favoring by the United States Government or the +University of California. The views and opinions of authors expressed +herein do not necessarily state or reflect those of the United States +Government or the University of California, and shall not be used for +advertising or product endorsement purposes. diff --git a/odemex/Parser/CVode/ida_src/src/ida/Makefile.in b/odemex/Parser/CVode/ida_src/src/ida/Makefile.in new file mode 100644 index 0000000..8c83d7a --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/Makefile.in @@ -0,0 +1,169 @@ +# ----------------------------------------------------------------- +# $Revision: 1.12 $ +# $Date: 2009/03/25 23:10:50 $ +# ----------------------------------------------------------------- +# Programmer(s): Radu Serban and Aaron Collier @ LLNL +# ----------------------------------------------------------------- +# Copyright (c) 2002, The Regents of the University of California. +# Produced at the Lawrence Livermore National Laboratory. +# All rights reserved. +# For details, see the LICENSE file. +# ----------------------------------------------------------------- +# Makefile for IDA module +# +# @configure_input@ +# ----------------------------------------------------------------- + +SHELL = @SHELL@ + +@SET_MAKE@ + +srcdir = @srcdir@ +builddir = @builddir@ +abs_builddir = @abs_builddir@ +top_builddir = @top_builddir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +includedir = @includedir@ +libdir = @libdir@ + +INSTALL = @INSTALL@ +INSTALL_LIB = @INSTALL_PROGRAM@ +INSTALL_HEADER = @INSTALL_DATA@ + +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ + +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CC = @CC@ +CFLAGS = @CFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ + +LAPACK_ENABLED = @LAPACK_ENABLED@ + +top_srcdir = $(srcdir)/../.. + +INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include + +LIB_REVISION = 2:0:0 + +IDA_LIB = libsundials_ida.la + +IDA_SRC_FILES = ida.c ida_ic.c ida_io.c ida_direct.c ida_dense.c ida_band.c ida_spils.c ida_spbcgs.c ida_spgmr.c ida_sptfqmr.c ida_bbdpre.c +IDA_BL_SRC_FILES = ida_lapack.c + +IDA_OBJ_FILES = $(IDA_SRC_FILES:.c=.o) +IDA_BL_OBJ_FILES = $(IDA_BL_SRC_FILES:.c=.o) + +IDA_LIB_FILES = $(IDA_SRC_FILES:.c=.lo) +IDA_BL_LIB_FILES = $(IDA_BL_SRC_FILES:.c=.lo) + +SHARED_LIB_FILES = $(top_builddir)/src/sundials/sundials_band.lo \ + $(top_builddir)/src/sundials/sundials_dense.lo \ + $(top_builddir)/src/sundials/sundials_direct.lo \ + $(top_builddir)/src/sundials/sundials_iterative.lo \ + $(top_builddir)/src/sundials/sundials_spgmr.lo \ + $(top_builddir)/src/sundials/sundials_spbcgs.lo \ + $(top_builddir)/src/sundials/sundials_sptfqmr.lo \ + $(top_builddir)/src/sundials/sundials_math.lo \ + $(top_builddir)/src/sundials/sundials_nvector.lo + +mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs +rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs + +# ---------------------------------------------------------------------------------------------------------------------- + +all: $(IDA_LIB) + +$(IDA_LIB): shared $(IDA_LIB_FILES) + @if test "X${LAPACK_ENABLED}" = "Xyes"; then \ + make lib_with_bl; \ + else \ + make lib_without_bl; \ + fi + +lib_without_bl: shared $(IDA_LIB_FILES) + $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(IDA_LIB) $(IDA_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -version-info $(LIB_REVISION) + +lib_with_bl: shared $(IDA_LIB_FILES) $(IDA_BL_LIB_FILES) + $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(IDA_LIB) $(IDA_LIB_FILES) $(IDA_BL_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -version-info $(LIB_REVISION) + +install: $(IDA_LIB) + $(mkinstalldirs) $(includedir)/ida + $(mkinstalldirs) $(libdir) + $(LIBTOOL) --mode=install $(INSTALL_LIB) $(IDA_LIB) $(libdir) + $(INSTALL_HEADER) $(top_srcdir)/include/ida/ida.h $(includedir)/ida/ + $(INSTALL_HEADER) $(top_srcdir)/include/ida/ida_direct.h $(includedir)/ida/ + $(INSTALL_HEADER) $(top_srcdir)/include/ida/ida_dense.h $(includedir)/ida/ + $(INSTALL_HEADER) $(top_srcdir)/include/ida/ida_band.h $(includedir)/ida/ + $(INSTALL_HEADER) $(top_srcdir)/include/ida/ida_spbcgs.h $(includedir)/ida/ + $(INSTALL_HEADER) $(top_srcdir)/include/ida/ida_spgmr.h $(includedir)/ida/ + $(INSTALL_HEADER) $(top_srcdir)/include/ida/ida_sptfqmr.h $(includedir)/ida/ + $(INSTALL_HEADER) $(top_srcdir)/include/ida/ida_bbdpre.h $(includedir)/ida/ + $(INSTALL_HEADER) $(top_srcdir)/include/ida/ida_spils.h $(includedir)/ida/ + $(INSTALL_HEADER) $(top_srcdir)/src/ida/ida_impl.h $(includedir)/ida/ + @if test "X${LAPACK_ENABLED}" = "Xyes"; then \ + $(INSTALL_HEADER) $(top_srcdir)/include/ida/ida_lapack.h $(includedir)/ida/ ; \ + fi + +uninstall: + $(LIBTOOL) --mode=uninstall rm -f $(libdir)/$(IDA_LIB) + rm -f $(includedir)/ida/ida.h + rm -f $(includedir)/ida/ida_direct.h + rm -f $(includedir)/ida/ida_dense.h + rm -f $(includedir)/ida/ida_band.h + rm -f $(includedir)/ida/ida_lapack.h + rm -f $(includedir)/ida/ida_spbcgs.h + rm -f $(includedir)/ida/ida_spgmr.h + rm -f $(includedir)/ida/ida_sptfqmr.h + rm -f $(includedir)/ida/ida_bbdpre.h + rm -f $(includedir)/ida/ida_spils.h + rm -f $(includedir)/ida/ida_impl.h + $(rminstalldirs) ${includedir}/ida + +shared: + @cd ${top_builddir}/src/sundials ; \ + ${MAKE} ; \ + cd ${abs_builddir} + +clean: + $(LIBTOOL) --mode=clean rm -f $(IDA_LIB) + rm -f $(IDA_LIB_FILES) + rm -f $(IDA_BL_LIB_FILES) + rm -f $(IDA_OBJ_FILES) + rm -f $(IDA_BL_OBJ_FILES) + +distclean: clean + rm -f Makefile + +ida.lo: $(srcdir)/ida.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/ida.c +ida_ic.lo: $(srcdir)/ida_ic.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/ida_ic.c +ida_io.lo: $(srcdir)/ida_io.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/ida_io.c +ida_direct.lo: $(srcdir)/ida_direct.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/ida_direct.c +ida_dense.lo: $(srcdir)/ida_dense.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/ida_dense.c +ida_band.lo: $(srcdir)/ida_band.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/ida_band.c +ida_lapack.lo: $(srcdir)/ida_lapack.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/ida_lapack.c +ida_spils.lo: $(srcdir)/ida_spils.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/ida_spils.c +ida_spbcgs.lo: $(srcdir)/ida_spbcgs.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/ida_spbcgs.c +ida_spgmr.lo: $(srcdir)/ida_spgmr.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/ida_spgmr.c +ida_sptfqmr.lo: $(srcdir)/ida_sptfqmr.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/ida_sptfqmr.c +ida_bbdpre.lo: $(srcdir)/ida_bbdpre.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/ida_bbdpre.c + +libtool: $(top_builddir)/$(LIBTOOL_DEPS) + @cd ${top_builddir} ; \ + ${SHELL} ./config.status --recheck ; \ + cd ${abs_builddir} diff --git a/odemex/Parser/CVode/ida_src/src/ida/README b/odemex/Parser/CVode/ida_src/src/ida/README new file mode 100644 index 0000000..cbe1d4d --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/README @@ -0,0 +1,364 @@ + IDA + Release 2.6.0, January 2008 + Alan C. Hindmarsh and Radu Serban + Center for Applied Scientific Computing, LLNL + + +IDA is a package for the solution of differential-algebraic equation +(DAE) systems. It is written in C, but derived from the package DASPK +[4,5], which is written in FORTRAN. + +IDA can be used both on serial and parallel (MPI) computers. The main +difference is in the NVECTOR module of vector kernels. The desired +version is obtained when compiling the example files by linking the +appropriate library of NVECTOR kernels. In the parallel version, +communication between processors is done with the MPI (Message Passage +Interface) system. + +When used with the serial NVECTOR module, IDA provides both direct +(dense and band) linear solvers and preconditioned Krylov (iterative) +linear solvers. Three different iterative solvers are available: scaled +preconditioned GMRES (SPGMR), scaled preconditioned BiCGStab (SPBCG), and +scaled preconditioned TFQMR (SPTFQMR). When IDA is used with the parallel +NVECTOR module, only the Krylov linear solvers are available. For the +latter case, in addition to the basic solver, the IDA package also contains +a preconditioner module called IDABBDPRE, which provides a band-block-diagonal +preconditioner. + +IDA is part of a software family called SUNDIALS: SUite of Nonlinear and +DIfferential/ALgebraic equation Solvers [3]. This suite consists of CVODE, +CVODES, IDA, IDAS, and KINSOL. The directory structure of the package supplied +reflects this family relationship. + +For use with Fortran applications, a set of Fortran/C interface routines, +called FIDA, is also supplied. These are written in C, but assume that +the user calling program and all user-supplied routines are in Fortran. + +Several examples problem programs are included, covering both serial +and parallel cases, both small and large problem sizes, and both +linear and nonlinear problems. + +The notes below provide the location of documentation, directions for the +installation of the IDA package, and relevant references. Following that +is a brief history of revisions to the package. + + +A. Documentation +---------------- + +/sundials/doc/ida/ contains PDF files for the IDA User Guide [1] (ida_guide.pdf) +and the IDA Examples [2] (ida_examples.pdf) documents. + + +B. Installation +--------------- + +For basic installation instructions see the file /sundials/INSTALL_NOTES. +For complete installation instructions see the "IDA Installation Procedure" +chapter in the IDA User Guide. + + +C. References +------------- + +[1] A. C. Hindmarsh, R. Serban, and A. Collier, "User Documentation for IDA v2.4.0," + LLNL technical report UCRL-SM-208112, November 2004. + +[2] A. C. Hindmarsh, R. Serban, and A. Collier, "Example Programs for IDA v2.4.0," + LLNL technical report UCRL-SM-208113, November 2004. + +[3] A. C. Hindmarsh, P. N. Brown, K. E. Grant, S. L. Lee, R. Serban, + D. E. Shumaker, and C. S. Woodward, "SUNDIALS, Suite of Nonlinear and + Differential/Algebraic Equation Solvers," ACM Trans. Math. Softw., + 31(3), pp. 363-396, 2005. + +[4] P. N. Brown, A. C. Hindmarsh, and L. R. Petzold, Using Krylov Methods + in the Solution of Large-Scale Differential-Algebraic Systems, + SIAM J. Sci. Comp., 15 (1994), pp. 1467-1488. + +[5] P. N. Brown, A. C. Hindmarsh, and L. R. Petzold, Consistent Initial + Condition Calculation for Differential-Algebraic Systems, + SIAM J. Sci. Comp., 19 (1998), pp. 1495-1512. + + +D. Releases +----------- + +v. 2.6.0 - Jan. 2008 +v. 2.5.0 - Nov. 2006 +v. 2.4.0 - Mar. 2006 +v. 2.3.0 - Apr. 2005 +v. 2.2.2 - Mar. 2005 +v. 2.2.1 - Jan. 2005 +v. 2.2.0 - Dec. 2004 +v. 2.0 - Jul. 2002 (first SUNDIALS release) +v. 1.0 - Feb. 1999 (date written) + + +E. Revision History +------------------- + +v. 2.5.0 (Nov. 2006) ---> v. 2.6.0 (Jan. 2008) +--------------------------------------------------------- + +- New features + - added a new linear solver module based on Blas + Lapack for + both dense and banded matrices. + - added optional input to specify which direction of zero-crossing + is to be monitored while performing root-finding. The root information + array iroots (returned by IDAGetRootInfo) also encodes the + direction of zero-crossing. + +- Bug fixes + - in the rootfinding algorithm, fixed a bug resulting in unnecessary + evaluations of the root functions after reinitialization of the + solver right after a return at a root. + +- Changes to user interface + - renamed all **Malloc functions to **Init + - tolerances are now specified through separate functions instead of + the initialization functions IDAInit (former IDAMalloc) and + IDAReInit. Depending on the tolerance type, one of 3 functions + must be called before the first call to IDASolve. + - removed function inputs from argument lists of all re-initialization + functions. + - all user-supplied functions now receive the same pointer to user data + (instead of having different ones for the system evaluation, Jacobian + information functions, etc.) + - removed IDA_NORMAL_TSTOP and IDA_ONE_STEP_TSTOP named constants for the + itask argument to IDASolve. A tstop value is now both set and activated + through IDASetStopTime. Once tstop is reached it is also deactivated. + A new value can be then spcified by calling again IDASetStopTime. + - common functionality for all direct linear solvers (dense, band, and + the new Lapack solver) has been collected into the DLS (Direct Linear + Solver) module, similar to the SPILS module for the iterative linear + solvers. All optional input and output functions for these linear + solver now have the prefix 'IDADls'. In addition, in order to include + the new Lapack-based linear solver, all dimensions for these linear + solvers (problem sizes, bandwidths, etc) are now of type 'int' + (instead of 'long int'). + - the initialization function for the preconditioner module IDABBDPRE + was renamed IDABBDInit (from IDABBDAlloc) and it does not return + a pointer to preconditioner memory anymore. Instead, all preconditioner + module-related functions are now called with the main solver memory + pointer as their first argument. When using the IDABBDPRE module, + there is no need to use special functions to attach one of the SPILS + linear solvers (instead use one of IDASpgmr, IDASpbcg, or IDASptfqmr). + Moreover, there is no need to call a memory deallocation function for + the preconditioner module. + - changes corresponding to the above were made to the FCMIX interface. + +v. 2.4.0 (Mar. 2006) ---> v. 2.5.0 (Oct. 2006) +--------------------------------------------------------- + +- Bug fixes + - fixed wrong logic in final stopping tests: now we check if + tout was reached before checking if tstop was reached. + - added a roundoff factor when testing whether tn was just returned + (in root finding) to prevent an unnecessary return. + - fixed perturbation factor "underflow" issue in IDADenseDQJac and + IDABandDQJac routines which are used to compute a difference quotient + approximation to the system Jacobian (see IDA_P1). + +- Changes related to the build system + - reorganized source tree: header files in ${srcdir}/include/ida, + source files in ${srcdir}/src/ida, fcmix source files in + ${srcdir}/src/ida/fcmix, examples in ${srcdir}/examples/ida + - exported header files are installed unde ${includedir}/ida + +- Changes to user interface + - all included header files use relative paths from ${includedir} + - modified prototype and implementation of IDACalcIC (removed + arguments t0, yy0, yp0). IDACalcIC will always correct the + initial conditions passed through IDAMalloc (or IDAReInit) + which were stored in the Nordsieck history array + - added optional output IDAGetConsistentIC function (which can + only be called before any IDASolve calls) to obtain the corrected + initial conditions. + +v. 2.3.0 (Apr. 2005) ---> v. 2.4.0 (Mar. 2006) +--------------------------------------------------------- + +- New features + - added IDASPBCG interface module to allow IDA to interface with the + shared SPBCG (scaled preconditioned Bi-CGSTAB) linear solver module. + - added IDASPTFQMR interface module to allow IDA to interface with the + shared SPTFQMR (scaled preconditioned TFQMR) linear solver module. + - added support for SPBCG and SPTFQMR to the IDABBDPRE preconditioner module. + - added FIDA (Fortran interface to IDA). + - added rootfinding feature in IDA; modified irobx example problem. + - added support for interpreting failures in user-supplied functions. + +- Changes to user-callable functions + - changed argument of IDAFree and IDABBDPrecFree to be the address + of the respective memory block pointer, so that its NULL value is + propagated back to the calling function. + - added IDASPBCG module which defines appropriate IDSpbcg* functions to + allow IDA to interface with the shared SPBCG linear solver module. + - added IDABBDSpbcg function to IDABBDPRE module to support SPBCG linear + solver module. + - changed function type names (not the actual definition) to accomodate + all the Scaled Preconditioned Iterative Linear Solvers now available: + IDASpgmrJactimesVecFn -> IDASpilsJacTimesVecFn + IDASpgmrPrecSetupFn -> IDASpilsPrecSetupFn + IDASpgmrPrecSolveFn -> IDASpilsPrecSolveFn + - changed some names for IDABBDPRE function outputs + - added option for user-supplied error handler function. + - added IDAGetEstLocalErrors() to return estimated local errors. + - renamed all exported header files (except for ida.h, all header files + have the prefix 'ida_') + - changed naming scheme for IDA examples + +- Changes related to the build system + - the main IDA header file (ida.h) is still exported to the install include + directory. However, all other IDA header files are exported into an 'ida' + subdirectory of the install include directory. + - the IDA library now contains all shared object files (there is no separate + libsundials_shared library anymore) + +v. 2.2.2 (Mar. 2005) ---> v. 2.3.0 (Apr. 2005) +---------------------------------------------- + +- New features + - added option for user-provided error weight computation function + (of type IDAEwtFn specified through IDASetEwtFn). + +- Changes to user interface + - IDA now stores tolerances through values rather than references + (to resolve potential scoping issues). + - IDA now stores the constraints and id vectors (if defined) through + values ratherthan references. + - IDA now passes information back to the user through values rather + than references (error weights) + - IDAMalloc, IDAReInit, IDASetTolerances: added option itol=IDA_WF + to indicate user-supplied function for computing the error weights; + reltol is now declared as realtype. Note that it is now illegal to call + IDASetTolerances before IDAMalloc. It is now legal to deallocate + the absolute tolerance N_Vector right after its use. + - IDAGetErrorWeights: the user is now responsible for allocating space + for the N_Vector in which error weights will be copied. + - IDACalcIC takes as additional arguments (t0,y0,yp0). As a consequence, + it can be called at any time to correct a pair (y,y'). + - Passing a value of 0 for the maximum step size or for maxsteps results + in the solver using the corresponding default value (infinity, and 500, + respectively) + - Several optional input functions were combined into a single one + (IDADenseSetJacFn and IDADenseSetJacData, IDABandSetJacFn and IDABandSetJacData, + IDASpgmrSetPrecSolveFn and IDASpgmrSetPrecSetFn and IDASpgmrSetPrecData, + IDASpgmrSetJacTimesVecFn and IDASpgmrSetJacData). + +v. 2.2.1 (Jan. 2005) ---> v. 2.2.2 (Mar. 2005) +---------------------------------------------- + +- Bug fixes + - changed implicit type conversion to explicit in check_flag() routine in + examples to avoid C++ compiler errors + +- Changes to documentation + - added section with numerical values of all input and output solver constants + - added more detailed notes on the type of absolute tolerances + - fixed several typos and removed reference to inexistent function IDASetMinStep + - added description of --with-mpi-flags option + +- Changes related to the build system + - fixed autoconf-related bug to allow configuration with the PGI Fortran compiler + - modified to use customized detection of the Fortran name mangling scheme + (autoconf's AC_F77_WRAPPERS routine is problematic on some platforms) + - added --with-mpi-flags as a configure option to allow user to specify + MPI-specific flags + - updated Makefiles for Fortran examples to avoid C++ compiler errors (now use + CC and MPICC to link) + + +v. 2.2.0 (Dec. 2004) ---> v. 2.2.1 (Jan. 2005) +---------------------------------------------- + +- Changes related to the build system + - changed order of compiler directives in header files to avoid compilation + errors when using a C++ compiler. + +- Changes to documentation + - fixed various mistakes and typos in the user guide and example program + documents. + +v. 2.0 (Jul. 2002) ---> v. 2.2.0 (Dec. 2004) +-------------------------------------------- + +- New features + - added option to disable all error messages. + +- Bug fixes + - in the solution of the nonlinear system, the correction for small constraint + violation is to ee, not y. + - besides delaying the order increase until the 2nd step, we now also delay + doubling the step size, to avoid using information from times before t0. + +- Changes related to the NVECTOR module + (see also the file sundials/shared/README) + - removed machEnv, redefined table of vector operations (now contained + in the N_Vector structure itself). + - all IDA functions create new N_Vector variables through cloning, using + an N_Vector passed by the user as a template. + +- Changes to type names and IDA constants + - removed type 'integertype'; instead use int or long int, as appropriate. + - restructured the list of return values from the various IDA functions. + - changed all IDA constants (inputs and return values) to have the + prefix 'IDA_' (e.g. IDA_SUCCESS). + - renamed various function types to have the prefix 'IDA' (e.g. IDAResFn). + +- Changes to optional input/ouput + - added IDASet* and IDAGet* functions for optional inputs/outputs, + replacing the arrays iopt and ropt. + - added new optional inputs (e.g. maximum number of Newton iterations, + maximum number of convergence failures, etc). + - added new function IDAGetSolution for dense output. + - the value of the last return flag from any function within a linear + solver module can be obtained as an optional output (e.g. IDADenseGetLastFlag). + +- Changes to user-callable functions + - added new function IDACreate which initializes the IDA solver + object and returns a pointer to the IDA memory block. + - removed N (problem size) from all functions except the initialization + functions for the direct linear solvers (IDADense and IDABand). + - shortened argument lists of most IDA functions (the arguments that + were dropped can now be specified through IDASet* functions). + - removed reinitialization functions for band/dense/SPGMR linear + solvers (same functionality can be obtained using IDA*Set* functions). + - in IDABBDPRE, added a new function, IDABBDSpgmr to initialize the + SPGMR linear solver with the BBD preconditioner. + - function names changed in IDABBDPRE for uniformity. + +- Changes to user-supplied functions + - removed N (probem dimension) from argument lists. + - shortened argument lists for user dense/band/SPGMR Jacobian routines. + - in IDASPGMR, shortened argument lists for user preconditioner functions. + - in IDABBDPRE, added Nlocal, the local vector size, as an argument to + IDABBDLocalFn and IDABBDCommFn. + +v. 1.0 (Feb. 1999) ---> v. 2.0 (Jul. 2002) +------------------------------------------ + +YYYYMMDD + +19990212 DATE WRITTEN; initial internal release (incomplete). +19990514 IDABBDPRE preconditioner module added. +19990720 Initial condition calculation routines (IDACalcIC) added. +19991208 In IDABBDPRE, user routine argument lists changed. +19991217 Generic SPGMR module revised to correct scalings. +20000316 In parallel NVECTOR, comm arg. to PVecInitMPI is non-NULL. +20000808 Fixed bug in N_VMin. In IDACalcIC: added calculation of system + index in CALC_YA_YDP_INIT case, added scaling of fnorm when index = 0. +20010110 Fixed two bugs in IDACalcIC and subordinate routines: + (1) Set hh in IDACalcIC independent of icopt, for lsetup. + (2) Set ypnew = yp0 in IDALineSrch in CALC_Y_INIT case. + Corrected #define ncfl0 line in idaspgmr.c. +20011015 Fixed bug in IDAInterp (tn test). + Fixed minor bugs in error messages (missing arguments etc.) +20011220 Default type 'integer' changed to 'long int' in llnltyps.h. +20020313 Modified to work with new NVECTOR abstraction. +20020626 Renamed types real, integer, boole as realtype, integertype, + and booleantype, and renamed related constants. Renamed files + llnlmath.*, llnltypes.h as sundialsmath.*, sundialstypes.h. +20020703 Added reinitialization routines for IDA, for each linear + solver module, and for IDABBDPRE. diff --git a/odemex/Parser/CVode/ida_src/src/ida/fcmix/CMakeLists.txt b/odemex/Parser/CVode/ida_src/src/ida/fcmix/CMakeLists.txt new file mode 100644 index 0000000..d1a4ae5 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/fcmix/CMakeLists.txt @@ -0,0 +1,43 @@ +# CMakeLists.txt file for the FIDA library + +# Add variable fida_SOURCES with the sources for the FIDA library +SET(fida_SOURCES + fidaband.c + fidabbd.c + fida.c + fidadense.c + fidaewt.c + fidajtimes.c + fidapreco.c + fidaroot.c + ) + +IF(LAPACK_FOUND) + SET(fida_BL_SOURCES fidalapack.c fidalapdense.c fidalapband.c) +ELSE(LAPACK_FOUND) + SET(fida_BL_SOURCES "") +ENDIF(LAPACK_FOUND) + +# Add source directories to include directories for access to +# implementation only header files (both for fida and ida) +INCLUDE_DIRECTORIES(.) +INCLUDE_DIRECTORIES(..) + +# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY +ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY) + +# Only build STATIC libraries (we cannot build shared libraries +# for the FCMIX interfaces due to unresolved symbol errors +# coming from inexistent user-provided functions) + +# Add the build target for the FIDA library +ADD_LIBRARY(sundials_fida_static STATIC ${fida_SOURCES} ${fida_BL_SOURCES}) + +# Set the library name and make sure it is not deleted +SET_TARGET_PROPERTIES(sundials_fida_static + PROPERTIES OUTPUT_NAME sundials_fida CLEAN_DIRECT_OUTPUT 1) + +# Install the FIDA library +INSTALL(TARGETS sundials_fida_static DESTINATION lib) +# +MESSAGE(STATUS "Added IDA FCMIX module") diff --git a/odemex/Parser/CVode/ida_src/src/ida/fcmix/Makefile.in b/odemex/Parser/CVode/ida_src/src/ida/fcmix/Makefile.in new file mode 100644 index 0000000..58a5e8d --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/fcmix/Makefile.in @@ -0,0 +1,123 @@ +# ----------------------------------------------------------------- +# $Revision: 1.8 $ +# $Date: 2009/03/25 23:10:50 $ +# ----------------------------------------------------------------- +# Programmer(s): Aaron Collier @ LLNL +# ----------------------------------------------------------------- +# Copyright (c) 2005, The Regents of the University of California. +# Produced at the Lawrence Livermore National Laboratory. +# All rights reserved. +# For details, see the LICENSE file. +# ----------------------------------------------------------------- +# Makefile for FIDA module +# +# @configure_input@ +# ----------------------------------------------------------------- + +SHELL = @SHELL@ + +srcdir = @srcdir@ +builddir = @builddir@ +abs_builddir = @abs_builddir@ +top_builddir = @top_builddir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +includedir = @includedir@ +libdir = @libdir@ + +INSTALL = @INSTALL@ +INSTALL_LIB = @INSTALL_PROGRAM@ +INSTALL_HEADER = @INSTALL_DATA@ + +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ + +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CC = @CC@ +CFLAGS = @CFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ + +LAPACK_ENABLED = @LAPACK_ENABLED@ + +top_srcdir = $(srcdir)/../../.. + +INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/src/ida -I$(top_builddir)/include + +LIB_REVISION = 1:0:0 + +FIDA_LIB = libsundials_fida.la + +FIDA_SRC_FILES = fida.c fidaband.c fidadense.c fidajtimes.c fidapreco.c fidaewt.c fidaroot.c fidabbd.c +FIDA_BL_SRC_FILES = fidalapack.c fidalapdense.c fidalapband.c + +FIDA_OBJ_FILES = $(FIDA_SRC_FILES:.c=.o) +FIDA_BL_OBJ_FILES = $(FIDA_BL_SRC_FILES:.c=.o) + +FIDA_LIB_FILES = $(FIDA_SRC_FILES:.c=.lo) +FIDA_BL_LIB_FILES = $(FIDA_BL_SRC_FILES:.c=.lo) + +mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs + +# ---------------------------------------------------------------------------------------------------------------------- + +all: $(FIDA_LIB) + +$(FIDA_LIB): $(FIDA_LIB_FILES) + @if test "X${LAPACK_ENABLED}" = "Xyes"; then \ + make lib_with_bl; \ + else \ + make lib_without_bl; \ + fi + +lib_without_bl: $(FIDA_LIB_FILES) + $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(FIDA_LIB) $(FIDA_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -static -version-info $(LIB_REVISION) + +lib_with_bl: $(FIDA_LIB_FILES) $(FIDA_BL_LIB_FILES) + $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(FIDA_LIB) $(FIDA_LIB_FILES) $(FIDA_BL_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -static -version-info $(LIB_REVISION) + +install: $(FIDA_LIB) + $(mkinstalldirs) $(libdir) + $(LIBTOOL) --mode=install $(INSTALL_LIB) $(FIDA_LIB) $(libdir) + +uninstall: + $(LIBTOOL) --mode=uninstall rm -f $(libdir)/$(FIDA_LIB) + +clean: + $(LIBTOOL) --mode=clean rm -f $(FIDA_LIB) + rm -f $(FIDA_LIB_FILES) + rm -f $(FIDA_BL_LIB_FILES) + rm -f $(FIDA_OBJ_FILES) + rm -f $(FIDA_BL_OBJ_FILES) + +distclean: clean + rm -f Makefile + +fida.lo: $(srcdir)/fida.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fida.c +fidaewt.lo: $(srcdir)/fidaewt.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fidaewt.c +fidaband.lo: $(srcdir)/fidaband.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fidaband.c +fidadense.lo: $(srcdir)/fidadense.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fidadense.c +fidalapack.lo: $(srcdir)/fidalapack.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fidalapack.c +fidalapband.lo: $(srcdir)/fidalapband.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fidalapband.c +fidalapdense.lo: $(srcdir)/fidalapdense.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fidalapdense.c +fidajtimes.lo: $(srcdir)/fidajtimes.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fidajtimes.c +fidapreco.lo: $(srcdir)/fidapreco.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fidapreco.c +fidabbd.lo: $(srcdir)/fidabbd.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fidabbd.c +fidaroot.lo: $(srcdir)/fidaroot.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fidaroot.c + +libtool: $(top_builddir)/$(LIBTOOL_DEPS) + @cd ${top_builddir} ; \ + ${SHELL} ./config.status --recheck ; \ + cd ${abs_builddir} diff --git a/odemex/Parser/CVode/ida_src/src/ida/fcmix/fida.c b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fida.c new file mode 100644 index 0000000..6ba06e6 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fida.c @@ -0,0 +1,751 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.9 $ + * $Date: 2008/03/18 14:49:29 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the Fortran interface to + * the IDA package. See fida.h for usage. + * NOTE: Some routines are necessarily stored elsewhere to avoid + * linking problems. + * ----------------------------------------------------------------- + */ + +#include +#include +#include + +#include "fida.h" /* function names, prototypes, global variables */ +#include "ida_impl.h" /* definition of IDAMem type */ + +#include /* prototypes for IDABAND interface routines */ +#include /* prototypes for IDADENSE interface routines */ +#include /* prototypes for IDASPTFQMR interface routines */ +#include /* prototypes for IDASPBCG interface routines */ +#include /* prototypes for IDASPGMR interface routines */ + +/*************************************************/ + +/* Definitions for global variables shared amongst various routines */ + +N_Vector F2C_IDA_ypvec, F2C_IDA_ewtvec; + +void *IDA_idamem; +long int *IDA_iout; +realtype *IDA_rout; +int IDA_ls; +int IDA_nrtfn; + +/*************************************************/ + +/* private constant(s) */ +#define ZERO RCONST(0.0) + +/*************************************************/ + +/* Prototype of user-supplied Fortran routine (IDAResFn) */ + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + + extern void FIDA_RESFUN(realtype*, /* T */ + realtype*, /* Y */ + realtype*, /* YP */ + realtype*, /* R */ + long int*, /* IPAR */ + realtype*, /* RPAR */ + int*); /* IER */ + +#ifdef __cplusplus +} +#endif + +/*************************************************/ + +void FIDA_MALLOC(realtype *t0, realtype *yy0, realtype *yp0, + int *iatol, realtype *rtol, realtype *atol, + long int *iout, realtype *rout, + long int *ipar, realtype *rpar, + int *ier) +{ + N_Vector Vatol; + FIDAUserData IDA_userdata; + + *ier = 0; + + /* Check for required vector operations */ + if ((F2C_IDA_vec->ops->nvgetarraypointer == NULL) || + (F2C_IDA_vec->ops->nvsetarraypointer == NULL)) { + *ier = -1; + printf("A required vector operation is not implemented.\n\n"); + return; + } + + /* Initialize all pointers to NULL */ + IDA_idamem = NULL; + Vatol = NULL; + F2C_IDA_ypvec = F2C_IDA_ewtvec = NULL; + + /* Create IDA object */ + IDA_idamem = IDACreate(); + if (IDA_idamem == NULL) { + *ier = -1; + return; + } + + /* Set and attach user data */ + IDA_userdata = NULL; + IDA_userdata = (FIDAUserData) malloc(sizeof *IDA_userdata); + if (IDA_userdata == NULL) { + *ier = -1; + return; + } + IDA_userdata->rpar = rpar; + IDA_userdata->ipar = ipar; + + *ier = IDASetUserData(IDA_idamem, IDA_userdata); + if(*ier != IDA_SUCCESS) { + free(IDA_userdata); IDA_userdata = NULL; + *ier = -1; + return; + } + + /* Attach user's yy0 to F2C_IDA_vec */ + N_VSetArrayPointer(yy0, F2C_IDA_vec); + + /* Create F2C_IDA_ypvec and attach user's yp0 to it */ + F2C_IDA_ypvec = NULL; + F2C_IDA_ypvec = N_VCloneEmpty(F2C_IDA_vec); + if (F2C_IDA_ypvec == NULL) { + free(IDA_userdata); IDA_userdata = NULL; + *ier = -1; + } + N_VSetArrayPointer(yp0, F2C_IDA_ypvec); + + /* Call IDAInit */ + *ier = IDAInit(IDA_idamem, FIDAresfn, *t0, F2C_IDA_vec, F2C_IDA_ypvec); + + /* Reset data pointers */ + N_VSetArrayPointer(NULL, F2C_IDA_vec); + N_VSetArrayPointer(NULL, F2C_IDA_ypvec); + + /* On failure, clean-up and exit */ + if (*ier != IDA_SUCCESS) { + N_VDestroy(F2C_IDA_ypvec); + free(IDA_userdata); IDA_userdata = NULL; + *ier = -1; + return; + } + + /* Set tolerances */ + switch (*iatol) { + case 1: + *ier = IDASStolerances(IDA_idamem, *rtol, *atol); + break; + case 2: + Vatol = NULL; + Vatol= N_VCloneEmpty(F2C_IDA_vec); + if (Vatol == NULL) { + free(IDA_userdata); IDA_userdata = NULL; + *ier = -1; + return; + } + N_VSetArrayPointer(atol, Vatol); + *ier = IDASVtolerances(IDA_idamem, *rtol, Vatol); + N_VDestroy(Vatol); + break; + } + + /* On failure, clean-up and exit */ + if (*ier != IDA_SUCCESS) { + free(IDA_userdata); IDA_userdata = NULL; + *ier = -1; + return; + } + + /* Grab optional output arrays and store them in global variables */ + IDA_iout = iout; + IDA_rout = rout; + + /* Store the unit roundoff in rout for user access */ + IDA_rout[5] = UNIT_ROUNDOFF; + + /* Set F2C_IDA_ewtvec on NULL */ + F2C_IDA_ewtvec = NULL; + + return; +} + +/*************************************************/ + +void FIDA_REINIT(realtype *t0, realtype *yy0, realtype *yp0, + int *iatol, realtype *rtol, realtype *atol, + int *ier) +{ + N_Vector Vatol; + + *ier = 0; + + /* Initialize all pointers to NULL */ + Vatol = NULL; + + /* Attach user's yy0 to F2C_IDA_vec */ + N_VSetArrayPointer(yy0, F2C_IDA_vec); + + /* Attach user's yp0 to F2C_IDA_ypvec */ + N_VSetArrayPointer(yp0, F2C_IDA_ypvec); + + /* Call IDAReInit */ + *ier = IDAReInit(IDA_idamem, *t0, F2C_IDA_vec, F2C_IDA_ypvec); + + /* Reset data pointers */ + N_VSetArrayPointer(NULL, F2C_IDA_vec); + N_VSetArrayPointer(NULL, F2C_IDA_ypvec); + + /* On failure, exit */ + if (*ier != IDA_SUCCESS) { + *ier = -1; + return; + } + + /* Set tolerances */ + switch (*iatol) { + case 1: + *ier = IDASStolerances(IDA_idamem, *rtol, *atol); + break; + case 2: + Vatol = NULL; + Vatol= N_VCloneEmpty(F2C_IDA_vec); + if (Vatol == NULL) { + *ier = -1; + return; + } + N_VSetArrayPointer(atol, Vatol); + *ier = IDASVtolerances(IDA_idamem, *rtol, Vatol); + N_VDestroy(Vatol); + break; + } + + /* On failure, exit */ + if (*ier != IDA_SUCCESS) { + *ier = -1; + return; + } + + return; +} + +/*************************************************/ + +void FIDA_SETIIN(char key_name[], long int *ival, int *ier, int key_len) +{ + if (!strncmp(key_name,"MAX_ORD", (size_t)key_len)) + *ier = IDASetMaxOrd(IDA_idamem, (int) *ival); + else if (!strncmp(key_name,"MAX_NSTEPS", (size_t)key_len)) + *ier = IDASetMaxNumSteps(IDA_idamem, (int) *ival); + else if (!strncmp(key_name,"MAX_ERRFAIL", (size_t)key_len)) + *ier = IDASetMaxErrTestFails(IDA_idamem, (int) *ival); + else if (!strncmp(key_name,"MAX_NITERS", (size_t)key_len)) + *ier = IDASetMaxNonlinIters(IDA_idamem, (int) *ival); + else if (!strncmp(key_name,"MAX_CONVFAIL", (size_t)key_len)) + *ier = IDASetMaxConvFails(IDA_idamem, (int) *ival); + else if (!strncmp(key_name,"SUPPRESS_ALG", (size_t)key_len)) + *ier = IDASetSuppressAlg(IDA_idamem, (int) *ival); + else if (!strncmp(key_name,"MAX_NSTEPS_IC", (size_t)key_len)) + *ier = IDASetMaxNumStepsIC(IDA_idamem, (int) *ival); + else if (!strncmp(key_name,"MAX_NITERS_IC", (size_t)key_len)) + *ier = IDASetMaxNumItersIC(IDA_idamem, (int) *ival); + else if (!strncmp(key_name,"MAX_NJE_IC", (size_t)key_len)) + *ier = IDASetMaxNumJacsIC(IDA_idamem, (int) *ival); + else if (!strncmp(key_name,"LS_OFF_IC", (size_t)key_len)) + *ier = IDASetLineSearchOffIC(IDA_idamem, (int) *ival); + else { + *ier = -99; + printf("FIDASETIIN: Unrecognized key.\n\n"); + } + +} + +/***************************************************************************/ + +void FIDA_SETRIN(char key_name[], realtype *rval, int *ier, int key_len) +{ + + if (!strncmp(key_name,"INIT_STEP", (size_t)key_len)) + *ier = IDASetInitStep(IDA_idamem, *rval); + else if (!strncmp(key_name,"MAX_STEP", (size_t)key_len)) + *ier = IDASetMaxStep(IDA_idamem, *rval); + else if (!strncmp(key_name,"STOP_TIME", (size_t)key_len)) + *ier = IDASetStopTime(IDA_idamem, *rval); + else if (!strncmp(key_name,"NLCONV_COEF", (size_t)key_len)) + *ier = IDASetNonlinConvCoef(IDA_idamem, *rval); + else if (!strncmp(key_name,"NLCONV_COEF_IC", (size_t)key_len)) + *ier = IDASetNonlinConvCoefIC(IDA_idamem, *rval); + else if (!strncmp(key_name,"STEP_TOL_IC", (size_t)key_len)) + *ier = IDASetStepToleranceIC(IDA_idamem, *rval); + else { + *ier = -99; + printf("FIDASETRIN: Unrecognized key.\n\n"); + } + +} + +/*************************************************/ + +void FIDA_SETVIN(char key_name[], realtype *vval, int *ier, int key_len) +{ + N_Vector Vec; + + *ier = 0; + + if (!strncmp(key_name,"ID_VEC", (size_t)key_len)) { + Vec = NULL; + Vec = N_VCloneEmpty(F2C_IDA_vec); + if (Vec == NULL) { + *ier = -1; + return; + } + N_VSetArrayPointer(vval, Vec); + IDASetId(IDA_idamem, Vec); + N_VDestroy(Vec); + } else if (!strncmp(key_name,"CONSTR_VEC", (size_t)key_len)) { + Vec = NULL; + Vec = N_VCloneEmpty(F2C_IDA_vec); + if (Vec == NULL) { + *ier = -1; + return; + } + N_VSetArrayPointer(vval, Vec); + IDASetConstraints(IDA_idamem, Vec); + N_VDestroy(Vec); + } else { + *ier = -99; + printf("FIDASETVIN: Unrecognized key.\n\n"); + } + +} + +/*************************************************/ + +void FIDA_TOLREINIT(int *iatol, realtype *rtol, realtype *atol, int *ier) +{ + int itol; + N_Vector Vatol=NULL; + + *ier = 0; + + itol = -1; + if (*iatol == 1) { + *ier = IDASStolerances(IDA_idamem, *rtol, *atol); + } else { + Vatol = NULL; + Vatol = N_VCloneEmpty(F2C_IDA_vec); + if (Vatol == NULL) { + *ier = -1; + return; + } + N_VSetArrayPointer(atol, Vatol); + *ier = IDASVtolerances(IDA_idamem, *rtol, Vatol); + N_VDestroy(Vatol); + } + + return; +} + +/*************************************************/ + +void FIDA_CALCIC(int *icopt, realtype *tout1, int *ier) +{ + *ier = 0; + *ier = IDACalcIC(IDA_idamem, *icopt, *tout1); + return; +} + +/*************************************************/ + +void FIDA_SPTFQMR(int *maxl, realtype *eplifac, realtype *dqincfac, int *ier) +{ + + *ier = 0; + + *ier = IDASptfqmr(IDA_idamem, *maxl); + if (*ier != IDASPILS_SUCCESS) return; + + if (*eplifac != ZERO) { + *ier = IDASpilsSetEpsLin(IDA_idamem, *eplifac); + if (*ier != IDASPILS_SUCCESS) return; + } + + if (*dqincfac != ZERO) { + *ier = IDASpilsSetIncrementFactor(IDA_idamem, *dqincfac); + if (*ier != IDASPILS_SUCCESS) return; + } + + IDA_ls = IDA_LS_SPTFQMR; + + return; +} + +/*************************************************/ + +void FIDA_SPBCG(int *maxl, realtype *eplifac, realtype *dqincfac, int *ier) +{ + + *ier = 0; + + *ier = IDASpbcg(IDA_idamem, *maxl); + if (*ier != IDASPILS_SUCCESS) return; + + if (*eplifac != ZERO) { + *ier = IDASpilsSetEpsLin(IDA_idamem, *eplifac); + if (*ier != IDASPILS_SUCCESS) return; + } + + if (*dqincfac != ZERO) { + *ier = IDASpilsSetIncrementFactor(IDA_idamem, *dqincfac); + if (*ier != IDASPILS_SUCCESS) return; + } + + IDA_ls = IDA_LS_SPBCG; + + return; +} + +/*************************************************/ + +void FIDA_SPGMR(int *maxl, int *gstype, int *maxrs, + realtype *eplifac, realtype *dqincfac, int *ier) +{ + + *ier = 0; + + *ier = IDASpgmr(IDA_idamem, *maxl); + if (*ier != IDASPILS_SUCCESS) return; + + if (*gstype != 0) { + *ier = IDASpilsSetGSType(IDA_idamem, *gstype); + if (*ier != IDASPILS_SUCCESS) return; + } + + if (*maxrs != 0) { + *ier = IDASpilsSetMaxRestarts(IDA_idamem, *maxrs); + if (*ier != IDASPILS_SUCCESS) return; + } + + if (*eplifac != ZERO) { + *ier = IDASpilsSetEpsLin(IDA_idamem, *eplifac); + if (*ier != IDASPILS_SUCCESS) return; + } + + if (*dqincfac != ZERO) { + *ier = IDASpilsSetIncrementFactor(IDA_idamem, *dqincfac); + if (*ier != IDASPILS_SUCCESS) return; + } + + IDA_ls = IDA_LS_SPGMR; + + return; +} + +/*************************************************/ + +void FIDA_DENSE(int *neq, int *ier) +{ + + *ier = 0; + + *ier = IDADense(IDA_idamem, *neq); + + IDA_ls = IDA_LS_DENSE; + + return; +} + +/*************************************************/ + +void FIDA_BAND(int *neq, int *mupper, int *mlower, int *ier) +{ + + *ier = 0; + + *ier = IDABand(IDA_idamem, *neq, *mupper, *mlower); + + IDA_ls = IDA_LS_BAND; + + return; +} + +/*************************************************/ + +void FIDA_SPTFQMRREINIT(int *maxl, realtype *eplifac, realtype *dqincfac, int *ier) +{ + + *ier = 0; + + if (*maxl > 0) { + *ier = IDASpilsSetMaxl(IDA_idamem, *maxl); + if (*ier != IDASPILS_SUCCESS) return; + } + + if (*eplifac != ZERO) { + *ier = IDASpilsSetEpsLin(IDA_idamem, *eplifac); + if (*ier != IDASPILS_SUCCESS) return; + } + + if (*dqincfac != ZERO) { + *ier = IDASpilsSetIncrementFactor(IDA_idamem, *dqincfac); + if (*ier != IDASPILS_SUCCESS) return; + } + + IDA_ls = IDA_LS_SPTFQMR; + + return; +} + +/*************************************************/ + +void FIDA_SPBCGREINIT(int *maxl, realtype *eplifac, realtype *dqincfac, int *ier) +{ + + *ier = 0; + + if (*maxl > 0) { + *ier = IDASpilsSetMaxl(IDA_idamem, *maxl); + if (*ier != IDASPILS_SUCCESS) return; + } + + if (*eplifac != ZERO) { + *ier = IDASpilsSetEpsLin(IDA_idamem, *eplifac); + if (*ier != IDASPILS_SUCCESS) return; + } + + if (*dqincfac != ZERO) { + *ier = IDASpilsSetIncrementFactor(IDA_idamem, *dqincfac); + if (*ier != IDASPILS_SUCCESS) return; + } + + IDA_ls = IDA_LS_SPBCG; + + return; +} + +/*************************************************/ + +void FIDA_SPGMRREINIT(int *gstype, int *maxrs, realtype *eplifac, + realtype *dqincfac, int *ier) +{ + + *ier = 0; + + if (*gstype != 0) { + *ier = IDASpilsSetGSType(IDA_idamem, *gstype); + if (*ier != IDASPILS_SUCCESS) return; + } + + if (*maxrs != 0) { + *ier = IDASpilsSetMaxRestarts(IDA_idamem, *maxrs); + if (*ier != IDASPILS_SUCCESS) return; + } + + if (*eplifac != ZERO) { + *ier = IDASpilsSetEpsLin(IDA_idamem, *eplifac); + if (*ier != IDASPILS_SUCCESS) return; + } + + if (*dqincfac != ZERO) { + *ier = IDASpilsSetIncrementFactor(IDA_idamem, *dqincfac); + if (*ier != IDASPILS_SUCCESS) return; + } + + IDA_ls = IDA_LS_SPGMR; + + return; +} + +/*************************************************/ + +void FIDA_SOLVE(realtype *tout, realtype *tret, realtype *yret, + realtype *ypret, int *itask, int *ier) +{ + + *ier = 0; + + /* Attach user data to vectors */ + N_VSetArrayPointer(yret, F2C_IDA_vec); + N_VSetArrayPointer(ypret, F2C_IDA_ypvec); + + *ier = IDASolve(IDA_idamem, *tout, tret, F2C_IDA_vec, F2C_IDA_ypvec, *itask); + + /* Reset data pointers */ + N_VSetArrayPointer(NULL, F2C_IDA_vec); + N_VSetArrayPointer(NULL, F2C_IDA_ypvec); + + /* Set optional outputs */ + + IDAGetWorkSpace(IDA_idamem, + &IDA_iout[0], /* LENRW */ + &IDA_iout[1]); /* LENIW */ + + IDAGetIntegratorStats(IDA_idamem, + &IDA_iout[2], /* NST */ + &IDA_iout[3], /* NRE */ + &IDA_iout[7], /* NSETUPS */ + &IDA_iout[4], /* NETF */ + (int *) &IDA_iout[8], /* KLAST */ + (int *) &IDA_iout[9], /* KCUR */ + &IDA_rout[0], /* HINUSED */ + &IDA_rout[1], /* HLAST */ + &IDA_rout[2], /* HCUR */ + &IDA_rout[3]); /* TCUR */ + IDAGetNonlinSolvStats(IDA_idamem, + &IDA_iout[6], /* NNI */ + &IDA_iout[5]); /* NCFN */ + IDAGetNumBacktrackOps(IDA_idamem, + &IDA_iout[10]); /* NBCKTRK */ + IDAGetTolScaleFactor(IDA_idamem, + &IDA_rout[4]); /* TOLSFAC */ + + /* Root finding is on */ + if (IDA_nrtfn != 0) + IDAGetNumGEvals(IDA_idamem, &IDA_iout[11]); /* NGE */ + + switch(IDA_ls) { + case IDA_LS_DENSE: + case IDA_LS_BAND: + case IDA_LS_LAPACKDENSE: + case IDA_LS_LAPACKBAND: + IDADlsGetWorkSpace(IDA_idamem, &IDA_iout[12], &IDA_iout[13]); /* LENRWLS, LENIWLS */ + IDADlsGetLastFlag(IDA_idamem, (int *) &IDA_iout[14]); /* LSTF */ + IDADlsGetNumResEvals(IDA_idamem, &IDA_iout[15]); /* NRE */ + IDADlsGetNumJacEvals(IDA_idamem, &IDA_iout[16]); /* NJE */ + break; + case IDA_LS_SPGMR: + case IDA_LS_SPBCG: + case IDA_LS_SPTFQMR: + IDASpilsGetWorkSpace(IDA_idamem, &IDA_iout[12], &IDA_iout[13]); /* LENRWLS, LENIWLS */ + IDASpilsGetLastFlag(IDA_idamem, (int *) &IDA_iout[14]); /* LSTF */ + IDASpilsGetNumResEvals(IDA_idamem, &IDA_iout[15]); /* NRE */ + IDASpilsGetNumJtimesEvals(IDA_idamem, &IDA_iout[16]); /* NJE */ + IDASpilsGetNumPrecEvals(IDA_idamem, &IDA_iout[17]); /* NPE */ + IDASpilsGetNumPrecSolves(IDA_idamem, &IDA_iout[18]); /* NPS */ + IDASpilsGetNumLinIters(IDA_idamem, &IDA_iout[19]); /* NLI */ + IDASpilsGetNumConvFails(IDA_idamem, &IDA_iout[20]); /* NCFL */ + break; + } + + + return; +} + +/*************************************************/ + +void FIDA_GETSOL(realtype *t, realtype *yret, realtype *ypret, int *ier) +{ + /* Attach user data to vectors */ + N_VSetArrayPointer(yret, F2C_IDA_vec); + N_VSetArrayPointer(ypret, F2C_IDA_ypvec); + + *ier = 0; + *ier = IDAGetSolution(IDA_idamem, *t, F2C_IDA_vec, F2C_IDA_ypvec); + + /* Reset data pointers */ + N_VSetArrayPointer(NULL, F2C_IDA_vec); + N_VSetArrayPointer(NULL, F2C_IDA_ypvec); + + return; +} + +/*************************************************/ + +void FIDA_GETERRWEIGHTS(realtype *eweight, int *ier) +{ + /* Attach user data to vector */ + N_VSetArrayPointer(eweight, F2C_IDA_vec); + + *ier = 0; + *ier = IDAGetErrWeights(IDA_idamem, F2C_IDA_vec); + + /* Reset data pointer */ + N_VSetArrayPointer(NULL, F2C_IDA_vec); + + return; +} + +/*************************************************/ + +void FIDA_GETESTLOCALERR(realtype *ele, int *ier) +{ + /* Attach user data to vector */ + N_VSetArrayPointer(ele, F2C_IDA_vec); + + *ier = 0; + *ier = IDAGetEstLocalErrors(IDA_idamem, F2C_IDA_vec); + + /* Reset data pointers */ + N_VSetArrayPointer(NULL, F2C_IDA_vec); + + return; +} + +/*************************************************/ + +void FIDA_FREE(void) +{ + IDAMem ida_mem; + + ida_mem = (IDAMem) IDA_idamem; + + free(ida_mem->ida_user_data); ida_mem->ida_user_data = NULL; + + IDAFree(&IDA_idamem); + + /* Free F2C_IDA_vec */ + N_VSetArrayPointer(NULL, F2C_IDA_vec); + N_VDestroy(F2C_IDA_vec); + + /* Free F2C_IDA_ypvec */ + N_VSetArrayPointer(NULL, F2C_IDA_ypvec); + N_VDestroy(F2C_IDA_ypvec); + + /* Free F2C_IDA_ewtvec */ + if (F2C_IDA_ewtvec != NULL) + N_VDestroy(F2C_IDA_ewtvec); + + return; +} + +/*************************************************/ + +int FIDAresfn(realtype t, N_Vector yy, N_Vector yp, + N_Vector rr, void *user_data) +{ + int ier; + realtype *yy_data, *yp_data, *rr_data; + FIDAUserData IDA_userdata; + + /* NOTE: The user-supplied routine should set ier to an + appropriate value, but we preset the value to zero + (meaning SUCCESS) so the user need only reset the + value if an error occurred */ + ier = 0; + + /* Get pointers to vector data */ + yy_data = N_VGetArrayPointer(yy); + yp_data = N_VGetArrayPointer(yp); + rr_data = N_VGetArrayPointer(rr); + + IDA_userdata = (FIDAUserData) user_data; + + /* Call user-supplied routine */ + FIDA_RESFUN(&t, yy_data, yp_data, rr_data, + IDA_userdata->ipar, IDA_userdata->rpar, &ier); + + return(ier); +} diff --git a/odemex/Parser/CVode/ida_src/src/ida/fcmix/fida.h b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fida.h new file mode 100644 index 0000000..79bc372 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fida.h @@ -0,0 +1,716 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.8 $ + * $Date: 2007/12/12 18:13:22 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for FIDA, the Fortran interface to + * the IDA package. + * ----------------------------------------------------------------- + */ + +/* + * ============================================================================= + * + * FIDA Interface Package + * + * The FIDA Interface Package is a package of C functions which support + * the use of the IDA solver, for the solution of DAE systems, in a + * mixed Fortran/C setting. While IDA is written in C, it is assumed + * here that the user's calling program and user-supplied problem-defining + * routines are written in Fortran. This package provides the necessary + * interface to IDA for both the serial and the parallel NVECTOR + * implementations. + * + * The user-callable functions, with the corresponding IDA functions, + * are as follows: + * + * FNVINITS* and FNVINITP* interface to N_VNew_Serial and + * N_VNew_Parallel, respectively + * + * FIDAMALLOC interfaces to IDACreate and IDAInit + * + * FIDAREINIT interfaces to IDAReInit + * + * FIDASETIIN, FIDASETRIN, FIDASETVIN interface to IDASet* + * + * FIDATOLREINIT interfaces to IDASetTolerances + * + * FIDACALCIC interfaces to IDACalcIC + * + * FIDAEWTSET interfaces to IDAWFtolerances + * + * FIDADENSE interfaces to IDADense + * FIDADENSESETJAC interfaces to IDADenseSetJacFn + * + * FIDABAND interfaces to IDABand + * FIDABANDSETJAC interfaces to IDABandSetJacFn + * + * FIDASPTFQMR/FIDASPTFQMRREINIT interface to IDASptfqmr and IDASptfqmrSet* + * FIDASPBCG/FIDASPBCGREINIT interface to IDASpbcg and IDASpbcgSet* + * FIDASPGMR/FIDASPGMRREINIT interface to IDASpgmr and IDASpgmrSet* + * FIDASPILSSETJAC interfaces to IDASpilsSetJacFn + * FIDASPILSSETPREC interfaces to IDASpilsSetPreconditioner + * + * FIDASOLVE interfaces to IDASolve, IDAGet*, and IDA*Get* + * + * FIDAGETSOL interfaces to IDAGetSolution + * + * FIDAGETERRWEIGHTS interfaces to IDAGetErrWeights + * + * FIDAGETESTLOCALERR interfaces to IDAGetEstLocalErrors + * + * FIDAFREE interfaces to IDAFree + * + * The user-supplied functions, each listed with the corresponding interface + * function which calls it (and its type within IDA), are as follows: + * FIDARESFUN is called by the interface function FIDAresfn of type IDAResFn + * FIDADJAC is called by the interface fn. FIDADenseJac of type IDADenseJacFn + * FIDABJAC is called by the interface fn. FIDABandJac of type IDABandJacFn + * FIDAPSOL is called by the interface fn. FIDAPSol of type IDASpilsPrecSolveFn + * FIDAPSET is called by the interface fn. FIDAPSet of type IDASpilsPrecSetupFn + * FIDAJTIMES is called by interface fn. FIDAJtimes of type IDASpilsJacTimesVecFn + * FIDAEWT is called by interface fn. FIDAEwtSet of type IDAEwtFn + * In contrast to the case of direct use of IDA, the names of all user-supplied + * routines here are fixed, in order to maximize portability for the resulting + * mixed-language program. + * + * Important note on portability: + * In this package, the names of the interface functions, and the names of + * the Fortran user routines called by them, appear as dummy names + * which are mapped to actual values by a series of definitions in the + * header file fida.h. + * + * ============================================================================= + * + * Usage of the FIDA Interface Package + * + * The usage of FIDA requires calls to a few different interface + * functions, depending on the method options selected, and one or more + * user-supplied routines which define the problem to be solved. These + * function calls and user routines are summarized separately below. + * + * Some details are omitted, and the user is referred to the user documents + * on IDA for more complete documentation. Information on the + * arguments of any given user-callable interface routine, or of a given + * user-supplied function called by an interface function, can be found in + * the documentation on the corresponding function in the IDA package. + * + * The number labels on the instructions below end with s for instructions + * that apply to the serial version of IDA only, and end with p for + * those that apply to the parallel version only. + * + * ----------------------------------------------------------------------------- + * + * (1) User-supplied residual routine: FIDARESFUN + * The user must in all cases supply the following Fortran routine + * SUBROUTINE FIDARESFUN(T, Y, YP, R, IPAR, RPAR, IER) + * DIMENSION Y(*), YP(*), R(*), IPAR(*), RPAR(*) + * It must set the R array to F(t,y,y'), the residual of the DAE + * system, as a function of T = t, the array Y = y, and the array YP = y'. + * Here Y, YP and R are distributed vectors. + * IPAR and RPAR are arrays of integer and real user data, respectively, + * as passed to FIDAMALLOC. + * + * (2s) Optional user-supplied dense Jacobian approximation routine: FIDADJAC + * As an option when using the DENSE linear solver, the user may supply a + * routine that computes a dense approximation of the system Jacobian + * J = df/dy. If supplied, it must have the following form: + * SUBROUTINE FIDADJAC(NEQ, T, Y, YP, R, DJAC, CJ, EWT, H, + * 1 IPAR, RPAR, WK1, WK2, WK3, IER) + * DIMENSION Y(*), YP(*), R(*), EWT(*), DJAC(NEQ,*), + * 1 IPAR(*), RPAR(*), WK1(*), WK2(*), WK3(*) + * This routine must compute the Jacobian and store it columnwise in DJAC. + * IPAR and RPAR are user (integer and real) arrays passed to FIDAMALLOC. + * + * (3s) Optional user-supplied band Jacobian approximation routine: FIDABJAC + * As an option when using the BAND linear solver, the user may supply a + * routine that computes a band approximation of the system Jacobian + * J = df/dy. If supplied, it must have the following form: + * SUBROUTINE FIDABJAC(NEQ, MU, ML, MDIM, T, Y, YP, R, CJ, + * 1 BJAC, EWT, H, IPAR, RPAR, WK1, WK2, WK3, IER) + * DIMENSION Y(*), YP(*), R(*), EWT(*), BJAC(MDIM,*), + * 1 IPAR(*), RPAR(*), WK1(*), WK2(*), WK3(*) + * This routine must load the MDIM by N array BJAC with the Jacobian matrix at the + * current (t,y,y') in band form. Store in BJAC(k,j) the Jacobian element J(i,j) + * with k = i - j + MU + 1 (k = 1 ... ML+MU+1) and j = 1 ... N. + * IPAR and RPAR are user (integer and real) arrays passed to FIDAMALLOC. + * + * (4) Optional user-supplied Jacobian-vector product routine: FIDAJTIMES + * As an option when using the SPGMR/SPBCG/SPTFQMR linear solver, the user may + * supply a routine that computes the product of the system Jacobian J = df/dy + * and a given vector v. If supplied, it must have the following form: + * SUBROUTINE FIDAJTIMES(T, Y, YP, R, V, FJV, CJ, EWT, H, + * 1 IPAR, RPAR, WK1, WK2, IER) + * DIMENSION V(*), FJV(*), Y(*), YP(*), R(*), EWT(*), + * 1 IPAR(*), RPAR(*), WK1(*), WK2(*) + * This routine must compute the product vector Jv, where the vector v is stored + * in V, and store the product in FJV. On return, set IER = 0 if FIDAJTIMES was + * successful, and nonzero otherwise. + * IPAR and RPAR are user (integer and real) arrays passed to FIDAMALLOC. + * + * (5) Optional user-supplied error weight vector routine: FIDAEWT + * As an option to providing the relative and absolute tolerances, the user + * may supply a routine that computes the weights used in the WRMS norms. + * If supplied, it must have the following form: + * SUBROUTINE FIDAEWT(Y, EWT, IPAR, RPAR, IER) + * DIMENSION Y(*), EWT(*) + * It must store the error weights in EWT, given the current solution vector Y. + * On return, set IER = 0 if successful, and nonzero otherwise. + * IPAR and RPAR are user (integer and real) arrays passed to FIDAMALLOC. + * + * ----------------------------------------------------------------------------- + * + * (6) Initialization: FNVINITS / FNVINITP , FIDAMALLOC, FIDAREINIT, + * FIDATOLREINIT, and FIDACALCIC + * + * (6.1s) To initialize the serial machine environment, the user must make + * the following call: + * CALL FNVINITS(KEY, NEQ, IER) + * The arguments are: + * KEY = 2 for IDA + * NEQ = size of vectors + * IER = return completion flag. Values are 0 = success, -1 = failure. + * + * (6.1p) To initialize the parallel machine environment, the user must make + * one of the following calls: + * CALL FNVINITP(KEY, NLOCAL, NGLOBAL, IER) + * -or- + * CALL FNVINITP(COMM, KEY, NLOCAL, NGLOBAL, IER) + * The arguments are: + * COMM = MPI communicator (e.g., MPI_COMM_WORLD) + * KEY = 2 for IDA + * NLOCAL = local size of vectors on this processor + * NGLOBAL = the system size, and the global size of vectors (the sum + * of all values of NLOCAL) + * IER = return completion flag. Values are 0 = success, -1 = failure. + * NOTE: The COMM argument passed to the FNVINITP routine is only supported if + * the MPI implementation used to build SUNDIALS includes the MPI_Comm_f2c + * function from the MPI-2 specification. To check if the function is supported + * look for the line "#define SUNDIALS_MPI_COMM_F2C 1" in the sundials_config.h + * header file. + * + * (6.2) To set various problem and solution parameters and allocate + * internal memory, make the following call: + * CALL FIDAMALLOC(T0, Y0, YP0, IATOL, RTOL, ATOL, + * 1 IOUT, ROUT, IPAR, RPAR, IER) + * The arguments are: + * T0 = initial value of t + * Y0 = array of initial conditions, y(t0) + * YP0 = value of y'(t0) + * IATOL = type for absolute tolerance ATOL: 1 = scalar, 2 = array. + * If IATOL = 3, then the user must supply a routine FIDAEWT to compute + * the error weight vector. + * RTOL = relative tolerance (scalar) + * ATOL = absolute tolerance (scalar or array) + * IOUT = array of length at least 21 for integer optional outputs + * (declare as INTEGER*4 or INTEGER*8 according to C type long int) + * ROUT = array of length at least 6 for real optional outputs + * IPAR = array with user integer data + * (declare as INTEGER*4 or INTEGER*8 according to C type long int) + * RPAR = array with user real data + * IER = return completion flag. Values are 0 = SUCCESS, and -1 = failure. + * See printed message for details in case of failure. + * + * The user data arrays IPAR and RPAR are passed unmodified to all subsequent + * calls to user-provided routines. Modifications to either array inside a + * user-provided routine will be propagated. Using these two arrays, the user + * can dispense with Common blocks to pass data betwen user-provided routines. + * + * The optional outputs are: + * LENRW = IOUT( 1) -> IDAGetWorkSpace + * LENIW = IOUT( 2) -> IDAGetWorkSpace + * NST = IOUT( 3) -> IDAGetNumSteps + * NRE = IOUT( 4) -> IDAGetNumResEvals + * NETF = IOUT( 5) -> IDAGetNumErrTestFails + * NCFN = IOUT( 6) -> IDAGetNumNonlinSolvConvFails + * NNI = IOUT( 7) -> IDAGetNumNonlinSolvIters + * NSETUPS = IOUT( 8) -> IDAGetNumLinSolvSetups + * KLAST = IOUT( 9) -> IDAGetLastOrder + * KCUR = IOUT(10) -> IDAGetCurrentOrder + * NBCKTRK = IOUT(11) -> IDAGetNumBacktrackOps + * NGE = IOUT(12) -> IDAGetNumGEvals + * + * HINUSED = ROUT( 1) -> IDAGetActualInitStep + * HLAST = ROUT( 2) -> IDAGetLastStep + * HCUR = ROUT( 3) -> IDAGetCurrentStep + * TCUR = ROUT( 4) -> IDAGetCurrentTime + * TOLSFAC = ROUT( 5) -> IDAGetTolScaleFactor + * UNITRND = ROUT( 6) -> UNIT_ROUNDOFF + * + * + * If the user program includes the FIDAEWT routine for the evaluation of the + * error weights, the following call must be made + * CALL FIDAEWTSET(FLAG, IER) + * with FLAG = 1 to specify that FIDAEWT is provided. + * The return flag IER is 0 if successful, and nonzero otherwise. + * + * (6.3) To set various integer optional inputs, make the folowing call: + * CALL FIDASETIIN(KEY, VALUE, IER) + * to set the optional input specified by the character key KEY to the + * integer value VAL. + * KEY is one of the following: MAX_ORD, MAX_NSTEPS, MAX_ERRFAIL, MAX_NITERS, + * MAX_CONVFAIL, SUPPRESS_ALG, MAX_NSTEPS_IC, MAX_NITERS_IC, MAX_NJE_IC, LS_OFF_IC. + * + * To set various real optional inputs, make the folowing call: + * CALL FIDASETRIN(KEY, VALUE, IER) + * to set the optional input specified by the character key KEY to the + * real value VAL. + * KEY is one of the following: INIT_STEP, MAX_STEP, MIIN_STEP, STOP_TIME, + * NLCONV_COEF. + * + * To set the vector of variable IDs or the vector of constraints, make + * the following call: + * CALL FIDASETVIN(KEY, ARRAY, IER) + * where ARRAY is an array of reals and KEY is 'ID_VEC' or 'CONSTR_VEC'. + * + * FIDASETIIN, FIDASETRIN, and FIDASETVIN return IER=0 if successful and + * IER<0 if an error occured. + * + * (6.4) To re-initialize the FIDA solver for the solution of a new problem + * of the same size as one already solved, make the following call: + * CALL FIDAREINIT(T0, Y0, YP0, IATOL, RTOL, ATOL, ID, CONSTR, IER) + * The arguments have the same names and meanings as those of FIDAMALLOC. + * FIDAREINIT performs the same initializations as FIDAMALLOC, but does no memory + * allocation for IDA data structures, using instead the existing internal memory + * created by the previous FIDAMALLOC call. The call to specify the linear system + * solution method may or may not be needed. See below. + * + * (6.5) To modify the tolerance parameters, make the following call: + * CALL FIDATOLREINIT(IATOL, RTOL, ATOL, IER) + * The arguments have the same names and meanings as those of FIDAMALLOC. + * FIDATOLREINIT simple calls IDASetTolerances with the given arguments. + * + * (6.6) To compute consistent initial conditions for an index-one DAE system, + * make the following call: + * CALL FIDACALCIC(ICOPT, TOUT, IER) + * The arguments are: + * ICOPT = specifies the option: 1 = IDA_YP_YDP_INIT, 2 = IDA_Y_INIT. + * (See user guide for additional details.) + * TOUT = the first value of t at which a solution will be requested + * (from FIDASOLVE). + * IER = return completion flag. + * + * ----------------------------------------------------------------------------- + * + * (7) Specification of linear system solution method. + * FIDA presently includes four choices for the treatment of these systems, + * and the user of FIDA must call a routine with a specific name to make the + * desired choice. + * + * (7.1s) DENSE treatment of the linear system. + * The user must make the call + * CALL FIDADENSE(NEQ, IER) + * The arguments are: + * NEQ = size of vectors + * IER = error return flag: 0 = success , negative value = an error occured + * + * If the user program includes the FIDADJAC routine for the evaluation of the + * dense approximation to the Jacobian, the following call must be made + * CALL FIDADENSESETJAC(FLAG, IER) + * with FLAG = 1 to specify that FIDADJAC is provided. (FLAG = 0 specifies + * using the internal finite differences approximation to the Jacobian.) + * The return flag IER is 0 if successful, and nonzero otherwise. + * + * Optional outputs specific to the DENSE case are: + * LENRWLS = IOUT(13) -> IDADenseGetWorkSpace + * LENIWLS = IOUT(14) -> IDADenseGetWorkSpace + * LSTF = IOUT(15) -> IDADenseGetLastFlag + * NRELS = IOUT(16) -> IDADenseGetNumResEvals + * NJE = IOUT(17) -> IDADenseGetNumJacEvals + * + * (7.2s) BAND treatment of the linear system + * The user must make the call + * CALL FIDABAND(NEQ, MU, ML, IER) + * The arguments are: + * NEQ = size of vectors + * MU = upper bandwidth + * ML = lower bandwidth + * IER = error return flag: 0 = success , negative value = an error occured + * + * If the user program includes the FIDABJAC routine for the evaluation of the + * band approximation to the Jacobian, the following call must be made + * CALL FIDABANDSETJAC (FLAG, IER) + * with FLAG = 1 to specify that FIDABJAC is provided. (FLAG = 0 specifies + * using the internal finite differences approximation to the Jacobian.) + * The return flag IER is 0 if successful, and nonzero otherwise. + * + * Optional outputs specific to the BAND case are: + * LENRWLS = IOUT(13) -> IDABandGetWorkSpace + * LENIWLS = IOUT(14) -> IDABandGetWorkSpace + * LSTF = IOUT(15) -> IDABandGetLastFlag + * NRELS = IOUT(16) -> IDABandGetNumResEvals + * NJE = IOUT(17) -> IDABandGetNumJacEvals + * + * (7.3) SPGMR treatment of the linear systems. + * For the Scaled Preconditioned GMRES solution of the linear systems, + * the user must make the following call: + * CALL FIDASPGMR(MAXL, IGSTYPE, MAXRS, EPLIFAC, DQINCFAC, IER) + * The arguments are: + * MAXL = maximum Krylov subspace dimension; 0 indicates default. + * IGSTYPE = specifies the type of Gram-Schmidt orthogonalization to be used: + * 1 = MODIFIED_GS, 2 = CLASSICAL_GS + * EPLIFAC = factor in the linear iteration convergence test constant + * DQINCFAC = factor in the increments to y used in the difference quotient + * approximations to the matrix-vector products Jv + * IER = error return flag: 0 = success; negative value = an error occured + * + * Optional outputs specific to the SPGMR case are: + * LENRWLS = IOUT(13) -> IDASpgmrGetWorkSpace + * LENIWLS = IOUT(14) -> IDASpgmrGetWorkSpace + * LSTF = IOUT(15) -> IDASpgmrGetLastFlag + * NRELS = IOUT(16) -> IDASpgmrGetResEvals + * NJE = IOUT(17) -> IDASpgmrGetJtimesEvals + * NPE = IOUT(18) -> IDASpgmrGetPrecEvals + * NPS = IOUT(19) -> IDASpgmrGetPrecSolves + * NLI = IOUT(20) -> IDASpgmrGetLinIters + * NLCF = IOUT(21) -> IDASpgmrGetConvFails + * + * If a sequence of problems of the same size is being solved using the + * SPGMR linear solver, then following the call to FIDAREINIT, a call to the + * FIDASPGMRREINIT routine is needed if any of IGSTYPE, MAXRS, EPLIFAC, or + * DQINCFAC is being changed. In that case, call FIDASPGMRREINIT as follows: + * CALL FIDASPGMRREINIT (IGSTYPE, MAXRS, EPLIFAC, DQINCFAC, IER) + * The arguments have the same meanings as for FIDASPGMR. If MAXL is being + * changed, then call FIDASPGMR instead. + * + * (7.4) SPBCG treatment of the linear systems. + * For the Scaled Preconditioned Bi-CGSTAB solution of the linear systems, + * the user must make the following call: + * CALL FIDASPBCG(MAXL, EPLIFAC, DQINCFAC, IER) + * The arguments are: + * MAXL = maximum Krylov subspace dimension; 0 indicates default. + * EPLIFAC = factor in the linear iteration convergence test constant + * DQINCFAC = factor in the increments to y used in the difference quotient + * approximations to matrix-vector products Jv + * IER = error return flag: 0 = success; negative value = an error occured + * + * Optional outputs specific to the SPBCG case are: + * LENRWLS = IOUT(13) -> IDASpbcgGetWorkSpace + * LENIWLS = IOUT(14) -> IDASpbcgGetWorkSpace + * LSTF = IOUT(15) -> IDASpbcgGetLastFlag + * NRELS = IOUT(16) -> IDASpbcgGetResEvals + * NJE = IOUT(17) -> IDASpbcgGetJtimesEvals + * NPE = IOUT(18) -> IDASpbcgGetPrecEvals + * NPS = IOUT(19) -> IDASpbcgGetPrecSolves + * NLI = IOUT(20) -> IDASpbcgGetLinIters + * NLCF = IOUT(21) -> IDASpbcgGetConvFails + * + * If a sequence of problems of the same size is being solved using the + * SPBCG linear solver, then following the call to FIDAREINIT, a call to the + * FIDASPBCGREINIT routine is needed if MAXL, EPLIFAC, or DQINCFAC is + * being changed. In that case, call FIDASPBCGREINIT as follows: + * CALL FIDASPBCGREINIT(MAXL, EPLIFAC, DQINCFAC, IER) + * The arguments have the same meanings as for FIDASPBCG. + * + * (7.5) SPTFQMR treatment of the linear systems. + * For the Scaled Preconditioned TFQMR solution of the linear systems, + * the user must make the following call: + * CALL FIDASPTFQMR(MAXL, EPLIFAC, DQINCFAC, IER) + * The arguments are: + * MAXL = maximum Krylov subspace dimension; 0 indicates default. + * EPLIFAC = factor in the linear iteration convergence test constant + * DQINCFAC = factor in the increments to y used in the difference quotient + * approximations to matrix-vector products Jv + * IER = error return flag: 0 = success; negative value = an error occured + * + * Optional outputs specific to the SPTFQMR case are: + * LENRWLS = IOUT(13) -> IDASptfqmrGetWorkSpace + * LENIWLS = IOUT(14) -> IDASptfqmrGetWorkSpace + * LSTF = IOUT(15) -> IDASptfqmrGetLastFlag + * NRELS = IOUT(16) -> IDASptfqmrGetResEvals + * NJE = IOUT(17) -> IDASptfqmrGetJtimesEvals + * NPE = IOUT(18) -> IDASptfqmrGetPrecEvals + * NPS = IOUT(19) -> IDASptfqmrGetPrecSolves + * NLI = IOUT(20) -> IDASptfqmrGetLinIters + * NLCF = IOUT(21) -> IDASptfqmrGetConvFails + * + * If a sequence of problems of the same size is being solved using the + * SPTFQMR linear solver, then following the call to FIDAREINIT, a call to the + * FIDASPTFQMRREINIT routine is needed if MAXL, EPLIFAC, or DQINCFAC is + * being changed. In that case, call FIDASPTFQMRREINIT as follows: + * CALL FIDASPTFQMRREINIT (MAXL, EPLIFAC, DQINCFAC, IER) + * The arguments have the same meanings as for FIDASPTFQMR. + * + * (7.6) Using user-provided functions for the iterative linear solvers + * + * If the user program includes the FIDAJTIMES routine for the evaluation of the + * Jacobian vector product, the following call must be made + * CALL FIDASPILSSETJAC (FLAG, IER) + * with FLAG = 1 to specify that FIDAJTIMES is provided. (FLAG = 0 specifies + * using and internal finite difference approximation to this product.) + * The return flag IER is 0 if successful, and nonzero otherwise. + * + * Usage of the user-supplied routines FIDAPSOL and FIDAPSET for solution of the + * preconditioner linear system requires the following call: + * CALL FIDASPILSSETPREC(FLAG, IER) + * with FLAG = 1. The return flag IER is 0 if successful, nonzero otherwise. + * The user-supplied routine FIDAPSOL must have the form: + * SUBROUTINE FIDAPSOL(T, Y, YP, R, RV, ZV, CJ, DELTA, EWT, + * 1 IPAR, RPAR, WRK, IER) + * DIMENSION Y(*), YP(*), R(*), RV(*), ZV(*), + * 1 IPAR(*), RPAR(*), EWT(*), WRK(*) + * This routine must solve the preconditioner linear system Pz = r, where r = RV + * is input, and store the solution z in ZV. + * + * The user-supplied routine FIDAPSET must be of the form: + * SUBROUTINE FIDAPSET(T, Y, YP, R, CJ, EWT, H, IPAR, RPAR, + * 1 WK1, WK2, WK3, IER) + * DIMENSION Y(*), YP(*), R(*), EWT(*), IPAR(*), RPAR(*), + * 1 WK1(*), WK2(*), WK3(*) + * This routine must perform any evaluation of Jacobian-related data and + * preprocessing needed for the solution of the preconditioner linear systems + * by FIDAPSOL. On return, set IER = 0 if FIDAPSET was successful, set IER + * positive if a recoverable error occurred, and set IER negative if a + * non-recoverable error occurred. + * IPAR and RPAR are user (integer and real) arrays passed to FIDAMALLOC. + * + * ----------------------------------------------------------------------------- + * + * (8) The solver: FIDASOLVE + * To solve the DAE system, make the following call: + * CALL FIDASOLVE(TOUT, TRET, Y, YP, ITASK, IER) + * The arguments are: + * TOUT = next value of t at which a solution is desired (input) + * TRET = value of t reached by the solver on output + * Y = array containing the computed solution on output + * YP = array containing current value of y' + * ITASK = task indicator: 1 = normal mode (overshoot TOUT and interpolate) + * 2 = one-step mode (return after each internal step taken) + * 3 = normal tstop mode (like 1, but integration never proceeds past + * TSTOP, which must be specified through a call to FIDASETRIN + * using the key 'STOP_TIME' + * 4 = one step tstop (like 2, but integration never goes past TSTOP) + * IER = completion flag: 0 = success, 1 = tstop return, 2 = root return, + * values -1 ... -10 are various failure modes (see IDA manual). + * The current values of the optional outputs are available in IOUT and ROUT. + * + * ----------------------------------------------------------------------------- + * + * (9) Getting current solution: FIDAGETSOL + * To obtain interpolated values of y and y' for any value of t in the last + * internal step taken by IDA, make the following call: + * CALL FIDAGETSOL(T, YRET, YPRET, IER) + * The arguments are: + * T = value of t at which solution is desired, in [TCUR-HU,TCUR]. + * Y = array containing interpolated y + * YP = array containing the derivative of the computed solution, y'(tret) + * IER = return flag: = 0 for success, < 0 for illegal argument. + * + * ----------------------------------------------------------------------------- + * + * (10) Memory freeing: FIDAFREE + * To the free the internal memory created by the calls to FIDAMALLOC and + * FNVINITS or FNVINITP, depending on the version (serial/parallel), make + * the following call: + * CALL FIDAFREE + * + * ============================================================================= + */ + +#ifndef _FIDA_H +#define _FIDA_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include /* definition of type IDAResFn */ +#include /* definition of type DlsMat */ +#include /* definition of type N_Vector */ +#include /* definition of type realtype */ + +#if defined(SUNDIALS_F77_FUNC) + +#define FIDA_MALLOC SUNDIALS_F77_FUNC(fidamalloc, FIDAMALLOC) +#define FIDA_REINIT SUNDIALS_F77_FUNC(fidareinit, FIDAREINIT) +#define FIDA_SETIIN SUNDIALS_F77_FUNC(fidasetiin, FIDASETIIN) +#define FIDA_SETRIN SUNDIALS_F77_FUNC(fidasetrin, FIDASETRIN) +#define FIDA_SETVIN SUNDIALS_F77_FUNC(fidasetvin, FIDASETVIN) +#define FIDA_TOLREINIT SUNDIALS_F77_FUNC(fidatolreinit, FIDATOLREINIT) +#define FIDA_SOLVE SUNDIALS_F77_FUNC(fidasolve, FIDASOLVE) +#define FIDA_FREE SUNDIALS_F77_FUNC(fidafree, FIDAFREE) +#define FIDA_CALCIC SUNDIALS_F77_FUNC(fidacalcic, FIDACALCIC) +#define FIDA_BAND SUNDIALS_F77_FUNC(fidaband, FIDABAND) +#define FIDA_BANDSETJAC SUNDIALS_F77_FUNC(fidabandsetjac, FIDABANDSETJAC) +#define FIDA_DENSE SUNDIALS_F77_FUNC(fidadense, FIDADENSE) +#define FIDA_DENSESETJAC SUNDIALS_F77_FUNC(fidadensesetjac, FIDADENSESETJAC) +#define FIDA_LAPACKBAND SUNDIALS_F77_FUNC(fidalapackband, FIDALAPACKBAND) +#define FIDA_LAPACKBANDSETJAC SUNDIALS_F77_FUNC(fidalapackbandsetjac, FIDALAPACKBANDSETJAC) +#define FIDA_LAPACKDENSE SUNDIALS_F77_FUNC(fidalapackdense, FIDALAPACKDENSE) +#define FIDA_LAPACKDENSESETJAC SUNDIALS_F77_FUNC(fidalapackdensesetjac, FIDALAPACKDENSESETJAC) +#define FIDA_SPTFQMR SUNDIALS_F77_FUNC(fidasptfqmr, FIDASPTFQMR) +#define FIDA_SPBCG SUNDIALS_F77_FUNC(fidaspbcg, FIDASPBCG) +#define FIDA_SPGMR SUNDIALS_F77_FUNC(fidaspgmr, FIDASPGMR) +#define FIDA_SPTFQMRREINIT SUNDIALS_F77_FUNC(fidasptfqmrreinit, FIDASPTFQMRREINIT) +#define FIDA_SPBCGREINIT SUNDIALS_F77_FUNC(fidaspbcgreinit, FIDASPBCGREINIT) +#define FIDA_SPGMRREINIT SUNDIALS_F77_FUNC(fidaspgmrreinit, FIDASPGMRREINIT) +#define FIDA_SPILSSETJAC SUNDIALS_F77_FUNC(fidaspilssetjac, FIDASPILSSETJAC) +#define FIDA_SPILSSETPREC SUNDIALS_F77_FUNC(fidaspilssetprec, FIDASPILSSETPREC) +#define FIDA_RESFUN SUNDIALS_F77_FUNC(fidaresfun, FIDARESFUN) +#define FIDA_DJAC SUNDIALS_F77_FUNC(fidadjac, FIDADJAC) +#define FIDA_BJAC SUNDIALS_F77_FUNC(fidabjac, FIDABJAC) +#define FIDA_PSET SUNDIALS_F77_FUNC(fidapset, FIDAPSET) +#define FIDA_PSOL SUNDIALS_F77_FUNC(fidapsol, FIDAPSOL) +#define FIDA_JTIMES SUNDIALS_F77_FUNC(fidajtimes, FIDAJTIMES) +#define FIDA_EWT SUNDIALS_F77_FUNC(fidaewt, FIDAEWT) +#define FIDA_GETSOL SUNDIALS_F77_FUNC(fidagetsol, FIDAGETSOL) +#define FIDA_GETERRWEIGHTS SUNDIALS_F77_FUNC(fidageterrweights, FIDAGETERRWEIGHTS) +#define FIDA_GETESTLOCALERR SUNDIALS_F77_FUNC(fidagetestlocalerr, FIDAGETESTLOCALERR) + +#else + +#define FIDA_MALLOC fidamalloc_ +#define FIDA_REINIT fidareinit_ +#define FIDA_SETIIN fidasetiin_ +#define FIDA_SETRIN fidasetrin_ +#define FIDA_SETVIN fidasetvin_ +#define FIDA_TOLREINIT fidatolreinit_ +#define FIDA_SOLVE fidasolve_ +#define FIDA_FREE fidafree_ +#define FIDA_CALCIC fidacalcic_ +#define FIDA_BAND fidaband_ +#define FIDA_BANDSETJAC fidabandsetjac_ +#define FIDA_DENSE fidadense_ +#define FIDA_DENSESETJAC fidadensesetjac_ +#define FIDA_LAPACKBAND fidalapackband_ +#define FIDA_LAPACKBANDSETJAC fidalapackbandsetjac_ +#define FIDA_LAPACKDENSE fidalapackdense_ +#define FIDA_LAPACKDENSESETJAC fidalapackdensesetjac_ +#define FIDA_SPTFQMR fidasptfqmr_ +#define FIDA_SPBCG fidaspbcg_ +#define FIDA_SPGMR fidaspgmr_ +#define FIDA_SPTFQMRREINIT fidasptfqmrreinit_ +#define FIDA_SPBCGREINIT fidaspbcgreinit_ +#define FIDA_SPGMRREINIT fidaspgmrreinit_ +#define FIDA_SPILSSETJAC fidaspilssetjac_ +#define FIDA_SPILSSETPREC fidaspilssetprec_ +#define FIDA_RESFUN fidaresfun_ +#define FIDA_DJAC fidadjac_ +#define FIDA_BJAC fidabjac_ +#define FIDA_PSET fidapset_ +#define FIDA_PSOL fidapsol_ +#define FIDA_JTIMES fidajtimes_ +#define FIDA_EWT fidaewt_ +#define FIDA_GETSOL fidagetsol_ +#define FIDA_GETERRWEIGHTS fidageterrweights_ +#define FIDA_GETESTLOCALERR fidagetestlocalerr_ + +#endif + +/* Type for user data */ + +typedef struct { + realtype *rpar; + long int *ipar; +} *FIDAUserData; + +/* Prototypes of exported functions */ + +void FIDA_MALLOC(realtype *t0, realtype *yy0, realtype *yp0, + int *iatol, realtype *rtol, realtype *atol, + long int *iout, realtype *rout, + long int *ipar, realtype *rpar, + int *ier); +void FIDA_REINIT(realtype *t0, realtype *yy0, realtype *yp0, + int *iatol, realtype *rtol, realtype *atol, + int *ier); + +void FIDA_SETIIN(char key_name[], long int *ival, int *ier, int key_len); + +void FIDA_SETRIN(char key_name[], realtype *rval, int *ier, int key_len); + +void FIDA_SETVIN(char key_name[], realtype *vval, int *ier, int key_len); + +void FIDA_TOLREINIT(int *iatol, realtype *rtol, realtype *atol, int *ier); +void FIDA_CALCIC(int *icopt, realtype *tout1, int *ier); + +void FIDA_DENSE(int *neq, int *ier); +void FIDA_DENSESETJAC(int *flag, int *ier); +void FIDA_BAND(int *neq, int *mupper, int *mlower, int *ier); +void FIDA_BANDSETJAC(int *flag, int *ier); + +void FIDA_LAPACKDENSE(int *neq, int *ier); +void FIDA_LAPACKDENSESETJAC(int *flag, int *ier); +void FIDA_LAPACKBAND(int *neq, int *mupper, int *mlower, int *ier); +void FIDA_LAPACKBANDSETJAC(int *flag, int *ier); + +void FIDA_SPTFQMR(int *maxl, realtype *eplifac, realtype *dqincfac, int *ier); +void FIDA_SPBCG(int *maxl, realtype *eplifac, realtype *dqincfac, int *ier); +void FIDA_SPGMR(int *maxl, int *gstype, int *maxrs, realtype *eplifac, + realtype *dqincfac, int *ier); +void FIDA_SPTFQMRREINIT(int *maxl, realtype *eplifac, realtype *dqincfac, int *ier); +void FIDA_SPBCGREINIT(int *maxl, realtype *eplifac, realtype *dqincfac, int *ier); +void FIDA_SPGMRREINIT(int *gstype, int *maxrs, realtype *eplifac, + realtype *dqincfac, int *ier); +void FIDA_SPILSSETJAC(int *flag, int *ier); +void FIDA_SPILSSETPREC(int *flag, int *ier); + +void FIDA_SOLVE(realtype *tout, realtype *tret, realtype *yret, + realtype *ypret, int *itask, int *ier); +void FIDA_FREE(void); +void FIDA_EWTSET(int *flag, int *ier); +void FIDA_GETSOL(realtype *t, realtype *yret, realtype *ypret, int *ier); +void FIDA_GETERRWEIGHTS(realtype *eweight, int *ier); +void FIDA_GETESTLOCALERR(realtype *ele, int *ier); + +/* Prototypes: Functions Called by the IDA Solver */ + +int FIDAresfn(realtype t, N_Vector yy, N_Vector yp, N_Vector rr, void *user_data); + +int FIDADenseJac(int N, realtype t, realtype c_j, + N_Vector yy, N_Vector yp, N_Vector rr, + DlsMat Jac, void *user_data, + N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3); + +int FIDABandJac(int N, int mupper, int mlower, + realtype t, realtype c_j, + N_Vector yy, N_Vector yp, N_Vector rr, + DlsMat Jac, void *user_data, + N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3); + +int FIDAJtimes(realtype t, N_Vector yy, N_Vector yp, N_Vector rr, + N_Vector v, N_Vector Jv, + realtype c_j, void *user_data, + N_Vector vtemp1, N_Vector vtemp2); + +int FIDAPSet(realtype t, N_Vector yy, N_Vector yp, N_Vector rr, + realtype c_j, void *user_data, + N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3); + +int FIDAPSol(realtype t, N_Vector yy, N_Vector yp, N_Vector rr, + N_Vector rvec, N_Vector zvec, + realtype c_j, realtype delta, void *user_data, + N_Vector vtemp1); + +int FIDAEwtSet(N_Vector yy, N_Vector ewt, void *user_data); + +/* Declarations for global variables shared amongst various routines */ + +extern N_Vector F2C_IDA_vec; /* defined in FNVECTOR module */ + +extern N_Vector F2C_IDA_ypvec; /* defined in fida.c */ +extern N_Vector F2C_IDA_ewtvec; /* defined in fida.c */ +extern void *IDA_idamem; /* defined in fida.c */ +extern long int *IDA_iout; /* defined in fida.c */ +extern realtype *IDA_rout; /* defined in fida.c */ +extern int IDA_ls; /* defined in fida.c */ +extern int IDA_nrtfn; /* defined in fida.c */ + +/* Linear solver IDs */ + +enum { IDA_LS_DENSE = 1, IDA_LS_BAND = 2, + IDA_LS_LAPACKDENSE = 3, IDA_LS_LAPACKBAND = 4, + IDA_LS_SPGMR = 5, IDA_LS_SPBCG = 6, IDA_LS_SPTFQMR = 7 }; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidaband.c b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidaband.c new file mode 100644 index 0000000..06190c8 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidaband.c @@ -0,0 +1,117 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.5 $ + * $Date: 2007/04/30 19:29:00 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Fortran/C interface routines for IDA/IDABAND, for the case of + * a user-supplied Jacobian approximation routine. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "fida.h" /* function names, prototypes, global vars.*/ +#include "ida_impl.h" /* definition of IDAMem type */ + +#include + +/*************************************************/ + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + + extern void FIDA_BJAC(int*, int*, int*, int*, + realtype*, realtype*, realtype*, realtype*, + realtype*, realtype*, realtype*, realtype*, + long int*, realtype*, + realtype*, realtype*, realtype*, int*); + +#ifdef __cplusplus +} +#endif + +/*************************************************/ + +void FIDA_BANDSETJAC(int *flag, int *ier) +{ + *ier = 0; + + if (*flag == 0) { + + *ier = IDADlsSetBandJacFn(IDA_idamem, NULL); + + } else { + + if (F2C_IDA_ewtvec == NULL) { + F2C_IDA_ewtvec = N_VClone(F2C_IDA_vec); + if (F2C_IDA_ewtvec == NULL) { + *ier = -1; + return; + } + } + + *ier = IDADlsSetBandJacFn(IDA_idamem, FIDABandJac); + + } + + return; +} + +/*************************************************/ + +int FIDABandJac(int N, int mupper, int mlower, + realtype t, realtype c_j, + N_Vector yy, N_Vector yp, N_Vector rr, + DlsMat J, void *user_data, + N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3) +{ + realtype *yy_data, *yp_data, *rr_data, *jacdata, *ewtdata, *v1data, *v2data, *v3data; + realtype h; + int eband; + int ier; + FIDAUserData IDA_userdata; + + /* Initialize all pointers to NULL */ + yy_data = yp_data = rr_data = jacdata = ewtdata = NULL; + v1data = v2data = v3data = NULL; + + /* NOTE: The user-supplied routine should set ier to an + appropriate value, but we preset the value to zero + (meaning SUCCESS) so the user need only reset the + value if an error occurred */ + ier = 0; + + IDAGetErrWeights(IDA_idamem, F2C_IDA_ewtvec); + IDAGetLastStep(IDA_idamem, &h); + + /* Get pointers to vector data */ + yy_data = N_VGetArrayPointer(yy); + yp_data = N_VGetArrayPointer(yp); + rr_data = N_VGetArrayPointer(rr); + ewtdata = N_VGetArrayPointer(F2C_IDA_ewtvec); + v1data = N_VGetArrayPointer(vtemp1); + v2data = N_VGetArrayPointer(vtemp2); + v3data = N_VGetArrayPointer(vtemp3); + + eband = (J->s_mu) + mlower + 1; + jacdata = BAND_COL(J,0) - mupper; + + IDA_userdata = (FIDAUserData) user_data; + + /* Call user-supplied routine */ + FIDA_BJAC(&N, &mupper, &mlower, &eband, &t, yy_data, yp_data, rr_data, + &c_j, jacdata, ewtdata, &h, + IDA_userdata->ipar, IDA_userdata->rpar, + v1data, v2data, v3data, &ier); + + return(ier); +} diff --git a/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidabbd.c b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidabbd.c new file mode 100644 index 0000000..fae7722 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidabbd.c @@ -0,0 +1,150 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.5 $ + * $Date: 2007/04/30 19:29:00 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This module contains the routines necessary to interface with the + * IDABBDPRE module and user-supplied Fortran routines. + * The routines here call the generically named routines and provide + * a standard interface to the C code of the IDABBDPRE package. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "fida.h" /* function names, prototypes, global variables */ +#include "fidabbd.h" /* prototypes of interfaces to IDABBD */ + +#include /* prototypes of IDABBDPRE functions and macros */ +#include /* prototypes of IDASPGMR interface routines */ +#include /* prototypes of IDASPBCG interface routines */ +#include /* prototypes of IDASPTFQMR interface routines */ + +/*************************************************/ + +/* private constant(s) */ + +#define ZERO RCONST(0.0) + +/*************************************************/ + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + + extern void FIDA_GLOCFN(int*, + realtype*, realtype*, realtype*, realtype*, + long int*, realtype*, + int*); + extern void FIDA_COMMFN(int*, + realtype*, realtype*, realtype*, + long int*, realtype*, + int*); + +#ifdef __cplusplus +} +#endif + +/*************************************************/ + +void FIDA_BBDINIT(int *Nloc, int *mudq, int *mldq, + int *mu, int *ml, realtype *dqrely, int *ier) +{ + *ier = IDABBDPrecInit(IDA_idamem, *Nloc, *mudq, *mldq, *mu, *ml, + *dqrely, (IDABBDLocalFn) FIDAgloc, (IDABBDCommFn) FIDAcfn); + + return; +} + +/*************************************************/ + +void FIDA_BBDREINIT(int *Nloc, int *mudq, int *mldq, + realtype *dqrely, int *ier) +{ + *ier = 0; + + *ier = IDABBDPrecReInit(IDA_idamem, *mudq, *mldq, *dqrely); + + return; +} + +/*************************************************/ + +int FIDAgloc(int Nloc, realtype t, N_Vector yy, N_Vector yp, + N_Vector gval, void *user_data) +{ + realtype *yy_data, *yp_data, *gval_data; + int ier; + FIDAUserData IDA_userdata; + + /* Initialize all pointers to NULL */ + yy_data = yp_data = gval_data = NULL; + + /* NOTE: The user-supplied routine should set ier to an + appropriate value, but we preset the value to zero + (meaning SUCCESS) so the user need only reset the + value if an error occurred */ + ier = 0; + + /* Get pointers to vector data */ + yy_data = N_VGetArrayPointer(yy); + yp_data = N_VGetArrayPointer(yp); + gval_data = N_VGetArrayPointer(gval); + + IDA_userdata = (FIDAUserData) user_data; + + /* Call user-supplied routine */ + FIDA_GLOCFN(&Nloc, &t, yy_data, yp_data, gval_data, + IDA_userdata->ipar, IDA_userdata->rpar, &ier); + + return(ier); +} + +/*************************************************/ + +int FIDAcfn(int Nloc, realtype t, N_Vector yy, N_Vector yp, + void *user_data) +{ + realtype *yy_data, *yp_data; + int ier; + FIDAUserData IDA_userdata; + + /* Initialize all pointers to NULL */ + yy_data = yp_data = NULL; + + /* NOTE: The user-supplied routine should set ier to an + appropriate value, but we preset the value to zero + (meaning SUCCESS) so the user need only reset the + value if an error occurred */ + ier = 0; + + /* Get pointers to vector data */ + yy_data = N_VGetArrayPointer(yy); + yp_data = N_VGetArrayPointer(yp); + + IDA_userdata = (FIDAUserData) user_data; + + /* Call user-supplied routine */ + FIDA_COMMFN(&Nloc, &t, yy_data, yp_data, + IDA_userdata->ipar, IDA_userdata->rpar, &ier); + + return(ier); +} + +/*************************************************/ + +void FIDA_BBDOPT(long int *lenrwbbd, long int *leniwbbd, long int *ngebbd) +{ + IDABBDPrecGetWorkSpace(IDA_idamem, lenrwbbd, leniwbbd); + IDABBDPrecGetNumGfnEvals(IDA_idamem, ngebbd); + + return; +} diff --git a/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidabbd.h b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidabbd.h new file mode 100644 index 0000000..770024f --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidabbd.h @@ -0,0 +1,333 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.7 $ + * $Date: 2008/04/16 21:18:22 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the Fortran interface include file for the BBD + * preconditioner (IDABBDPRE) + * ----------------------------------------------------------------- + */ + +/* + * ============================================================================== + * + * FIDABBD Interface Package + * + * The FIDABBD Interface Package is a package of C functions which, + * together with the FIDA Interface Package, support the use of the + * IDA solver (parallel MPI version) with the IDABBDPRE preconditioner module, + * for the solution of DAE systems in a mixed Fortran/C setting. The + * combination of IDA and IDABBDPRE solves DAE systems with the SPGMR + * (scaled preconditioned GMRES), SPBCG (scaled preconditioned Bi-CGSTAB), or + * SPTFQMR (scaled preconditioned TFQMR) method for the linear systems that arise, + * and with a preconditioner that is block-diagonal with banded blocks. While + * IDA and IDABBDPRE are written in C, it is assumed here that the user's + * calling program and user-supplied problem-defining routines are written in + * Fortran. + * + * The user-callable functions in this package, with the corresponding + * IDA and IDABBDPRE functions, are as follows: + * FIDABBDININT interfaces to IDABBDPrecInit + * FIDABBDSPGMR interfaces to IDABBDSpgmr and IDASpilsSet* + * FIDABBDSPBCG interfaces to IDABBDSpbcg and IDASpilsSet* + * FIDABBDSPTFQMR interfaces to IDABBDSptfqmr and IDASpilsSet* + * FIDABBDREINIT interfaces to IDABBDPrecReInit + * FIDABBDOPT accesses optional outputs + * FIDABBDFREE interfaces to IDABBDPrecFree + * + * In addition to the Fortran residual function FIDARESFUN, the + * user-supplied functions used by this package, are listed below, + * each with the corresponding interface function which calls it (and its + * type within IDABBDPRE or IDA): + * FIDAGLOCFN is called by the interface function FIDAgloc of type IDABBDLocalFn + * FIDACOMMFN is called by the interface function FIDAcfn of type IDABBDCommFn + * FIDAJTIMES (optional) is called by the interface function FIDAJtimes of + * type IDASpilsJacTimesVecFn + * (The names of all user-supplied routines here are fixed, in order to + * maximize portability for the resulting mixed-language program.) + * + * Important note on portability: + * In this package, the names of the interface functions, and the names of + * the Fortran user routines called by them, appear as dummy names + * which are mapped to actual values by a series of definitions in the + * header file fidabbd.h. + * + * ============================================================================== + * + * Usage of the FIDA/FIDABBD Interface Packages + * + * The usage of the combined interface packages FIDA and FIDABBD requires + * calls to several interface functions, and a few different user-supplied + * routines which define the problem to be solved and indirectly define + * the preconditioner. These function calls and user routines are + * summarized separately below. + * + * Some details are omitted, and the user is referred to the IDA user document + * for more complete information. + * + * (1) User-supplied residual routine: FIDARESFUN + * The user must in all cases supply the following Fortran routine + * SUBROUTINE FIDARESFUN(T, Y, YP, R, IPAR, RPAR, IER) + * DIMENSION Y(*), YP(*), R(*), IPAR(*), RPAR(*) + * It must set the R array to F(t,y,y'), the residual of the DAE + * system, as a function of T = t, the array Y = y, and the array YP = y'. + * Here Y, YP and R are distributed vectors. + * + * (2) User-supplied routines to define preconditoner: FIDAGLOCFN and FIDACOMMFN + * + * The routines in the IDABBDPRE module provide a preconditioner matrix + * for IDA that is block-diagonal with banded blocks. The blocking + * corresponds to the distribution of the dependent variable vectors y and y' + * among the processes. Each preconditioner block is generated from the + * Jacobian of the local part (associated with the current process) of a given + * function G(t,y,y') approximating F(t,y,y'). The blocks are generated by a + * difference quotient scheme independently by each process, utilizing + * an assumed banded structure with given half-bandwidths. A separate + * pair of half-bandwidths defines the band matrix retained. + * + * (2.1) Local approximate function FIDAGLOCFN. + * The user must supply a subroutine of the form + * SUBROUTINE FIDAGLOCFN(NLOC, T, YLOC, YPLOC, GLOC, IPAR, RPAR, IER) + * DIMENSION YLOC(*), YPLOC(*), GLOC(*), IPAR(*), RPAR(*) + * to compute the function G(t,y,y') which approximates the residual + * function F(t,y,y'). This function is to be computed locally, i.e., without + * interprocess communication. (The case where G is mathematically + * identical to F is allowed.) It takes as input the local vector length + * NLOC, the independent variable value T = t, and the local realtype + * dependent variable arrays YLOC and YPLOC. It is to compute the local part + * of G(t,y,y') and store this in the realtype array GLOC. + * + * (2.2) Communication function FIDACOMMF. + * The user must also supply a subroutine of the form + * SUBROUTINE FIDACOMMFN(NLOC, T, YLOC, YPLOC, IPAR, RPAR, IER) + * DIMENSION YLOC(*), YPLOC(*), IPAR(*), RPAR(*) + * which is to perform all interprocess communication necessary to + * evaluate the approximate residual function G described above. + * This function takes as input the local vector length NLOC, the + * independent variable value T = t, and the local real dependent + * variable arrays YLOC and YPLOC. It is expected to save communicated + * data in work space defined by the user, and made available to FIDAGLOCFN. + * Each call to the FIDACOMMFN is preceded by a call to FIDARESFUN with + * the same (t,y,y') arguments. Thus FIDACOMMFN can omit any + * communications done by FIDARESFUN if relevant to the evaluation of G. + * + * (3) Optional user-supplied Jacobian-vector product routine: FIDAJTIMES + * As an option when using the SPGMR/SPBCG/SPTFQMR linear solver, the user may + * supply a routine that computes the product of the system Jacobian J = df/dy + * and a given vector v. If supplied, it must have the following form: + * SUBROUTINE FIDAJTIMES(T, Y, YP, R, V, FJV, CJ, EWT, H, + * 1 IPAR, RPAR, WK1, WK2, IER) + * DIMENSION V(*), FJV(*), Y(*), YP(*), R(*), EWT(*), + * 1 , IPAR(*), RPAR(*), WK1(*), WK2(*) + * This routine must compute the product vector Jv, where the vector v is stored + * in V, and store the product in FJV. On return, set IER = 0 if FIDAJTIMES was + * successful, and nonzero otherwise. + * + * (4) Initialization: FNVINITP, FIDAMALLOC, FIDABBDINIT. + * + * (4.1) To initialize the parallel machine environment, the user must make + * one of the following calls: + * CALL FNVINITP (KEY, NLOCAL, NGLOBAL, IER) + * -or- + * CALL FNVINITP (COMM, KEY, NLOCAL, NGLOBAL, IER) + * The arguments are: + * COMM = MPI communicator (e.g., MPI_COMM_WORLD) + * KEY = 3 for IDA + * NLOCAL = local size of vectors on this processor + * NGLOBAL = the system size, and the global size of vectors (the sum + * of all values of NLOCAL) + * IER = return completion flag. Values are 0 = success, -1 = failure. + * NOTE: The COMM argument passed to the FNVINITP routine is only supported if + * the MPI implementation used to build SUNDIALS includes the MPI_Comm_f2c + * function from the MPI-2 specification. To check if the function is supported + * look for the line "#define SUNDIALS_MPI_COMM_F2C 1" in the sundials_config.h + * header file. + * + * (4.2) To set various problem and solution parameters and allocate + * internal memory, make the following call: + * CALL FIDAMALLOC(T0, Y0, YP0, IATOL, RTOL, ATOL, ID, CONSTR, + * 1 IOUT, ROUT, IPAR, RPAR, IER) + * The arguments are: + * T0 = initial value of t + * Y0 = array of initial conditions, y(t0) + * YP0 = value of y'(t0) + * IATOL = type for absolute tolerance ATOL: 1 = scalar, 2 = array. + * If IATOL = 3, then the user must supply a routine FIDAEWT to compute + * the error weight vector. + * RTOL = relative tolerance (scalar) + * ATOL = absolute tolerance (scalar or array) + * IOUT = array of length at least 21 for integer optional inputs and outputs + * (declare as INTEGER*4 or INTEGER*8 according to C type long int) + * ROUT = array of length 6 for real optional inputs and outputs + * + * The optional outputs are: + * + * LENRW = IOUT( 1) -> IDAGetWorkSpace + * LENIW = IOUT( 2) -> IDAGetWorkSpace + * NST = IOUT( 3) -> IDAGetNumSteps + * NRE = IOUT( 4) -> IDAGetNumResEvals + * NETF = IOUT( 5) -> IDAGetNumErrTestFails + * NCFN = IOUT( 6) -> IDAGetNumNonlinSolvConvFails + * NNI = IOUT( 7) -> IDAGetNumNonlinSolvIters + * NSETUPS = IOUT( 8) -> IDAGetNumLinSolvSetups + * KLAST = IOUT( 9) -> IDAGetLastOrder + * KCUR = IOUT(10) -> IDAGetCurrentOrder + * NBCKTRK = IOUT(11) -> IDAGetNumBacktrackOps + * NGE = IOUT(12) -> IDAGetNumGEvals + * + * HINUSED = ROUT( 1) -> IDAGetActualInitStep + * HLAST = ROUT( 2) -> IDAGetLastStep + * HCUR = ROUT( 3) -> IDAGetCurrentStep + * TCUR = ROUT( 4) -> IDAGetCurrentTime + * TOLSFAC = ROUT( 5) -> IDAGetTolScaleFactor + * UNITRND = ROUT( 6) -> UNIT_ROUNDOFF + * + * IPAR = array with user integer data + * (declare as INTEGER*4 or INTEGER*8 according to C type long int) + * RPAR = array with user real data + * IER = return completion flag. Values are 0 = SUCCESS, and -1 = failure. + * See printed message for details in case of failure. + * + * If the user program includes the FIDAEWT routine for the evaluation of the + * error weights, the following call must be made + * CALL FIDAEWTSET (FLAG, IER) + * with FLAG = 1 to specify that FIDAEWT is provided. + * The return flag IER is 0 if successful, and nonzero otherwise. + * + * (4.3) Attach one of the 3 SPILS linear solvers. Make one of the + * following calls (see fida.h) for more details. + * CALL FIDASPGMR(MAXL, IGSTYPE, MAXRS, EPLIFAC, DQINCFAC, IER) + * CALL FIDASPBCG(MAXL, EPLIFAC, DQINCFAC, IER) + * CALL FIDASPTFQMR(MAXL, EPLIFAC, DQINCFAC, IER) + * + * (4.4) To allocate memory and initialize data associated with the IDABBDPRE + * preconditioner, make the following call: + * CALL FIDABBDINIT(NLOCAL, MUDQ, MLDQ, MU, ML, DQRELY, IER) + * The arguments are: + * NLOCAL = local size of vectors + * MUDQ,MLDQ = upper and lower half-bandwidths to be used in the computation + * of the local Jacobian blocks by difference quotients. + * These may be smaller than the true half-bandwidths of the + * Jacobian of the local block of g, when smaller values may + * provide greater efficiency. + * MU, ML = upper and lower half-bandwidths of the band matrix that + * is retained as an approximation of the local Jacobian block. + * These may be smaller than MUDQ and MLDQ. + * DQRELY = relative increment factor in y for difference quotients + * (optional). 0.0 indicates the default, sqrt(UNIT_ROUNDOFF). + * IER = return completion flag: IER=0: success, IER<0: an error occured + * + * (4.5) To specify whether the linear solver should use the supplied FIDAJTIMES or the + * internal finite difference approximation, make the call + * CALL FIDASPILSSETJAC(FLAG, IER) + * where FLAG=0 for finite differences approxaimtion or + * FLAG=1 to use the supplied routine FIDAJTIMES + * + * (5) Re-initialization: FIDAREINIT, FIDABBDREINIT + * If a sequence of problems of the same size is being solved using the SPGMR or + * SPBCG linear solver in combination with the IDABBDPRE preconditioner, then the + * IDA package can be reinitialized for the second and subsequent problems + * so as to avoid further memory allocation. First, in place of the call + * to FIDAMALLOC, make the following call: + * CALL FIDAREINIT(T0, Y0, YP0, IATOL, RTOL, ATOL, ID, CONSTR, IER) + * The arguments have the same names and meanings as those of FIDAMALLOC. + * FIDAREINIT performs the same initializations as FIDAMALLOC, but does no + * memory allocation for IDA data structures, using instead the existing + * internal memory created by the previous FIDAMALLOC call. Following the call + * to FIDAREINIT, a call to FIDABBDINIT may or may not be needed. If the input + * arguments are the same, no FIDABBDINIT call is needed. If there is a change + * in input arguments other than MU, ML or MAXL, then the user program should call + * FIDABBDREINIT. The arguments of the FIDABBDREINIT routine have the + * same names and meanings as FIDABBDINIT. Finally, if the value of MU, ML, or + * MAXL is being changed, then a call to FIDABBDINIT must be made. + * + * (6) The solver: FIDASOLVE + * To solve the DAE system, make the following call: + * CALL FIDASOLVE (TOUT, TRET, Y, YP, ITASK, IER) + * The arguments are: + * TOUT = next value of t at which a solution is desired (input) + * TRET = value of t reached by the solver on output + * Y = array containing the computed solution on output + * YP = array containing current value of y' + * ITASK = task indicator: 1 = normal mode (overshoot TOUT and interpolate) + * 2 = one-step mode (return after each internal step taken) + * 3 = normal tstop mode (like 1, but integration never proceeds past + * TSTOP, which must be specified through a call to FIDASETRIN + * using the key 'STOP_TIME' + * 4 = one step tstop (like 2, but integration never goes past TSTOP) + * IER = completion flag: 0 = success, 1 = tstop return, 2 = root return, + * values -1 ... -10 are various failure modes (see IDA manual). + * The current values of the optional outputs are available in IOUT and ROUT. + * + * (7) Optional outputs: FIDABBDOPT + * Optional outputs specific to the SPGMR/SPBCG/SPTFQMR solver are available + * in IOUT(13)...IOUT(21) + * + * To obtain the optional outputs associated with the IDABBDPRE module, make + * the following call: + * CALL FIDABBDOPT (LENRWBBD, LENIWBBD, NGEBBD) + * The arguments returned are: + * LENRWBBD = length of real preconditioner work space, in realtype words. + * This size is local to the current process. + * LENIWBBD = length of integer preconditioner work space, in integer words. + * This size is local to the current process. + * NGEBBD = number of G(t,y,y') evaluations (calls to FIDAGLOCFN) so far. + * + * (8) Memory freeing: FIDAFREE + * To the free the internal memory created by the calls to FNVINITP and + * FIDAMALLOC, make the following call: + * CALL FIDAFREE + * + * ============================================================================== + */ + +#ifndef _FIDABBD_H +#define _FIDABBD_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +#if defined(F77_FUNC) + +#define FIDA_BBDINIT F77_FUNC(fidabbdinit, FIDABBDINIT) +#define FIDA_BBDREINIT F77_FUNC(fidabbdreinit, FIDABBDREINIT) +#define FIDA_BBDOPT F77_FUNC(fidabbdopt, FIDABBDOPT) +#define FIDA_GLOCFN F77_FUNC(fidaglocfn, FIDAGLOCFN) +#define FIDA_COMMFN F77_FUNC(fidacommfn, FIDACOMMFN) + +#else + +#define FIDA_BBDINIT fidabbdinit_ +#define FIDA_BBDREINIT fidabbdreinit_ +#define FIDA_BBDOPT fidabbdopt_ +#define FIDA_GLOCFN fidaglocfn_ +#define FIDA_COMMFN fidacommfn_ + +#endif + +/* Prototypes of exported functions */ + +void FIDA_BBDINIT(int *Nloc, int *mudq, int *mldq, int *mu, int *ml, realtype *dqrely, int *ier); +void FIDA_BBDOPT(long int *lenrwbbd, long int *leniwbbd, long int *ngebbd); + +/* Prototypes: Functions Called by the IDABBD Module */ + +int FIDAgloc(int Nloc, realtype t, N_Vector yy, N_Vector yp, N_Vector gval, void *user_data); +int FIDAcfn(int Nloc, realtype t, N_Vector yy, N_Vector yp, void *user_data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidadense.c b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidadense.c new file mode 100644 index 0000000..3c401b6 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidadense.c @@ -0,0 +1,115 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.5 $ + * $Date: 2007/04/30 19:29:00 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Fortran/C interface routines for IDA/IDADENSE, for the case + * of a user-supplied Jacobian approximation routine. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "fida.h" /* actual function names, prototypes and global vars.*/ +#include "ida_impl.h" /* definition of IDAMem type */ + +#include + +/*************************************************/ + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + + extern void FIDA_DJAC(int*, + realtype*, realtype*, realtype*, realtype*, + realtype*, + realtype*, realtype*, realtype*, + long int*, realtype*, + realtype*, realtype*, realtype*, + int*); + +#ifdef __cplusplus +} +#endif + +/*************************************************/ + +void FIDA_DENSESETJAC(int *flag, int *ier) +{ + *ier = 0; + + if (*flag == 0) { + + *ier = IDADlsSetDenseJacFn(IDA_idamem, NULL); + + } else { + + if (F2C_IDA_ewtvec == NULL) { + F2C_IDA_ewtvec = N_VClone(F2C_IDA_vec); + if (F2C_IDA_ewtvec == NULL) { + *ier = -1; + return; + } + } + + *ier = IDADlsSetDenseJacFn(IDA_idamem, FIDADenseJac); + } + + return; +} + +/*************************************************/ + +int FIDADenseJac(int N, realtype t, realtype c_j, + N_Vector yy, N_Vector yp, N_Vector rr, + DlsMat Jac, void *user_data, + N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3) +{ + realtype *yy_data, *yp_data, *rr_data, *jacdata, *ewtdata, *v1data, *v2data, *v3data; + realtype h; + int ier; + FIDAUserData IDA_userdata; + + /* Initialize all pointers to NULL */ + yy_data = yp_data = rr_data = jacdata = ewtdata = NULL; + v1data = v2data = v3data = NULL; + + /* NOTE: The user-supplied routine should set ier to an + appropriate value, but we preset the value to zero + (meaning SUCCESS) so the user need only reset the + value if an error occurred */ + ier = 0; + + IDAGetErrWeights(IDA_idamem, F2C_IDA_ewtvec); + IDAGetLastStep(IDA_idamem, &h); + + /* Get pointers to vector data */ + yy_data = N_VGetArrayPointer(yy); + yp_data = N_VGetArrayPointer(yp); + rr_data = N_VGetArrayPointer(rr); + ewtdata = N_VGetArrayPointer(F2C_IDA_ewtvec); + v1data = N_VGetArrayPointer(vtemp1); + v2data = N_VGetArrayPointer(vtemp2); + v3data = N_VGetArrayPointer(vtemp3); + + jacdata = DENSE_COL(Jac,0); + + IDA_userdata = (FIDAUserData) user_data; + + /* Call user-supplied routine*/ + FIDA_DJAC(&N, &t, yy_data, yp_data, rr_data, jacdata, + &c_j, ewtdata, &h, + IDA_userdata->ipar, IDA_userdata->rpar, + v1data, v2data, v3data, &ier); + + return(ier); +} diff --git a/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidaewt.c b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidaewt.c new file mode 100644 index 0000000..53ecf9c --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidaewt.c @@ -0,0 +1,87 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.3 $ + * $Date: 2007/04/30 19:29:00 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Fortran/C interface routines for IDA, for the case of a + * user-supplied error weight calculation routine. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "fida.h" /* actual function names, prototypes and global vars.*/ +#include "ida_impl.h" /* definition of IDAMem type */ + +/*************************************************/ + +/* Prototype of user-supplied Fortran routine */ + +#ifdef __cplusplus /* wrapper to enable C++ usage (IDAEwtFn) */ +extern "C" { +#endif + + extern void FIDA_EWT(realtype*, realtype*, /* Y, EWT */ + long int*, realtype*, /* IPAR, RPAR */ + int*); /* IER */ + +#ifdef __cplusplus +} +#endif + +/*************************************************/ + +/* + * User-callable function to interface to IDASetEwtFn. + */ + +void FIDA_EWTSET(int *flag, int *ier) +{ + *ier = 0; + + if (*flag != 0) { + *ier = IDAWFtolerances(IDA_idamem, FIDAEwtSet); + } + + return; +} + +/*************************************************/ + +/* + * C function to interface between IDA and a Fortran subroutine FIDAVEWT. + */ + +int FIDAEwtSet(N_Vector y, N_Vector ewt, void *user_data) +{ + int ier; + realtype *y_data, *ewt_data; + FIDAUserData IDA_userdata; + + /* Initialize all pointers to NULL */ + y_data = ewt_data = NULL; + + /* NOTE: The user-supplied routine should set ier to an + appropriate value, but we preset the value to zero + (meaning SUCCESS) so the user need only reset the + value if an error occurred */ + ier = 0; + + y_data = N_VGetArrayPointer(y); + ewt_data = N_VGetArrayPointer(ewt); + + IDA_userdata = (FIDAUserData) user_data; + + /* Call user-supplied routine */ + FIDA_EWT(y_data, ewt_data, IDA_userdata->ipar, IDA_userdata->rpar, &ier); + + return(ier); +} diff --git a/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidajtimes.c b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidajtimes.c new file mode 100644 index 0000000..cbd1adb --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidajtimes.c @@ -0,0 +1,116 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.3 $ + * $Date: 2007/04/30 19:29:00 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * The C function FIDAJtimes is to interface between the + * IDASPILS modules and the user-supplied Jacobian-vector + * product routine FIDAJTIMES. Note the use of the generic name + * FIDA_JTIMES below. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "fida.h" /* actual fn. names, prototypes and global vars.*/ +#include "ida_impl.h" /* definition of IDAMem type */ + +#include + +/*************************************************/ + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + + extern void FIDA_JTIMES(realtype*, realtype*, realtype*, /* T, Y, YP */ + realtype*, realtype*, realtype*, /* R, V, FJV */ + realtype*, realtype*, realtype*, /* CJ, EWT, H */ + long int*, realtype*, /* IPAR, RPAR */ + realtype*, realtype*, /* WK1, WK2 */ + int*); /* IER */ + +#ifdef __cplusplus +} +#endif + +/*************************************************/ + +void FIDA_SPILSSETJAC(int *flag, int *ier) +{ + *ier = 0; + + if (*flag == 0) { + + *ier = IDASpilsSetJacTimesVecFn(IDA_idamem, NULL); + + } else { + + if (F2C_IDA_ewtvec == NULL) { + F2C_IDA_ewtvec = N_VClone(F2C_IDA_vec); + if (F2C_IDA_ewtvec == NULL) { + *ier = -1; + return; + } + } + + *ier = IDASpilsSetJacTimesVecFn(IDA_idamem, FIDAJtimes); + + } + + return; +} + +/*************************************************/ + +int FIDAJtimes(realtype t, N_Vector yy, N_Vector yp, N_Vector rr, + N_Vector v, N_Vector Jv, + realtype c_j, void *user_data, + N_Vector vtemp1, N_Vector vtemp2) +{ + realtype *yy_data, *yp_data, *rr_data, *vdata, *Jvdata, *ewtdata; + realtype *v1data, *v2data; + realtype h; + FIDAUserData IDA_userdata; + int ier; + + /* Initialize all pointers to NULL */ + yy_data = yp_data = rr_data = vdata = Jvdata = ewtdata = NULL; + + /* NOTE: The user-supplied routine should set ier to an + appropriate value, but we preset the value to zero + (meaning SUCCESS) so the user need only reset the + value if an error occurred */ + ier = 0; + + IDAGetErrWeights(IDA_idamem, F2C_IDA_ewtvec); + IDAGetLastStep(IDA_idamem, &h); + + /* Get pointers to vector data */ + yy_data = N_VGetArrayPointer(yy); + yp_data = N_VGetArrayPointer(yp); + rr_data = N_VGetArrayPointer(rr); + ewtdata = N_VGetArrayPointer(F2C_IDA_ewtvec); + vdata = N_VGetArrayPointer(v); + Jvdata = N_VGetArrayPointer(Jv); + v1data = N_VGetArrayPointer(vtemp1); + v2data = N_VGetArrayPointer(vtemp2); + + IDA_userdata = (FIDAUserData) user_data; + + /* Call user-supplied routine */ + FIDA_JTIMES(&t, yy_data, yp_data, rr_data, vdata, Jvdata, + &c_j, ewtdata, &h, + IDA_userdata->ipar, IDA_userdata->rpar, + v1data, v2data, &ier); + + return(ier); +} diff --git a/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidalapack.c b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidalapack.c new file mode 100644 index 0000000..0ba0dfa --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidalapack.c @@ -0,0 +1,53 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.1 $ + * $Date: 2006/11/22 00:12:50 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Fortran/C interface routines for IDA/IDALAPACK. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "fida.h" /* actual function names, prototypes and global vars.*/ +#include "ida_impl.h" /* definition of IDAMem type */ + +#include + +/*************************************************/ + +void FIDA_LAPACKDENSE(int *neq, int *ier) +{ + + *ier = 0; + + *ier = IDALapackDense(IDA_idamem, *neq); + + IDA_ls = IDA_LS_LAPACKDENSE; + + return; +} + +/*************************************************/ + +void FIDA_LAPACKBAND(int *neq, int *mupper, int *mlower, int *ier) +{ + + *ier = 0; + + *ier = IDALapackBand(IDA_idamem, *neq, *mupper, *mlower); + + IDA_ls = IDA_LS_LAPACKBAND; + + return; +} + +/*************************************************/ diff --git a/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidalapband.c b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidalapband.c new file mode 100644 index 0000000..0601cc2 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidalapband.c @@ -0,0 +1,112 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.5 $ + * $Date: 2007/08/21 23:32:13 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Fortran/C interface routines for IDA/IDALAPACK, for the case of + * a user-supplied Jacobian approximation routine. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "fida.h" /* function names, prototypes, global vars.*/ +#include "ida_impl.h" /* definition of IDAMem type */ + +#include + +/*************************************************/ + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + + extern void FIDA_BJAC(int*, int*, int*, int*, + realtype*, realtype*, realtype*, realtype*, + realtype*, realtype*, realtype*, realtype*, + long int*, realtype*, + realtype*, realtype*, realtype*, int*); + +#ifdef __cplusplus +} +#endif + +/*************************************************/ + +void FIDA_BANDSETJAC(int *flag, int *ier) +{ + *ier = 0; + + if (*flag == 0) { + *ier = IDADlsSetBandJacFn(IDA_idamem, NULL); + } else { + if (F2C_IDA_ewtvec == NULL) { + F2C_IDA_ewtvec = N_VClone(F2C_IDA_vec); + if (F2C_IDA_ewtvec == NULL) { + *ier = -1; + return; + } + } + *ier = IDADlsSetBandJacFn(IDA_idamem, FIDABandJac); + } + + return; +} + +/*************************************************/ + +int FIDALapackBandJac(int N, int mupper, int mlower, + realtype t, realtype c_j, + N_Vector yy, N_Vector yp, N_Vector rr, + DlsMat J, void *user_data, + N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3) +{ + realtype *yy_data, *yp_data, *rr_data, *jacdata, *ewtdata, *v1data, *v2data, *v3data; + realtype h; + int eband; + int ier; + FIDAUserData IDA_userdata; + + /* Initialize all pointers to NULL */ + yy_data = yp_data = rr_data = jacdata = ewtdata = NULL; + v1data = v2data = v3data = NULL; + + /* NOTE: The user-supplied routine should set ier to an + appropriate value, but we preset the value to zero + (meaning SUCCESS) so the user need only reset the + value if an error occurred */ + ier = 0; + + IDAGetErrWeights(IDA_idamem, F2C_IDA_ewtvec); + IDAGetLastStep(IDA_idamem, &h); + + /* Get pointers to vector data */ + yy_data = N_VGetArrayPointer(yy); + yp_data = N_VGetArrayPointer(yp); + rr_data = N_VGetArrayPointer(rr); + ewtdata = N_VGetArrayPointer(F2C_IDA_ewtvec); + v1data = N_VGetArrayPointer(vtemp1); + v2data = N_VGetArrayPointer(vtemp2); + v3data = N_VGetArrayPointer(vtemp3); + + eband = (J->s_mu) + mlower + 1; + jacdata = BAND_COL(J,0) - mupper; + + IDA_userdata = (FIDAUserData) user_data; + + /* Call user-supplied routine */ + FIDA_BJAC(&N, &mupper, &mlower, &eband, &t, yy_data, yp_data, rr_data, + &c_j, jacdata, ewtdata, &h, + IDA_userdata->ipar, IDA_userdata->rpar, + v1data, v2data, v3data, &ier); + + return(ier); +} diff --git a/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidalapdense.c b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidalapdense.c new file mode 100644 index 0000000..93b1021 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidalapdense.c @@ -0,0 +1,111 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.5 $ + * $Date: 2007/08/21 23:32:13 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Fortran/C interface routines for IDA/IDALAPACK, for the case + * of a user-supplied Jacobian approximation routine. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "fida.h" /* actual function names, prototypes and global vars.*/ +#include "ida_impl.h" /* definition of IDAMem type */ + +#include + +/*************************************************/ + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + + extern void FIDA_DJAC(int*, + realtype*, realtype*, realtype*, realtype*, + realtype*, + realtype*, realtype*, realtype*, + long int*, realtype*, + realtype*, realtype*, realtype*, + int*); + +#ifdef __cplusplus +} +#endif + +/*************************************************/ + +void FIDA_LAPACKDENSESETJAC(int *flag, int *ier) +{ + *ier = 0; + + if (*flag == 0) { + *ier = IDADlsSetDenseJacFn(IDA_idamem, NULL); + } else { + if (F2C_IDA_ewtvec == NULL) { + F2C_IDA_ewtvec = N_VClone(F2C_IDA_vec); + if (F2C_IDA_ewtvec == NULL) { + *ier = -1; + return; + } + } + *ier = IDADlsSetDenseJacFn(IDA_idamem, FIDADenseJac); + } + + return; +} + +/*************************************************/ + +int FIDALapackDenseJac(int N, realtype t, realtype c_j, + N_Vector yy, N_Vector yp, N_Vector rr, + DlsMat Jac, void *user_data, + N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3) +{ + realtype *yy_data, *yp_data, *rr_data, *jacdata, *ewtdata, *v1data, *v2data, *v3data; + realtype h; + int ier; + FIDAUserData IDA_userdata; + + /* Initialize all pointers to NULL */ + yy_data = yp_data = rr_data = jacdata = ewtdata = NULL; + v1data = v2data = v3data = NULL; + + /* NOTE: The user-supplied routine should set ier to an + appropriate value, but we preset the value to zero + (meaning SUCCESS) so the user need only reset the + value if an error occurred */ + ier = 0; + + IDAGetErrWeights(IDA_idamem, F2C_IDA_ewtvec); + IDAGetLastStep(IDA_idamem, &h); + + /* Get pointers to vector data */ + yy_data = N_VGetArrayPointer(yy); + yp_data = N_VGetArrayPointer(yp); + rr_data = N_VGetArrayPointer(rr); + ewtdata = N_VGetArrayPointer(F2C_IDA_ewtvec); + v1data = N_VGetArrayPointer(vtemp1); + v2data = N_VGetArrayPointer(vtemp2); + v3data = N_VGetArrayPointer(vtemp3); + + jacdata = DENSE_COL(Jac,0); + + IDA_userdata = (FIDAUserData) user_data; + + /* Call user-supplied routine*/ + FIDA_DJAC(&N, &t, yy_data, yp_data, rr_data, jacdata, + &c_j, ewtdata, &h, + IDA_userdata->ipar, IDA_userdata->rpar, + v1data, v2data, v3data, &ier); + + return(ier); +} diff --git a/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidapreco.c b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidapreco.c new file mode 100644 index 0000000..9b01417 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidapreco.c @@ -0,0 +1,159 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.3 $ + * $Date: 2007/04/30 19:29:00 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * The C function FIDAPSet is to interface between the IDASPILS + * modules and the user-supplied preconditioner setup routine FIDAPSET. + * Note the use of the generic name FIDA_PSET below. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "fida.h" /* actual fn. names, prototypes and global vars.*/ +#include "ida_impl.h" /* definition of IDAMem type */ + +#include + +/*************************************************/ + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + + extern void FIDA_PSET(realtype*, realtype*, realtype*, realtype*, + realtype*, realtype*, realtype*, + long int*, realtype*, + realtype*, realtype*, realtype*, + int*); + + extern void FIDA_PSOL(realtype*, realtype*, realtype*, realtype*, + realtype*, realtype*, realtype*, realtype*, + realtype*, + long int*, realtype*, + realtype*, int*); + +#ifdef __cplusplus +} +#endif + +/*************************************************/ + +void FIDA_SPILSSETPREC(int *flag, int *ier) +{ + *ier = 0; + + if (*flag == 0) { + + *ier = IDASpilsSetPreconditioner(IDA_idamem, NULL, NULL); + + } else { + + if (F2C_IDA_ewtvec == NULL) { + F2C_IDA_ewtvec = N_VClone(F2C_IDA_vec); + if (F2C_IDA_ewtvec == NULL) { + *ier = -1; + return; + } + } + + *ier = IDASpilsSetPreconditioner(IDA_idamem, (IDASpilsPrecSetupFn) FIDAPSet, + (IDASpilsPrecSolveFn) FIDAPSol); + } + + return; +} + +/*************************************************/ + +int FIDAPSet(realtype t, N_Vector yy, N_Vector yp, N_Vector rr, + realtype c_j, void *user_data, + N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3) +{ + realtype *yy_data, *yp_data, *rr_data, *ewtdata, *v1data, *v2data, *v3data; + realtype h; + int ier; + FIDAUserData IDA_userdata; + + /* Initialize all pointers to NULL */ + yy_data = yp_data = rr_data = ewtdata = NULL; + v1data = v2data = v3data = NULL; + + /* NOTE: The user-supplied routine should set ier to an + appropriate value, but we preset the value to zero + (meaning SUCCESS) so the user need only reset the + value if an error occurred */ + ier = 0; + + IDAGetErrWeights(IDA_idamem, F2C_IDA_ewtvec); + IDAGetLastStep(IDA_idamem, &h); + + /* Get pointers to vector data */ + yy_data = N_VGetArrayPointer(yy); + yp_data = N_VGetArrayPointer(yp); + rr_data = N_VGetArrayPointer(rr); + ewtdata = N_VGetArrayPointer(F2C_IDA_ewtvec); + v1data = N_VGetArrayPointer(vtemp1); + v2data = N_VGetArrayPointer(vtemp2); + v3data = N_VGetArrayPointer(vtemp3); + + IDA_userdata = (FIDAUserData) user_data; + + /* Call user-supplied routine */ + FIDA_PSET(&t, yy_data, yp_data, rr_data, &c_j, ewtdata, &h, + IDA_userdata->ipar, IDA_userdata->rpar, + v1data, v2data, v3data, &ier); + + return(ier); +} + +/*************************************************/ + +int FIDAPSol(realtype t, N_Vector yy, N_Vector yp, N_Vector rr, + N_Vector rvec, N_Vector zvec, + realtype c_j, realtype delta, void *user_data, + N_Vector vtemp1) +{ + realtype *yy_data, *yp_data, *rr_data, *ewtdata, *rdata, *zdata, *v1data; + int ier; + FIDAUserData IDA_userdata; + + /* Initialize all pointers to NULL */ + yy_data = yp_data = rr_data = ewtdata = user_data = zdata = v1data = NULL; + + /* NOTE: The user-supplied routine should set ier to an + appropriate value, but we preset the value to zero + (meaning SUCCESS) so the user need only reset the + value if an error occurred */ + ier = 0; + + IDAGetErrWeights(IDA_idamem, F2C_IDA_ewtvec); + + /* Get pointers to vector data */ + yy_data = N_VGetArrayPointer(yy); + yp_data = N_VGetArrayPointer(yp); + rr_data = N_VGetArrayPointer(rr); + ewtdata = N_VGetArrayPointer(F2C_IDA_ewtvec); + rdata = N_VGetArrayPointer(rvec); + zdata = N_VGetArrayPointer(zvec); + v1data = N_VGetArrayPointer(vtemp1); + + IDA_userdata = (FIDAUserData) user_data; + + /* Call user-supplied routine */ + FIDA_PSOL(&t, yy_data, yp_data, rr_data, rdata, zdata, + &c_j, &delta, ewtdata, + IDA_userdata->ipar, IDA_userdata->rpar, + v1data, &ier); + + return(ier); +} diff --git a/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidaroot.c b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidaroot.c new file mode 100644 index 0000000..0548dbb --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidaroot.c @@ -0,0 +1,88 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.3 $ + * $Date: 2007/04/30 19:29:00 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier and Alan C. Hindmarsh @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * The FIDAROOT module contains the routines necessary to use + * the rootfinding feature of the IDA module and to interface + * with the user-supplied Fortran subroutine. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "fida.h" /* actual function names, prototypes and global vars.*/ +#include "fidaroot.h" /* prototypes of interfaces to IDA */ +#include "ida_impl.h" /* definition of IDAMeme type */ + +/***************************************************************************/ + +/* Prototype of the Fortran routine */ + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + extern void FIDA_ROOTFN(realtype*, /* T */ + realtype*, /* Y */ + realtype*, /* YP */ + realtype*, /* G */ + long int*, /* IPAR */ + realtype*, /* RPAR */ + int*); /* IER */ +#ifdef __cplusplus +} +#endif + +/***************************************************************************/ + +void FIDA_ROOTINIT(int *nrtfn, int *ier) +{ + *ier = IDARootInit(IDA_idamem, *nrtfn, (IDARootFn) FIDArootfunc); + IDA_nrtfn = *nrtfn; + + return; +} + +/***************************************************************************/ + +void FIDA_ROOTINFO(int *nrtfn, int *info, int *ier) +{ + *ier = IDAGetRootInfo(IDA_idamem, info); + return; +} + +/***************************************************************************/ + +void FIDA_ROOTFREE(void) +{ + IDARootInit(IDA_idamem, 0, NULL); + + return; +} + +/***************************************************************************/ + +int FIDArootfunc(realtype t, N_Vector y, N_Vector yp, realtype *gout, + void *user_data) +{ + int ier; + realtype *ydata, *ypdata; + FIDAUserData IDA_userdata; + + ydata = N_VGetArrayPointer(y); + ypdata = N_VGetArrayPointer(yp); + + IDA_userdata = (FIDAUserData) user_data; + + FIDA_ROOTFN(&t, ydata, ypdata, gout, IDA_userdata->ipar, IDA_userdata->rpar, &ier); + + return(ier); +} diff --git a/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidaroot.h b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidaroot.h new file mode 100644 index 0000000..210de4c --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/fcmix/fidaroot.h @@ -0,0 +1,142 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.4 $ + * $Date: 2007/04/30 19:29:00 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier and Alan C. Hindmarsh @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the Fortran interface include file for the rootfinding + * feature of IDA. + * ----------------------------------------------------------------- + */ + +/* + * ============================================================================== + * + * FIDAROOT Interface Package + * + * The FIDAROOT interface package allows programs written in FORTRAN to + * use the rootfinding feature of the IDA solver module. + * + * The user-callable functions constituting the FIDAROOT package are the + * following: FIDAROOTINIT, FIDAROOTINFO, and FIDAROOTFREE. The corresponding + * IDA subroutine called by each interface function is given below. + * + * ------------------ --------------------- + * | FIDAROOT routine | | IDA function called | + * ------------------ --------------------- + * FIDAROOTINIT -> IDARootInit + * FIDAROOTINFO -> IDAGetRootInfo + * FIDAROOTFREE -> IDARootInit + * + * FIDAROOTFN is a user-supplied subroutine defining the functions whose + * roots are sought. + * + * ============================================================================== + * + * Usage of the FIDAROOT Interface Package + * + * 1. In order to use the rootfinding feature of the IDA package the user must + * define the following subroutine: + * + * SUBROUTINE FIDAROOTFN (T, Y, YP, G, IPAR, RPAR, IER) + * DIMENSION Y(*), YP(*), G(*) + * + * The arguments are: + * T = independent variable value t [input] + * Y = dependent variable vector y [input] + * YP = dependent variable derivative vector y' [input] + * G = function values g(t,y,y') [output] + * IPAR, RPAR = user (integer and real) data [input/output] + * IER = return flag (set on 0 if successful, non-zero if an error occurred) + * + * 2. After calling FIDAMALLOC but prior to calling FIDASOLVE, the user must + * allocate and initialize memory for the FIDAROOT module by making the + * following call: + * + * CALL FIDAROOTINIT (NRTFN, IER) + * + * The arguments are: + * NRTFN = total number of root functions [input] + * IER = return completion flag (0 = success, -1 = IDA memory NULL and + * -14 = memory allocation error) [output] + * + * 3. After calling FIDA, to see whether a root was found, test the FIDA + * return flag IER. The value IER = 2 means one or more roots were found. + * + * 4. If a root was found, and if NRTFN > 1, then to determine which root + * functions G(*) were found to have a root, make the following call: + * CALL FIDAROOTINFO (NRTFN, INFO, IER) + * The arguments are: + * NRTFN = total number of root functions [input] + * INFO = integer array of length NRTFN, with values 0 or 1 [output] + * For i = 1,...,NRTFN, G(i) was found to have a root if INFO(i) = 1. + * IER = completion flag (0 = success, negative = failure) + * + * 5. The total number of calls made to the root function (FIDAROOTFN), + * NGE, can be obtained from IOUT(12). + * + * If the FIDA/IDA memory block is reinitialized to solve a different + * problem via a call to FIDAREINIT, then the counter variable NGE is cleared + * (reset to zero). + * + * 6. To free the memory resources allocated by a prior call to FIDAROOTINIT, + * make the following call: + * CALL FIDAROOTFREE + * See the IDA documentation for additional information. + * + * ============================================================================== + */ + +#ifndef _FIDAROOT_H +#define _FIDAROOT_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +/* header files */ + +#include /* definition of type N_Vector */ +#include /* definition of SUNDIALS type realtype */ + +/* Definitions of interface function names */ + +#if defined(F77_FUNC) + +#define FIDA_ROOTINIT F77_FUNC(fidarootinit, FIDAROOTINIT) +#define FIDA_ROOTINFO F77_FUNC(fidarootinfo, FIDAROOTINFO) +#define FIDA_ROOTFREE F77_FUNC(fidarootfree, FIDAROOTFREE) +#define FIDA_ROOTFN F77_FUNC(fidarootfn, FIDAROOTFN) + +#else + +#define FIDA_ROOTINIT fidarootinit_ +#define FIDA_ROOTINFO fidarootinfo_ +#define FIDA_ROOTFREE fidarootfree_ +#define FIDA_ROOTFN fidarootfn_ + +#endif + +/* Prototypes of exported function */ + +void FIDA_ROOTINIT(int *nrtfn, int *ier); +void FIDA_ROOTINFO(int *nrtfn, int *info, int *ier); +void FIDA_ROOTFREE(void); + +/* Prototype of function called by IDA module */ + +int FIDArootfunc(realtype t, N_Vector y, N_Vector yp, realtype *gout, + void *user_data); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/odemex/Parser/CVode/ida_src/src/ida/ida.c b/odemex/Parser/CVode/ida_src/src/ida/ida.c new file mode 100644 index 0000000..62f03ff --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/ida.c @@ -0,0 +1,3339 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.22 $ + * $Date: 2009/05/06 22:12:11 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan Hindmarsh, Radu Serban and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the main IDA solver. + * It is independent of the linear solver in use. + * ----------------------------------------------------------------- + * + * EXPORTED FUNCTIONS + * ------------------ + * Creation, allocation and re-initialization functions + * IDACreate + * IDAInit + * IDAReInit + * IDARootInit + * Main solver function + * IDASolve + * Interpolated output and extraction functions + * IDAGetSolution + * Deallocation functions + * IDAFree + * + * PRIVATE FUNCTIONS + * ----------------- + * IDACheckNvector + * Memory allocation/deallocation + * IDAAllocVectors + * IDAFreeVectors + * Initial setup + * IDAInitialSetup + * IDAEwtSet + * IDAEwtSetSS + * IDAEwtSetSV + * Stopping tests + * IDAStopTest1 + * IDAStopTest2 + * Error handler + * IDAHandleFailure + * Main IDAStep function + * IDAStep + * IDASetCoeffs + * Nonlinear solver functions + * IDANls + * IDAPredict + * IDANewtonIter + * Error test + * IDATestError + * IDARestore + * Handler for convergence and/or error test failures + * IDAHandleNFlag + * IDAReset + * Function called after a successful step + * IDACompleteStep + * Norm functions + * IDAWrmsNorm + * Functions for rootfinding + * IDARcheck1 + * IDARcheck2 + * IDARcheck3 + * IDARootfind + * IDA Error message handling functions + * IDAProcessError + * IDAErrHandler + * ----------------------------------------------------------------- + */ + +/* + * ================================================================= + * IMPORTED HEADER FILES + * ================================================================= + */ + +#include +#include +#include +#include + +#include "ida_impl.h" +#include + +/* + * ================================================================= + * MACRO DEFINITIONS + * ================================================================= + */ + +/* Macro: loop */ +#define loop for(;;) + +/* + * ================================================================= + * IDAS PRIVATE CONSTANTS + * ================================================================= + */ + +#define ZERO RCONST(0.0) /* real 0.0 */ +#define HALF RCONST(0.5) /* real 0.5 */ +#define QUARTER RCONST(0.25) /* real 0.25 */ +#define TWOTHIRDS RCONST(0.667) /* real 2/3 */ +#define ONE RCONST(1.0) /* real 1.0 */ +#define ONEPT5 RCONST(1.5) /* real 1.5 */ +#define TWO RCONST(2.0) /* real 2.0 */ +#define FOUR RCONST(4.0) /* real 4.0 */ +#define FIVE RCONST(5.0) /* real 5.0 */ +#define TEN RCONST(10.0) /* real 10.0 */ +#define TWELVE RCONST(12.0) /* real 12.0 */ +#define TWENTY RCONST(20.0) /* real 20.0 */ +#define HUNDRED RCONST(100.0) /* real 100.0 */ +#define PT9 RCONST(0.9) /* real 0.9 */ +#define PT99 RCONST(0.99) /* real 0.99 */ +#define PT1 RCONST(0.1) /* real 0.1 */ +#define PT01 RCONST(0.01) /* real 0.01 */ +#define PT001 RCONST(0.001) /* real 0.001 */ +#define PT0001 RCONST(0.0001) /* real 0.0001 */ + +/* + * ================================================================= + * IDAS ROUTINE-SPECIFIC CONSTANTS + * ================================================================= + */ + +/* + * Control constants for lower-level functions used by IDASolve + * ------------------------------------------------------------ + */ + +/* IDAStep control constants */ + +#define PREDICT_AGAIN 20 + +/* Return values for lower level routines used by IDASolve */ + +#define IDA_RES_RECVR +1 +#define IDA_LSETUP_RECVR +2 +#define IDA_LSOLVE_RECVR +3 + +#define IDA_NCONV_RECVR +4 +#define IDA_CONSTR_RECVR +5 +#define CONTINUE_STEPS +99 + +/* IDACompleteStep constants */ + +#define UNSET -1 +#define LOWER +1 +#define RAISE +2 +#define MAINTAIN +3 + +/* IDATestError constants */ + +#define ERROR_TEST_FAIL +7 + +/* + * Control constants for lower-level rootfinding functions + * ------------------------------------------------------- + */ + +#define RTFOUND +1 +#define CLOSERT +3 + +/* + * Control constants for tolerances + * -------------------------------- + */ + +#define IDA_NN 0 +#define IDA_SS 1 +#define IDA_SV 2 +#define IDA_WF 3 + +/* + * Algorithmic constants + * --------------------- + */ + +#define MXNCF 10 /* max number of convergence failures allowed */ +#define MXNEF 10 /* max number of error test failures allowed */ +#define MAXNH 5 /* max. number of h tries in IC calc. */ +#define MAXNJ 4 /* max. number of J tries in IC calc. */ +#define MAXNI 10 /* max. Newton iterations in IC calc. */ +#define EPCON RCONST(0.33) /* Newton convergence test constant */ + +/* IDANewtonIter constants */ + +#define MAXIT 4 +#define RATEMAX RCONST(0.9) +#define XRATE RCONST(0.25) + +/* + * ================================================================= + * PRIVATE FUNCTION PROTOTYPES + * ================================================================= + */ + +static booleantype IDACheckNvector(N_Vector tmpl); + +/* Memory allocation/deallocation */ + +static booleantype IDAAllocVectors(IDAMem IDA_mem, N_Vector tmpl); +static void IDAFreeVectors(IDAMem IDA_mem); + +/* Initial setup */ + +int IDAInitialSetup(IDAMem IDA_mem); +static int IDAEwtSetSS(IDAMem IDA_mem, N_Vector ycur, N_Vector weight); +static int IDAEwtSetSV(IDAMem IDA_mem, N_Vector ycur, N_Vector weight); + +/* Main IDAStep function */ + +static int IDAStep(IDAMem IDA_mem); + +/* Function called at beginning of step */ + +static void IDASetCoeffs(IDAMem IDA_mem, realtype *ck); + +/* Nonlinear solver functions */ + +static void IDAPredict(IDAMem IDA_mem); +static int IDANls(IDAMem IDA_mem); +static int IDANewtonIter(IDAMem IDA_mem); + +/* Error test */ + +static int IDATestError(IDAMem IDA_mem, realtype ck, + realtype *err_k, realtype *err_km1); + +/* Handling of convergence and/or error test failures */ + +static void IDARestore(IDAMem IDA_mem, realtype saved_t); +static int IDAHandleNFlag(IDAMem IDA_mem, int nflag, realtype err_k, realtype err_km1, + long int *ncfnPtr, int *ncfPtr, long int *netfPtr, int *nefPtr); +static void IDAReset(IDAMem IDA_mem); + +/* Function called after a successful step */ + +static void IDACompleteStep(IDAMem IDA_mem, realtype err_k, realtype err_km1); + +/* Stopping tests and failure handling */ + +static int IDAStopTest1(IDAMem IDA_mem, realtype tout,realtype *tret, + N_Vector yret, N_Vector ypret, int itask); +static int IDAStopTest2(IDAMem IDA_mem, realtype tout, realtype *tret, + N_Vector yret, N_Vector ypret, int itask); +static int IDAHandleFailure(IDAMem IDA_mem, int sflag); + +/* Functions for rootfinding */ + +static int IDARcheck1(IDAMem IDA_mem); +static int IDARcheck2(IDAMem IDA_mem); +static int IDARcheck3(IDAMem IDA_mem); +static int IDARootfind(IDAMem IDA_mem); + +/* Norm functions */ + +realtype IDAWrmsNorm(IDAMem IDA_mem, N_Vector x, N_Vector w, booleantype mask); + +/* + * ================================================================= + * EXPORTED FUNCTIONS IMPLEMENTATION + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Creation, allocation and re-initialization functions + * ----------------------------------------------------------------- + */ + +/* + * IDACreate + * + * IDACreate creates an internal memory block for a problem to + * be solved by IDA. + * If successful, IDACreate returns a pointer to the problem memory. + * This pointer should be passed to IDAInit. + * If an initialization error occurs, IDACreate prints an error + * message to standard err and returns NULL. + */ + +void *IDACreate(void) +{ + IDAMem IDA_mem; + + IDA_mem = NULL; + IDA_mem = (IDAMem) malloc(sizeof(struct IDAMemRec)); + if (IDA_mem == NULL) { + IDAProcessError(NULL, 0, "IDA", "IDACreate", MSG_MEM_FAIL); + return (NULL); + } + + /* Set unit roundoff in IDA_mem */ + IDA_mem->ida_uround = UNIT_ROUNDOFF; + + /* Set default values for integrator optional inputs */ + IDA_mem->ida_res = NULL; + IDA_mem->ida_user_data = NULL; + IDA_mem->ida_itol = IDA_NN; + IDA_mem->ida_user_efun = FALSE; + IDA_mem->ida_efun = NULL; + IDA_mem->ida_edata = NULL; + IDA_mem->ida_ehfun = IDAErrHandler; + IDA_mem->ida_eh_data = IDA_mem; + IDA_mem->ida_errfp = stderr; + IDA_mem->ida_maxord = MAXORD_DEFAULT; + IDA_mem->ida_mxstep = MXSTEP_DEFAULT; + IDA_mem->ida_hmax_inv = HMAX_INV_DEFAULT; + IDA_mem->ida_hin = ZERO; + IDA_mem->ida_epcon = EPCON; + IDA_mem->ida_maxnef = MXNEF; + IDA_mem->ida_maxncf = MXNCF; + IDA_mem->ida_maxcor = MAXIT; + IDA_mem->ida_suppressalg = FALSE; + IDA_mem->ida_id = NULL; + IDA_mem->ida_constraints = NULL; + IDA_mem->ida_constraintsSet = FALSE; + IDA_mem->ida_tstopset = FALSE; + + /* set the saved value maxord_alloc */ + IDA_mem->ida_maxord_alloc = MAXORD_DEFAULT; + + /* Set default values for IC optional inputs */ + IDA_mem->ida_epiccon = PT01 * EPCON; + IDA_mem->ida_maxnh = MAXNH; + IDA_mem->ida_maxnj = MAXNJ; + IDA_mem->ida_maxnit = MAXNI; + IDA_mem->ida_lsoff = FALSE; + IDA_mem->ida_steptol = RPowerR(IDA_mem->ida_uround, TWOTHIRDS); + + /* Initialize lrw and liw */ + IDA_mem->ida_lrw = 25 + 5*MXORDP1; + IDA_mem->ida_liw = 38; + + /* No mallocs have been done yet */ + IDA_mem->ida_VatolMallocDone = FALSE; + IDA_mem->ida_constraintsMallocDone = FALSE; + IDA_mem->ida_idMallocDone = FALSE; + IDA_mem->ida_MallocDone = FALSE; + + /* Return pointer to IDA memory block */ + return((void *)IDA_mem); +} + +/*-----------------------------------------------------------------*/ + +#define lrw (IDA_mem->ida_lrw) +#define liw (IDA_mem->ida_liw) + +/*-----------------------------------------------------------------*/ + +/*-----------------------------------------------------------------*/ +/* Added by Joep Vanlier */ + +int IDASetMaxTime( void *ida_mem, double maxTime ) +{ + IDAMem IDA_mem; + + if (ida_mem == NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDAS", "IDAInit", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + IDA_mem->tMax = maxTime; +} + +/*-----------------------------------------------------------------*/ + +/*-----------------------------------------------------------------*/ + +/* + * IDAInit + * + * IDAInit allocates and initializes memory for a problem. All + * problem specification inputs are checked for errors. If any + * error occurs during initialization, it is reported to the + * error handler function. + */ + +int IDAInit(void *ida_mem, IDAResFn res, + realtype t0, N_Vector yy0, N_Vector yp0) +{ + IDAMem IDA_mem; + booleantype nvectorOK, allocOK; + long int lrw1, liw1; + + /* Check ida_mem */ + + if (ida_mem == NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAInit", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + /* Set max integration time Joep Vanlier */ + + IDA_mem->tMax = DBL_MAX; + + /* Check for legal input parameters */ + + if (yy0 == NULL) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAInit", MSG_Y0_NULL); + return(IDA_ILL_INPUT); + } + + if (yp0 == NULL) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAInit", MSG_YP0_NULL); + return(IDA_ILL_INPUT); + } + + if (res == NULL) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAInit", MSG_RES_NULL); + return(IDA_ILL_INPUT); + } + + /* Test if all required vector operations are implemented */ + + nvectorOK = IDACheckNvector(yy0); + if (!nvectorOK) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAInit", MSG_BAD_NVECTOR); + return(IDA_ILL_INPUT); + } + + /* Set space requirements for one N_Vector */ + + if (yy0->ops->nvspace != NULL) { + N_VSpace(yy0, &lrw1, &liw1); + } else { + lrw1 = 0; + liw1 = 0; + } + IDA_mem->ida_lrw1 = lrw1; + IDA_mem->ida_liw1 = liw1; + + /* Allocate the vectors (using yy0 as a template) */ + + allocOK = IDAAllocVectors(IDA_mem, yy0); + if (!allocOK) { + IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDA", "IDAInit", MSG_MEM_FAIL); + return(IDA_MEM_FAIL); + } + + /* All error checking is complete at this point */ + + /* Copy the input parameters into IDA memory block */ + + IDA_mem->ida_res = res; + IDA_mem->ida_tn = t0; + + /* Set the linear solver addresses to NULL */ + + IDA_mem->ida_linit = NULL; + IDA_mem->ida_lsetup = NULL; + IDA_mem->ida_lsolve = NULL; + IDA_mem->ida_lperf = NULL; + IDA_mem->ida_lfree = NULL; + IDA_mem->ida_lmem = NULL; + + /* Initialize the phi array */ + + N_VScale(ONE, yy0, IDA_mem->ida_phi[0]); + N_VScale(ONE, yp0, IDA_mem->ida_phi[1]); + + /* Initialize all the counters and other optional output values */ + + IDA_mem->ida_nst = 0; + IDA_mem->ida_nre = 0; + IDA_mem->ida_ncfn = 0; + IDA_mem->ida_netf = 0; + IDA_mem->ida_nni = 0; + IDA_mem->ida_nsetups = 0; + + IDA_mem->ida_kused = 0; + IDA_mem->ida_hused = ZERO; + IDA_mem->ida_tolsf = ONE; + + IDA_mem->ida_nge = 0; + + IDA_mem->ida_irfnd = 0; + + /* Initialize root-finding variables */ + + IDA_mem->ida_glo = NULL; + IDA_mem->ida_ghi = NULL; + IDA_mem->ida_grout = NULL; + IDA_mem->ida_iroots = NULL; + IDA_mem->ida_rootdir = NULL; + IDA_mem->ida_gfun = NULL; + IDA_mem->ida_nrtfn = 0; + IDA_mem->ida_gactive = NULL; + IDA_mem->ida_mxgnull = 1; + + /* Initial setup not done yet */ + + IDA_mem->ida_SetupDone = FALSE; + + /* Problem memory has been successfully allocated */ + + IDA_mem->ida_MallocDone = TRUE; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +#define lrw1 (IDA_mem->ida_lrw1) +#define liw1 (IDA_mem->ida_liw1) + +/*-----------------------------------------------------------------*/ + +/* + * IDAReInit + * + * IDAReInit re-initializes IDA's memory for a problem, assuming + * it has already beeen allocated in a prior IDAInit call. + * All problem specification inputs are checked for errors. + * The problem size Neq is assumed to be unchaged since the call + * to IDAInit, and the maximum order maxord must not be larger. + * If any error occurs during reinitialization, it is reported to + * the error handler function. + * The return value is IDA_SUCCESS = 0 if no errors occurred, or + * a negative value otherwise. + */ + +int IDAReInit(void *ida_mem, + realtype t0, N_Vector yy0, N_Vector yp0) +{ + IDAMem IDA_mem; + + /* Check for legal input parameters */ + + if (ida_mem == NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAReInit", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + /* Check if problem was malloc'ed */ + + if (IDA_mem->ida_MallocDone == FALSE) { + IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDA", "IDAReInit", MSG_NO_MALLOC); + return(IDA_NO_MALLOC); + } + + /* Check for legal input parameters */ + + if (yy0 == NULL) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAReInit", MSG_Y0_NULL); + return(IDA_ILL_INPUT); + } + + if (yp0 == NULL) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAReInit", MSG_YP0_NULL); + return(IDA_ILL_INPUT); + } + + /* Copy the input parameters into IDA memory block */ + + IDA_mem->ida_tn = t0; + + /* Initialize the phi array */ + + N_VScale(ONE, yy0, IDA_mem->ida_phi[0]); + N_VScale(ONE, yp0, IDA_mem->ida_phi[1]); + + /* Initialize all the counters and other optional output values */ + + IDA_mem->ida_nst = 0; + IDA_mem->ida_nre = 0; + IDA_mem->ida_ncfn = 0; + IDA_mem->ida_netf = 0; + IDA_mem->ida_nni = 0; + IDA_mem->ida_nsetups = 0; + + IDA_mem->ida_kused = 0; + IDA_mem->ida_hused = ZERO; + IDA_mem->ida_tolsf = ONE; + + IDA_mem->ida_nge = 0; + + IDA_mem->ida_irfnd = 0; + + /* Initial setup not done yet */ + + IDA_mem->ida_SetupDone = FALSE; + + /* Problem has been successfully re-initialized */ + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +/* + * IDASStolerances + * IDASVtolerances + * IDAWFtolerances + * + * These functions specify the integration tolerances. One of them + * MUST be called before the first call to IDA. + * + * IDASStolerances specifies scalar relative and absolute tolerances. + * IDASVtolerances specifies scalar relative tolerance and a vector + * absolute tolerance (a potentially different absolute tolerance + * for each vector component). + * IDAWFtolerances specifies a user-provides function (of type IDAEwtFn) + * which will be called to set the error weight vector. + */ + +int IDASStolerances(void *ida_mem, realtype reltol, realtype abstol) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASStolerances", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + if (IDA_mem->ida_MallocDone == FALSE) { + IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDA", "IDASStolerances", MSG_NO_MALLOC); + return(IDA_NO_MALLOC); + } + + /* Check inputs */ + + if (reltol < ZERO) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASStolerances", MSG_BAD_RTOL); + return(IDA_ILL_INPUT); + } + + if (abstol < ZERO) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASStolerances", MSG_BAD_ATOL); + return(IDA_ILL_INPUT); + } + + /* Copy tolerances into memory */ + + IDA_mem->ida_rtol = reltol; + IDA_mem->ida_Satol = abstol; + + IDA_mem->ida_itol = IDA_SS; + + IDA_mem->ida_user_efun = FALSE; + IDA_mem->ida_efun = IDAEwtSet; + IDA_mem->ida_edata = NULL; /* will be set to ida_mem in InitialSetup; */ + + return(IDA_SUCCESS); +} + + +int IDASVtolerances(void *ida_mem, realtype reltol, N_Vector abstol) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASVtolerances", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + if (IDA_mem->ida_MallocDone == FALSE) { + IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDA", "IDASVtolerances", MSG_NO_MALLOC); + return(IDA_NO_MALLOC); + } + + /* Check inputs */ + + if (reltol < ZERO) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASVtolerances", MSG_BAD_RTOL); + return(IDA_ILL_INPUT); + } + + if (N_VMin(abstol) < ZERO) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASVtolerances", MSG_BAD_ATOL); + return(IDA_ILL_INPUT); + } + + /* Copy tolerances into memory */ + + if ( !(IDA_mem->ida_VatolMallocDone) ) { + IDA_mem->ida_Vatol = N_VClone(IDA_mem->ida_ewt); + lrw += lrw1; + liw += liw1; + IDA_mem->ida_VatolMallocDone = TRUE; + } + + IDA_mem->ida_rtol = reltol; + N_VScale(ONE, abstol, IDA_mem->ida_Vatol); + + IDA_mem->ida_itol = IDA_SV; + + IDA_mem->ida_user_efun = FALSE; + IDA_mem->ida_efun = IDAEwtSet; + IDA_mem->ida_edata = NULL; /* will be set to ida_mem in InitialSetup; */ + + return(IDA_SUCCESS); +} + + +int IDAWFtolerances(void *ida_mem, IDAEwtFn efun) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAWFtolerances", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + if (IDA_mem->ida_MallocDone == FALSE) { + IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDA", "IDAWFtolerances", MSG_NO_MALLOC); + return(IDA_NO_MALLOC); + } + + IDA_mem->ida_itol = IDA_WF; + + IDA_mem->ida_user_efun = TRUE; + IDA_mem->ida_efun = efun; + IDA_mem->ida_edata = NULL; /* will be set to user_data in InitialSetup */ + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +#define gfun (IDA_mem->ida_gfun) +#define glo (IDA_mem->ida_glo) +#define ghi (IDA_mem->ida_ghi) +#define grout (IDA_mem->ida_grout) +#define iroots (IDA_mem->ida_iroots) +#define rootdir (IDA_mem->ida_rootdir) +#define gactive (IDA_mem->ida_gactive) + +/*-----------------------------------------------------------------*/ + +/* + * IDARootInit + * + * IDARootInit initializes a rootfinding problem to be solved + * during the integration of the DAE system. It loads the root + * function pointer and the number of root functions, and allocates + * workspace memory. The return value is IDA_SUCCESS = 0 if no + * errors occurred, or a negative value otherwise. + */ + +int IDARootInit(void *ida_mem, int nrtfn, IDARootFn g) +{ + IDAMem IDA_mem; + int i, nrt; + + /* Check ida_mem pointer */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDARootInit", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + nrt = (nrtfn < 0) ? 0 : nrtfn; + + /* If rerunning IDARootInit() with a different number of root + functions (changing number of gfun components), then free + currently held memory resources */ + if ((nrt != IDA_mem->ida_nrtfn) && (IDA_mem->ida_nrtfn > 0)) { + + free(glo); glo = NULL; + free(ghi); ghi = NULL; + free(grout); grout = NULL; + free(iroots); iroots = NULL; + free(rootdir); iroots = NULL; + free(gactive); gactive = NULL; + + lrw -= 3 * (IDA_mem->ida_nrtfn); + liw -= 3 * (IDA_mem->ida_nrtfn); + + } + + /* If IDARootInit() was called with nrtfn == 0, then set ida_nrtfn to + zero and ida_gfun to NULL before returning */ + if (nrt == 0) { + IDA_mem->ida_nrtfn = nrt; + gfun = NULL; + return(IDA_SUCCESS); + } + + /* If rerunning IDARootInit() with the same number of root functions + (not changing number of gfun components), then check if the root + function argument has changed */ + /* If g != NULL then return as currently reserved memory resources + will suffice */ + if (nrt == IDA_mem->ida_nrtfn) { + if (g != gfun) { + if (g == NULL) { + free(glo); glo = NULL; + free(ghi); ghi = NULL; + free(grout); grout = NULL; + free(iroots); iroots = NULL; + free(rootdir); iroots = NULL; + free(gactive); gactive = NULL; + + lrw -= 3*nrt; + liw -= 3*nrt; + + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDARootInit", MSG_ROOT_FUNC_NULL); + return(IDA_ILL_INPUT); + } + else { + gfun = g; + return(IDA_SUCCESS); + } + } + else return(IDA_SUCCESS); + } + + /* Set variable values in IDA memory block */ + IDA_mem->ida_nrtfn = nrt; + if (g == NULL) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDARootInit", MSG_ROOT_FUNC_NULL); + return(IDA_ILL_INPUT); + } + else gfun = g; + + /* Allocate necessary memory and return */ + glo = NULL; + glo = (realtype *) malloc(nrt*sizeof(realtype)); + if (glo == NULL) { + IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDA", "IDARootInit", MSG_MEM_FAIL); + return(IDA_MEM_FAIL); + } + + ghi = NULL; + ghi = (realtype *) malloc(nrt*sizeof(realtype)); + if (ghi == NULL) { + free(glo); glo = NULL; + IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDA", "IDARootInit", MSG_MEM_FAIL); + return(IDA_MEM_FAIL); + } + + grout = NULL; + grout = (realtype *) malloc(nrt*sizeof(realtype)); + if (grout == NULL) { + free(glo); glo = NULL; + free(ghi); ghi = NULL; + IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDA", "IDARootInit", MSG_MEM_FAIL); + return(IDA_MEM_FAIL); + } + + iroots = NULL; + iroots = (int *) malloc(nrt*sizeof(int)); + if (iroots == NULL) { + free(glo); glo = NULL; + free(ghi); ghi = NULL; + free(grout); grout = NULL; + IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDA", "IDARootInit", MSG_MEM_FAIL); + return(IDA_MEM_FAIL); + } + + rootdir = NULL; + rootdir = (int *) malloc(nrt*sizeof(int)); + if (rootdir == NULL) { + free(glo); glo = NULL; + free(ghi); ghi = NULL; + free(grout); grout = NULL; + free(iroots); iroots = NULL; + IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDA", "IDARootInit", MSG_MEM_FAIL); + return(IDA_MEM_FAIL); + } + + gactive = NULL; + gactive = (booleantype *) malloc(nrt*sizeof(booleantype)); + if (gactive == NULL) { + free(glo); glo = NULL; + free(ghi); ghi = NULL; + free(grout); grout = NULL; + free(iroots); iroots = NULL; + free(rootdir); rootdir = NULL; + IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDA", "IDARootInit", MSG_MEM_FAIL); + return(IDA_MEM_FAIL); + } + + /* Set default values for rootdir (both directions) */ + for(i=0; iida_res) +#define y0 (IDA_mem->ida_y0) +#define yp0 (IDA_mem->ida_yp0) + +#define itol (IDA_mem->ida_itol) +#define rtol (IDA_mem->ida_rtol) +#define Satol (IDA_mem->ida_Satol) +#define Vatol (IDA_mem->ida_Vatol) +#define efun (IDA_mem->ida_efun) +#define edata (IDA_mem->ida_edata) + +#define user_data (IDA_mem->ida_user_data) +#define maxord (IDA_mem->ida_maxord) +#define mxstep (IDA_mem->ida_mxstep) +#define hin (IDA_mem->ida_hin) +#define hmax_inv (IDA_mem->ida_hmax_inv) +#define tstop (IDA_mem->ida_tstop) +#define tstopset (IDA_mem->ida_tstopset) +#define epcon (IDA_mem->ida_epcon) +#define maxnef (IDA_mem->ida_maxnef) +#define maxncf (IDA_mem->ida_maxncf) +#define maxcor (IDA_mem->ida_maxcor) +#define suppressalg (IDA_mem->ida_suppressalg) +#define id (IDA_mem->ida_id) +#define constraints (IDA_mem->ida_constraints) + +#define epiccon (IDA_mem->ida_epiccon) +#define maxnh (IDA_mem->ida_maxnh) +#define maxnj (IDA_mem->ida_maxnj) +#define maxnit (IDA_mem->ida_maxnit) +#define lsoff (IDA_mem->ida_lsoff) +#define steptol (IDA_mem->ida_steptol) + +#define uround (IDA_mem->ida_uround) +#define phi (IDA_mem->ida_phi) +#define ewt (IDA_mem->ida_ewt) +#define yy (IDA_mem->ida_yy) +#define yp (IDA_mem->ida_yp) +#define delta (IDA_mem->ida_delta) +#define mm (IDA_mem->ida_mm) +#define ee (IDA_mem->ida_ee) +#define savres (IDA_mem->ida_savres) +#define tempv1 (IDA_mem->ida_tempv1) +#define tempv2 (IDA_mem->ida_tempv2) +#define kk (IDA_mem->ida_kk) +#define hh (IDA_mem->ida_hh) +#define h0u (IDA_mem->ida_h0u) +#define tn (IDA_mem->ida_tn) +#define tretlast (IDA_mem->ida_tretlast) +#define cj (IDA_mem->ida_cj) +#define cjold (IDA_mem->ida_cjold) +#define cjratio (IDA_mem->ida_cjratio) +#define cjlast (IDA_mem->ida_cjlast) +#define nbacktr (IDA_mem->ida_nbacktr) +#define nst (IDA_mem->ida_nst) +#define nre (IDA_mem->ida_nre) +#define ncfn (IDA_mem->ida_ncfn) +#define netf (IDA_mem->ida_netf) +#define nni (IDA_mem->ida_nni) +#define nsetups (IDA_mem->ida_nsetups) +#define ns (IDA_mem->ida_ns) +#define linit (IDA_mem->ida_linit) +#define lsetup (IDA_mem->ida_lsetup) +#define lsolve (IDA_mem->ida_lsolve) +#define lperf (IDA_mem->ida_lperf) +#define lfree (IDA_mem->ida_lfree) +#define lmem (IDA_mem->ida_lmem) +#define knew (IDA_mem->ida_knew) +#define kused (IDA_mem->ida_kused) +#define hused (IDA_mem->ida_hused) +#define tolsf (IDA_mem->ida_tolsf) +#define phase (IDA_mem->ida_phase) +#define epsNewt (IDA_mem->ida_epsNewt) +#define toldel (IDA_mem->ida_toldel) +#define ss (IDA_mem->ida_ss) +#define rr (IDA_mem->ida_rr) +#define psi (IDA_mem->ida_psi) +#define alpha (IDA_mem->ida_alpha) +#define beta (IDA_mem->ida_beta) +#define sigma (IDA_mem->ida_sigma) +#define gamma (IDA_mem->ida_gamma) +#define setupNonNull (IDA_mem->ida_setupNonNull) +#define constraintsSet (IDA_mem->ida_constraintsSet) +#define nrtfn (IDA_mem->ida_nrtfn) +#define tlo (IDA_mem->ida_tlo) +#define thi (IDA_mem->ida_thi) +#define toutc (IDA_mem->ida_toutc) +#define trout (IDA_mem->ida_trout) +#define ttol (IDA_mem->ida_ttol) +#define taskc (IDA_mem->ida_taskc) +#define irfnd (IDA_mem->ida_irfnd) +#define nge (IDA_mem->ida_nge) + +/* + * ----------------------------------------------------------------- + * Main solver function + * ----------------------------------------------------------------- + */ + +/* + * IDASolve + * + * This routine is the main driver of the IDA package. + * + * It integrates over an independent variable interval defined by the user, + * by calling IDAStep to take internal independent variable steps. + * + * The first time that IDASolve is called for a successfully initialized + * problem, it computes a tentative initial step size. + * + * IDASolve supports two modes, specified by itask: + * In the IDA_NORMAL mode, the solver steps until it passes tout and then + * interpolates to obtain y(tout) and yp(tout). + * In the IDA_ONE_STEP mode, it takes one internal step and returns. + * + * IDASolve returns integer values corresponding to success and failure as below: + * + * successful returns: + * + * IDA_SUCCESS + * IDA_TSTOP_RETURN + * + * failed returns: + * + * IDA_ILL_INPUT + * IDA_TOO_MUCH_WORK + * IDA_MEM_NULL + * IDA_TOO_MUCH_ACC + * IDA_CONV_FAIL + * IDA_LSETUP_FAIL + * IDA_LSOLVE_FAIL + * IDA_CONSTR_FAIL + * IDA_ERR_FAIL + * IDA_REP_RES_ERR + * IDA_RES_FAIL + */ + +int IDASolve(void *ida_mem, realtype tout, realtype *tret, + N_Vector yret, N_Vector ypret, int itask) +{ + long int nstloc; + int sflag, istate, ier, irfndp, ir; + realtype tdist, troundoff, ypnorm, rh, nrm; + IDAMem IDA_mem; + booleantype inactive_roots; + time_t tStart, tEnd; //Added by Joep Vanlier + + /* Check for legal inputs in all cases. */ + + if (ida_mem == NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASolve", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + /* Check if problem was malloc'ed */ + + if (IDA_mem->ida_MallocDone == FALSE) { + IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDA", "IDASolve", MSG_NO_MALLOC); + return(IDA_NO_MALLOC); + } + + /* Check for legal arguments */ + + if (yret == NULL) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_YRET_NULL); + return(IDA_ILL_INPUT); + } + yy = yret; + + if (ypret == NULL) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_YPRET_NULL); + return(IDA_ILL_INPUT); + } + yp = ypret; + + if (tret == NULL) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_TRET_NULL); + return(IDA_ILL_INPUT); + } + + if ((itask != IDA_NORMAL) && (itask != IDA_ONE_STEP)) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_ITASK); + return(IDA_ILL_INPUT); + } + + if (itask == IDA_NORMAL) toutc = tout; + taskc = itask; + + if (nst == 0) { /* This is the first call */ + + /* Check inputs to IDA for correctness and consistency */ + + if (IDA_mem->ida_SetupDone == FALSE) { + ier = IDAInitialSetup(IDA_mem); + if (ier != IDA_SUCCESS) return(IDA_ILL_INPUT); + IDA_mem->ida_SetupDone = TRUE; + } + + /* On first call, check for tout - tn too small, set initial hh, + check for approach to tstop, and scale phi[1] by hh. + Also check for zeros of root function g at and near t0. */ + + tdist = ABS(tout - tn); + if (tdist == ZERO) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_TOO_CLOSE); + return(IDA_ILL_INPUT); + } + troundoff = TWO*uround*(ABS(tn) + ABS(tout)); + if (tdist < troundoff) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_TOO_CLOSE); + return(IDA_ILL_INPUT); + } + + hh = hin; + if ( (hh != ZERO) && ((tout-tn)*hh < ZERO) ) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_HINIT); + return(IDA_ILL_INPUT); + } + + if (hh == ZERO) { + hh = PT001*tdist; + ypnorm = IDAWrmsNorm(IDA_mem, phi[1], ewt, suppressalg); + if (ypnorm > HALF/hh) hh = HALF/ypnorm; + if (tout < tn) hh = -hh; + } + + rh = ABS(hh)*hmax_inv; + if (rh > ONE) hh /= rh; + + if (tstopset) { + if ( (tstop - tn)*hh < ZERO) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TSTOP, tstop, tn); + return(IDA_ILL_INPUT); + } + if ( (tn + hh - tstop)*hh > ZERO) + hh = (tstop - tn)*(ONE-FOUR*uround); + } + + h0u = hh; + kk = 0; kused = 0; /* set in case of an error return before a step */ + + /* Check for exact zeros of the root functions at or near t0. */ + if (nrtfn > 0) { + ier = IDARcheck1(IDA_mem); + if (ier == IDA_RTFUNC_FAIL) { + IDAProcessError(IDA_mem, IDA_RTFUNC_FAIL, "IDA", "IDARcheck1", MSG_RTFUNC_FAILED, tn); + return(IDA_RTFUNC_FAIL); + } + } + + N_VScale(hh, phi[1], phi[1]); /* set phi[1] = hh*y' */ + + /* Set the convergence test constants epsNewt and toldel */ + epsNewt = epcon; + toldel = PT0001 * epsNewt; + + } /* end of first-call block. */ + + /* Call lperf function and set nstloc for later performance testing. */ + + if (lperf != NULL) lperf(IDA_mem, 0); + nstloc = 0; + + /* If not the first call, perform all stopping tests. */ + + if (nst > 0) { + + /* First, check for a root in the last step taken, other than the + last root found, if any. If itask = IDA_ONE_STEP and y(tn) was not + returned because of an intervening root, return y(tn) now. */ + + if (nrtfn > 0) { + + irfndp = irfnd; + + ier = IDARcheck2(IDA_mem); + + if (ier == CLOSERT) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDARcheck2", MSG_CLOSE_ROOTS, tlo); + return(IDA_ILL_INPUT); + } else if (ier == IDA_RTFUNC_FAIL) { + IDAProcessError(IDA_mem, IDA_RTFUNC_FAIL, "IDA", "IDARcheck2", MSG_RTFUNC_FAILED, tlo); + return(IDA_RTFUNC_FAIL); + } else if (ier == RTFOUND) { + tretlast = *tret = tlo; + return(IDA_ROOT_RETURN); + } + + /* If tn is distinct from tretlast (within roundoff), + check remaining interval for roots */ + troundoff = HUNDRED*uround*(ABS(tn) + ABS(hh)); + if ( ABS(tn - tretlast) > troundoff ) { + ier = IDARcheck3(IDA_mem); + if (ier == IDA_SUCCESS) { /* no root found */ + irfnd = 0; + if ((irfndp == 1) && (itask == IDA_ONE_STEP)) { + tretlast = *tret = tn; + ier = IDAGetSolution(IDA_mem, tn, yret, ypret); + return(IDA_SUCCESS); + } + } else if (ier == RTFOUND) { /* a new root was found */ + irfnd = 1; + tretlast = *tret = tlo; + return(IDA_ROOT_RETURN); + } else if (ier == IDA_RTFUNC_FAIL) { /* g failed */ + IDAProcessError(IDA_mem, IDA_RTFUNC_FAIL, "IDA", "IDARcheck3", MSG_RTFUNC_FAILED, tlo); + return(IDA_RTFUNC_FAIL); + } + } + + } /* end of root stop check */ + + + /* Now test for all other stop conditions. */ + + istate = IDAStopTest1(IDA_mem, tout, tret, yret, ypret, itask); + if (istate != CONTINUE_STEPS) return(istate); + } + + /* Looping point for internal steps. */ + time( &tStart ); /* Added by J. Vanlier */ + + loop { + + time( &tEnd ); /* Added by J. Vanlier */ + if ( difftime( tEnd, tStart ) > IDA_mem->tMax ) { /* Added by Joep Vanlier */ + fprintf(stderr, "Simulation time exceeded: t=%e", tn ); + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_MAX_STEPS, tn); + istate = IDA_TOO_MUCH_WORK; + tretlast = *tret = tn; + break; + } + + /* Check for too many steps taken. */ + + if ( (mxstep>0) && (nstloc >= mxstep) ) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_MAX_STEPS, tn); + istate = IDA_TOO_MUCH_WORK; + *tret = tretlast = tn; + break; /* Here yy=yret and yp=ypret already have the current solution. */ + } + + /* Call lperf to generate warnings of poor performance. */ + + if (lperf != NULL) lperf(IDA_mem, 1); + + /* Reset and check ewt (if not first call). */ + + if (nst > 0) { + + ier = efun(phi[0], ewt, edata); + + if (ier != 0) { + + if (itol == IDA_WF) + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_EWT_NOW_FAIL, tn); + else + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_EWT_NOW_BAD, tn); + + istate = IDA_ILL_INPUT; + ier = IDAGetSolution(IDA_mem, tn, yret, ypret); + *tret = tretlast = tn; + break; + + } + + } + + /* Check for too much accuracy requested. */ + + nrm = IDAWrmsNorm(IDA_mem, phi[0], ewt, suppressalg); + tolsf = uround * nrm; + if (tolsf > ONE) { + tolsf *= TEN; + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_TOO_MUCH_ACC, tn); + istate = IDA_TOO_MUCH_ACC; + *tret = tretlast = tn; + if (nst > 0) ier = IDAGetSolution(IDA_mem, tn, yret, ypret); + break; + } + + /* Call IDAStep to take a step. */ + + sflag = IDAStep(IDA_mem); + + /* Process all failed-step cases, and exit loop. */ + + if (sflag != IDA_SUCCESS) { + istate = IDAHandleFailure(IDA_mem, sflag); + *tret = tretlast = tn; + ier = IDAGetSolution(IDA_mem, tn, yret, ypret); + break; + } + + nstloc++; + + /* After successful step, check for stop conditions; continue or break. */ + + /* First check for root in the last step taken. */ + + if (nrtfn > 0) { + + ier = IDARcheck3(IDA_mem); + + if (ier == RTFOUND) { /* A new root was found */ + irfnd = 1; + istate = IDA_ROOT_RETURN; + tretlast = *tret = tlo; + break; + } else if (ier == IDA_RTFUNC_FAIL) { /* g failed */ + IDAProcessError(IDA_mem, IDA_RTFUNC_FAIL, "IDA", "IDARcheck3", MSG_RTFUNC_FAILED, tlo); + istate = IDA_RTFUNC_FAIL; + break; + } + + /* If we are at the end of the first step and we still have + * some event functions that are inactive, issue a warning + * as this may indicate a user error in the implementation + * of the root function. */ + + if (nst==1) { + inactive_roots = FALSE; + for (ir=0; irida_mxgnull > 0) && inactive_roots) { + IDAProcessError(IDA_mem, IDA_WARNING, "IDAS", "IDASolve", MSG_INACTIVE_ROOTS); + } + } + + } + + /* Now check all other stop conditions. */ + + istate = IDAStopTest2(IDA_mem, tout, tret, yret, ypret, itask); + if (istate != CONTINUE_STEPS) break; + + } /* End of step loop */ + + return(istate); +} + +/* + * ----------------------------------------------------------------- + * Interpolated output + * ----------------------------------------------------------------- + */ + +/* + * IDAGetSolution + * + * This routine evaluates y(t) and y'(t) as the value and derivative of + * the interpolating polynomial at the independent variable t, and stores + * the results in the vectors yret and ypret. It uses the current + * independent variable value, tn, and the method order last used, kused. + * This function is called by IDASolve with t = tout, t = tn, or t = tstop. + * + * If kused = 0 (no step has been taken), or if t = tn, then the order used + * here is taken to be 1, giving yret = phi[0], ypret = phi[1]/psi[0]. + * + * The return values are: + * IDA_SUCCESS if t is legal, or + * IDA_BAD_T if t is not within the interval of the last step taken. + */ + +int IDAGetSolution(void *ida_mem, realtype t, N_Vector yret, N_Vector ypret) +{ + IDAMem IDA_mem; + realtype tfuzz, tp, delt, c, d, gam; + int j, kord; + + if (ida_mem == NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetSolution", MSG_NO_MEM); + return (IDA_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + /* Check t for legality. Here tn - hused is t_{n-1}. */ + + tfuzz = HUNDRED * uround * (ABS(tn) + ABS(hh)); + if (hh < ZERO) tfuzz = - tfuzz; + tp = tn - hused - tfuzz; + if ((t - tp)*hh < ZERO) { + IDAProcessError(IDA_mem, IDA_BAD_T, "IDA", "IDAGetSolution", MSG_BAD_T, t, tn-hused, tn); + return(IDA_BAD_T); + } + + /* Initialize yret = phi[0], ypret = 0, and kord = (kused or 1). */ + + N_VScale (ONE, phi[0], yret); + N_VConst (ZERO, ypret); + kord = kused; + if (kused == 0) kord = 1; + + /* Accumulate multiples of columns phi[j] into yret and ypret. */ + + delt = t - tn; + c = ONE; d = ZERO; + gam = delt/psi[0]; + for (j=1; j <= kord; j++) { + d = d*gam + c/psi[j-1]; + c = c*gam; + gam = (delt + psi[j-1])/psi[j]; + N_VLinearSum(ONE, yret, c, phi[j], yret); + N_VLinearSum(ONE, ypret, d, phi[j], ypret); + } + return(IDA_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * Deallocation function + * ----------------------------------------------------------------- + */ + +/* + * IDAFree + * + * This routine frees the problem memory allocated by IDAInit + * Such memory includes all the vectors allocated by IDAAllocVectors, + * and the memory lmem for the linear solver (deallocated by a call + * to lfree). + */ + +void IDAFree(void **ida_mem) +{ + IDAMem IDA_mem; + + if (*ida_mem == NULL) return; + + IDA_mem = (IDAMem) (*ida_mem); + + IDAFreeVectors(IDA_mem); + + if (lfree != NULL) lfree(IDA_mem); + + if (nrtfn > 0) { + free(glo); glo = NULL; + free(ghi); ghi = NULL; + free(grout); grout = NULL; + free(iroots); iroots = NULL; + free(rootdir); rootdir = NULL; + free(gactive); gactive = NULL; + } + + free(*ida_mem); + *ida_mem = NULL; +} + +/* + * ================================================================= + * PRIVATE FUNCTIONS + * ================================================================= + */ + +/* + * IDACheckNvector + * + * This routine checks if all required vector operations are present. + * If any of them is missing it returns FALSE. + */ + +static booleantype IDACheckNvector(N_Vector tmpl) +{ + if ((tmpl->ops->nvclone == NULL) || + (tmpl->ops->nvdestroy == NULL) || + (tmpl->ops->nvlinearsum == NULL) || + (tmpl->ops->nvconst == NULL) || + (tmpl->ops->nvprod == NULL) || + (tmpl->ops->nvscale == NULL) || + (tmpl->ops->nvabs == NULL) || + (tmpl->ops->nvinv == NULL) || + (tmpl->ops->nvaddconst == NULL) || + (tmpl->ops->nvwrmsnorm == NULL) || + (tmpl->ops->nvmin == NULL)) + return(FALSE); + else + return(TRUE); +} + +/* + * ----------------------------------------------------------------- + * Memory allocation/deallocation + * ----------------------------------------------------------------- + */ + +/* + * IDAAllocVectors + * + * This routine allocates the IDA vectors ewt, tempv1, tempv2, and + * phi[0], ..., phi[maxord]. + * If all memory allocations are successful, IDAAllocVectors returns + * TRUE. Otherwise all allocated memory is freed and IDAAllocVectors + * returns FALSE. + * This routine also sets the optional outputs lrw and liw, which are + * (respectively) the lengths of the real and integer work spaces + * allocated here. + */ + +static booleantype IDAAllocVectors(IDAMem IDA_mem, N_Vector tmpl) +{ + int i, j, maxcol; + + /* Allocate ewt, ee, delta, tempv1, tempv2 */ + + ewt = N_VClone(tmpl); + if (ewt == NULL) return(FALSE); + + ee = N_VClone(tmpl); + if (ee == NULL) { + N_VDestroy(ewt); + return(FALSE); + } + + delta = N_VClone(tmpl); + if (delta == NULL) { + N_VDestroy(ewt); + N_VDestroy(ee); + return(FALSE); + } + + tempv1 = N_VClone(tmpl); + if (tempv1 == NULL) { + N_VDestroy(ewt); + N_VDestroy(ee); + N_VDestroy(delta); + return(FALSE); + } + + tempv2= N_VClone(tmpl); + if (tempv2 == NULL) { + N_VDestroy(ewt); + N_VDestroy(ee); + N_VDestroy(delta); + N_VDestroy(tempv1); + return(FALSE); + } + + savres = tempv1; + + /* Allocate phi[0] ... phi[maxord]. Make sure phi[2] and phi[3] are + allocated (for use as temporary vectors), regardless of maxord. */ + + maxcol = MAX(maxord,3); + for (j=0; j <= maxcol; j++) { + phi[j] = N_VClone(tmpl); + if (phi[j] == NULL) { + N_VDestroy(ewt); + N_VDestroy(ee); + N_VDestroy(delta); + N_VDestroy(tempv1); + N_VDestroy(tempv2); + for (i=0; i < j; i++) N_VDestroy(phi[i]); + return(FALSE); + } + } + + /* Update solver workspace lengths */ + lrw += (maxcol + 6)*lrw1; + liw += (maxcol + 6)*liw1; + + /* Store the value of maxord used here */ + IDA_mem->ida_maxord_alloc = maxord; + + return(TRUE); +} + +/* + * IDAfreeVectors + * + * This routine frees the IDA vectors allocated for IDA. + */ + +static void IDAFreeVectors(IDAMem IDA_mem) +{ + int j, maxcol; + + N_VDestroy(ewt); + N_VDestroy(ee); + N_VDestroy(delta); + N_VDestroy(tempv1); + N_VDestroy(tempv2); + maxcol = MAX(IDA_mem->ida_maxord_alloc,3); + for(j=0; j <= maxcol; j++) N_VDestroy(phi[j]); + + lrw -= (maxcol + 6)*lrw1; + liw -= (maxcol + 6)*liw1; + + if (IDA_mem->ida_VatolMallocDone) { + N_VDestroy(Vatol); + lrw -= lrw1; + liw -= liw1; + } + + if (IDA_mem->ida_constraintsMallocDone) { + N_VDestroy(constraints); + lrw -= lrw1; + liw -= liw1; + } + + if (IDA_mem->ida_idMallocDone) { + N_VDestroy(id); + lrw -= lrw1; + liw -= liw1; + } + +} + +/* + * ----------------------------------------------------------------- + * Initial setup + * ----------------------------------------------------------------- + */ + +/* + * IDAInitialSetup + * + * This routine is called by IDASolve once at the first step. + * It performs all checks on optional inputs and inputs to + * IDAInit/IDAReInit that could not be done before. + * + * If no merror is encountered, IDAInitialSetup returns IDA_SUCCESS. + * Otherwise, it returns an error flag and reported to the error + * handler function. + */ + +int IDAInitialSetup(IDAMem IDA_mem) +{ + booleantype conOK; + int ier; + + /* Test for more vector operations, depending on options */ + if (suppressalg) + if (id->ops->nvwrmsnormmask == NULL) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAInitialSetup", MSG_BAD_NVECTOR); + return(IDA_ILL_INPUT); + } + + /* Test id vector for legality */ + if (suppressalg && (id==NULL)){ + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAInitialSetup", MSG_MISSING_ID); + return(IDA_ILL_INPUT); + } + + /* Did the user specify tolerances? */ + if (itol == IDA_NN) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAInitialSetup", MSG_NO_TOLS); + return(IDA_ILL_INPUT); + } + + /* Set data for efun */ + if (IDA_mem->ida_user_efun) edata = user_data; + else edata = IDA_mem; + + /* Initial error weight vector */ + ier = efun(phi[0], ewt, edata); + if (ier != 0) { + if (itol == IDA_WF) + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAInitialSetup", MSG_FAIL_EWT); + else + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAInitialSetup", MSG_BAD_EWT); + return(IDA_ILL_INPUT); + } + + /* Check to see if y0 satisfies constraints. */ + if (constraintsSet) { + conOK = N_VConstrMask(constraints, phi[0], tempv2); + if (!conOK) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAInitialSetup", MSG_Y0_FAIL_CONSTR); + return(IDA_ILL_INPUT); + } + } + + /* Check that lsolve exists and call linit function if it exists. */ + if (lsolve == NULL) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAInitialSetup", MSG_LSOLVE_NULL); + return(IDA_ILL_INPUT); + } + + if (linit != NULL) { + ier = linit(IDA_mem); + if (ier != 0) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAInitialSetup", MSG_LINIT_FAIL); + return(IDA_LINIT_FAIL); + } + } + + return(IDA_SUCCESS); +} + +/* + * IDAEwtSet + * + * This routine is responsible for loading the error weight vector + * ewt, according to itol, as follows: + * (1) ewt[i] = 1 / (rtol * ABS(ycur[i]) + atol), i=0,...,Neq-1 + * if itol = IDA_SS + * (2) ewt[i] = 1 / (rtol * ABS(ycur[i]) + atol[i]), i=0,...,Neq-1 + * if itol = IDA_SV + * + * IDAEwtSet returns 0 if ewt is successfully set as above to a + * positive vector and -1 otherwise. In the latter case, ewt is + * considered undefined. + * + * All the real work is done in the routines IDAEwtSetSS, IDAEwtSetSV. + */ + +int IDAEwtSet(N_Vector ycur, N_Vector weight, void *data) +{ + IDAMem IDA_mem; + int flag = 0; + + /* data points to IDA_mem here */ + + IDA_mem = (IDAMem) data; + + switch(itol) { + case IDA_SS: + flag = IDAEwtSetSS(IDA_mem, ycur, weight); + break; + case IDA_SV: + flag = IDAEwtSetSV(IDA_mem, ycur, weight); + break; + } + return(flag); +} + +/* + * IDAEwtSetSS + * + * This routine sets ewt as decribed above in the case itol=IDA_SS. + * It tests for non-positive components before inverting. IDAEwtSetSS + * returns 0 if ewt is successfully set to a positive vector + * and -1 otherwise. In the latter case, ewt is considered + * undefined. + */ + +static int IDAEwtSetSS(IDAMem IDA_mem, N_Vector ycur, N_Vector weight) +{ + N_VAbs(ycur, tempv1); + N_VScale(rtol, tempv1, tempv1); + N_VAddConst(tempv1, Satol, tempv1); + if (N_VMin(tempv1) <= ZERO) return(-1); + N_VInv(tempv1, weight); + return(0); +} + +/* + * IDAEwtSetSV + * + * This routine sets ewt as decribed above in the case itol=IDA_SV. + * It tests for non-positive components before inverting. IDAEwtSetSV + * returns 0 if ewt is successfully set to a positive vector + * and -1 otherwise. In the latter case, ewt is considered + * undefined. + */ + +static int IDAEwtSetSV(IDAMem IDA_mem, N_Vector ycur, N_Vector weight) +{ + N_VAbs(ycur, tempv1); + N_VLinearSum(rtol, tempv1, ONE, Vatol, tempv1); + if (N_VMin(tempv1) <= ZERO) return(-1); + N_VInv(tempv1, weight); + return(0); +} + +/* + * ----------------------------------------------------------------- + * Stopping tests + * ----------------------------------------------------------------- + */ + +/* + * IDAStopTest1 + * + * This routine tests for stop conditions before taking a step. + * The tests depend on the value of itask. + * The variable tretlast is the previously returned value of tret. + * + * The return values are: + * CONTINUE_STEPS if no stop conditions were found + * IDA_SUCCESS for a normal return to the user + * IDA_TSTOP_RETURN for a tstop-reached return to the user + * IDA_ILL_INPUT for an illegal-input return to the user + * + * In the tstop cases, this routine may adjust the stepsize hh to cause + * the next step to reach tstop exactly. + */ + +static int IDAStopTest1(IDAMem IDA_mem, realtype tout, realtype *tret, + N_Vector yret, N_Vector ypret, int itask) +{ + int ier; + realtype troundoff; + + switch (itask) { + + case IDA_NORMAL: + + if (tstopset) { + /* Test for tn past tstop, tn = tretlast, tn past tout, tn near tstop. */ + if ( (tn - tstop)*hh > ZERO) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TSTOP, tstop, tn); + return(IDA_ILL_INPUT); + } + } + + /* Test for tout = tretlast, and for tn past tout. */ + if (tout == tretlast) { + *tret = tretlast = tout; + return(IDA_SUCCESS); + } + if ((tn - tout)*hh >= ZERO) { + ier = IDAGetSolution(IDA_mem, tout, yret, ypret); + if (ier != IDA_SUCCESS) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TOUT, tout); + return(IDA_ILL_INPUT); + } + *tret = tretlast = tout; + return(IDA_SUCCESS); + } + + if (tstopset) { + troundoff = HUNDRED*uround*(ABS(tn) + ABS(hh)); + if (ABS(tn - tstop) <= troundoff) { + ier = IDAGetSolution(IDA_mem, tstop, yret, ypret); + if (ier != IDA_SUCCESS) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TSTOP, tstop, tn); + return(IDA_ILL_INPUT); + } + *tret = tretlast = tstop; + tstopset = FALSE; + return(IDA_TSTOP_RETURN); + } + if ((tn + hh - tstop)*hh > ZERO) + hh = (tstop - tn)*(ONE-FOUR*uround); + } + + return(CONTINUE_STEPS); + + case IDA_ONE_STEP: + + if (tstopset) { + /* Test for tn past tstop, tn past tretlast, and tn near tstop. */ + if ((tn - tstop)*hh > ZERO) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TSTOP, tstop, tn); + return(IDA_ILL_INPUT); + } + } + + /* Test for tn past tretlast. */ + if ((tn - tretlast)*hh > ZERO) { + ier = IDAGetSolution(IDA_mem, tn, yret, ypret); + *tret = tretlast = tn; + return(IDA_SUCCESS); + } + + if (tstopset) { + troundoff = HUNDRED*uround*(ABS(tn) + ABS(hh)); + if (ABS(tn - tstop) <= troundoff) { + ier = IDAGetSolution(IDA_mem, tstop, yret, ypret); + if (ier != IDA_SUCCESS) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TSTOP, tstop, tn); + return(IDA_ILL_INPUT); + } + *tret = tretlast = tstop; + tstopset = FALSE; + return(IDA_TSTOP_RETURN); + } + if ((tn + hh - tstop)*hh > ZERO) + hh = (tstop - tn)*(ONE-FOUR*uround); + } + + return(CONTINUE_STEPS); + + } + return(-99); +} + +/* + * IDAStopTest2 + * + * This routine tests for stop conditions after taking a step. + * The tests depend on the value of itask. + * + * The return values are: + * CONTINUE_STEPS if no stop conditions were found + * IDA_SUCCESS for a normal return to the user + * IDA_TSTOP_RETURN for a tstop-reached return to the user + * + * In the two cases with tstop, this routine may reset the stepsize hh + * to cause the next step to reach tstop exactly. + * + * In the two cases with ONE_STEP mode, no interpolation to tn is needed + * because yret and ypret already contain the current y and y' values. + * + * Note: No test is made for an error return from IDAGetSolution here, + * because the same test was made prior to the step. + */ + +static int IDAStopTest2(IDAMem IDA_mem, realtype tout, realtype *tret, + N_Vector yret, N_Vector ypret, int itask) +{ + int ier; + realtype troundoff; + + switch (itask) { + + case IDA_NORMAL: + + /* Test for tn past tout. */ + if ((tn - tout)*hh >= ZERO) { + ier = IDAGetSolution(IDA_mem, tout, yret, ypret); + *tret = tretlast = tout; + return(IDA_SUCCESS); + } + + if (tstopset) { + /* Test for tn at tstop and for tn near tstop */ + troundoff = HUNDRED*uround*(ABS(tn) + ABS(hh)); + if (ABS(tn - tstop) <= troundoff) { + ier = IDAGetSolution(IDA_mem, tstop, yret, ypret); + *tret = tretlast = tstop; + tstopset = FALSE; + return(IDA_TSTOP_RETURN); + } + if ((tn + hh - tstop)*hh > ZERO) + hh = (tstop - tn)*(ONE-FOUR*uround); + } + + return(CONTINUE_STEPS); + + case IDA_ONE_STEP: + + if (tstopset) { + /* Test for tn at tstop and for tn near tstop */ + troundoff = HUNDRED*uround*(ABS(tn) + ABS(hh)); + if (ABS(tn - tstop) <= troundoff) { + ier = IDAGetSolution(IDA_mem, tstop, yret, ypret); + *tret = tretlast = tstop; + tstopset = FALSE; + return(IDA_TSTOP_RETURN); + } + if ((tn + hh - tstop)*hh > ZERO) + hh = (tstop - tn)*(ONE-FOUR*uround); + } + + *tret = tretlast = tn; + return(IDA_SUCCESS); + + } + return -99; +} + +/* + * ----------------------------------------------------------------- + * Error handler + * ----------------------------------------------------------------- + */ + +/* + * IDAHandleFailure + * + * This routine prints error messages for all cases of failure by + * IDAStep. It returns to IDASolve the value that it is to return to + * the user. + */ + +static int IDAHandleFailure(IDAMem IDA_mem, int sflag) +{ + /* Depending on sflag, print error message and return error flag */ + switch (sflag) { + + case IDA_ERR_FAIL: + IDAProcessError(IDA_mem, IDA_ERR_FAIL, "IDA", "IDASolve", MSG_ERR_FAILS, tn, hh); + return(IDA_ERR_FAIL); + + case IDA_CONV_FAIL: + IDAProcessError(IDA_mem, IDA_CONV_FAIL, "IDA", "IDASolve", MSG_CONV_FAILS, tn, hh); + return(IDA_CONV_FAIL); + + case IDA_LSETUP_FAIL: + IDAProcessError(IDA_mem, IDA_LSETUP_FAIL, "IDA", "IDASolve", MSG_SETUP_FAILED, tn); + return(IDA_LSETUP_FAIL); + + case IDA_LSOLVE_FAIL: + IDAProcessError(IDA_mem, IDA_LSOLVE_FAIL, "IDA", "IDASolve", MSG_SOLVE_FAILED, tn); + return(IDA_LSOLVE_FAIL); + + case IDA_REP_RES_ERR: + IDAProcessError(IDA_mem, IDA_REP_RES_ERR, "IDA", "IDASolve", MSG_REP_RES_ERR, tn); + return(IDA_REP_RES_ERR); + + case IDA_RES_FAIL: + IDAProcessError(IDA_mem, IDA_RES_FAIL, "IDA", "IDASolve", MSG_RES_NONRECOV, tn); + return(IDA_RES_FAIL); + + case IDA_CONSTR_FAIL: + IDAProcessError(IDA_mem, IDA_CONSTR_FAIL, "IDA", "IDASolve", MSG_FAILED_CONSTR, tn); + return(IDA_CONSTR_FAIL); + + } + + return -99; +} + +/* + * ----------------------------------------------------------------- + * Main IDAStep function + * ----------------------------------------------------------------- + */ + +/* + * IDAStep + * + * This routine performs one internal IDA step, from tn to tn + hh. + * It calls other routines to do all the work. + * + * It solves a system of differential/algebraic equations of the form + * F(t,y,y') = 0, for one step. In IDA, tt is used for t, + * yy is used for y, and yp is used for y'. The function F is supplied as 'res' + * by the user. + * + * The methods used are modified divided difference, fixed leading + * coefficient forms of backward differentiation formulas. + * The code adjusts the stepsize and order to control the local error per step. + * + * The main operations done here are as follows: + * * initialize various quantities; + * * setting of multistep method coefficients; + * * solution of the nonlinear system for yy at t = tn + hh; + * * deciding on order reduction and testing the local error; + * * attempting to recover from failure in nonlinear solver or error test; + * * resetting stepsize and order for the next step. + * * updating phi and other state data if successful; + * + * On a failure in the nonlinear system solution or error test, the + * step may be reattempted, depending on the nature of the failure. + * + * Variables or arrays (all in the IDAMem structure) used in IDAStep are: + * + * tt -- Independent variable. + * yy -- Solution vector at tt. + * yp -- Derivative of solution vector after successful stelp. + * res -- User-supplied function to evaluate the residual. See the + * description given in file ida.h . + * lsetup -- Routine to prepare for the linear solver call. It may either + * save or recalculate quantities used by lsolve. (Optional) + * lsolve -- Routine to solve a linear system. A prior call to lsetup + * may be required. + * hh -- Appropriate step size for next step. + * ewt -- Vector of weights used in all convergence tests. + * phi -- Array of divided differences used by IDAStep. This array is composed + * of (maxord+1) nvectors (each of size Neq). (maxord+1) is the maximum + * order for the problem, maxord, plus 1. + * + * Return values are: + * IDA_SUCCESS IDA_RES_FAIL LSETUP_ERROR_NONRECVR + * IDA_LSOLVE_FAIL IDA_ERR_FAIL + * IDA_CONSTR_FAIL IDA_CONV_FAIL + * IDA_REP_RES_ERR + */ + +static int IDAStep(IDAMem IDA_mem) +{ + realtype saved_t, ck; + realtype err_k, err_km1; + int ncf, nef; + int nflag, kflag; + + saved_t = tn; + ncf = nef = 0; + + if (nst == ZERO){ + kk = 1; + kused = 0; + hused = ZERO; + psi[0] = hh; + cj = ONE/hh; + phase = 0; + ns = 0; + } + + /* To prevent 'unintialized variable' warnings */ + err_k = ZERO; + err_km1 = ZERO; + + /* Looping point for attempts to take a step */ + + loop { + + /*----------------------- + Set method coefficients + -----------------------*/ + + IDASetCoeffs(IDA_mem, &ck); + + kflag = IDA_SUCCESS; + + /*---------------------------------------------------- + If tn is past tstop (by roundoff), reset it to tstop. + -----------------------------------------------------*/ + + tn = tn + hh; + if (tstopset) { + if ((tn - tstop)*hh > ZERO) tn = tstop; + } + + /*----------------------- + Advance state variables + -----------------------*/ + + /* Nonlinear system solution */ + nflag = IDANls(IDA_mem); + + /* If NLS was successful, perform error test */ + if (nflag == IDA_SUCCESS) + nflag = IDATestError(IDA_mem, ck, &err_k, &err_km1); + + /* Test for convergence or error test failures */ + if (nflag != IDA_SUCCESS) { + + /* restore and decide what to do */ + IDARestore(IDA_mem, saved_t); + kflag = IDAHandleNFlag(IDA_mem, nflag, err_k, err_km1, + &ncfn, &ncf, &netf, &nef); + + /* exit on nonrecoverable failure */ + if (kflag != PREDICT_AGAIN) return(kflag); + + /* recoverable error; predict again */ + if(nst==0) IDAReset(IDA_mem); + continue; + + } + + /* kflag == IDA_SUCCESS */ + break; + + } + + /* Nonlinear system solve and error test were both successful; + update data, and consider change of step and/or order */ + + IDACompleteStep(IDA_mem, err_k, err_km1); + + /* + Rescale ee vector to be the estimated local error + Notes: + (1) altering the value of ee is permissible since + it will be re-initialized to the zero vector by + IDASolve()->IDAStep()->IDANls()->IDANewtonIter() + before it is needed again + (2) the value of ee is only valid if IDAHandleNFlag() + returns either PREDICT_AGAIN or IDA_SUCCESS + */ + + N_VScale(ck, ee, ee); + + return(IDA_SUCCESS); +} + +/* + * IDASetCoeffs + * + * This routine computes the coefficients relevant to the current step. + * The counter ns counts the number of consecutive steps taken at + * constant stepsize h and order k, up to a maximum of k + 2. + * Then the first ns components of beta will be one, and on a step + * with ns = k + 2, the coefficients alpha, etc. need not be reset here. + * Also, IDACompleteStep prohibits an order increase until ns = k + 2. + */ + +static void IDASetCoeffs(IDAMem IDA_mem, realtype *ck) +{ + int i; + realtype temp1, temp2, alpha0, alphas; + + /* Set coefficients for the current stepsize h */ + + if (hh != hused || kk != kused) ns = 0; + ns = MIN(ns+1,kused+2); + if (kk+1 >= ns){ + beta[0] = ONE; + alpha[0] = ONE; + temp1 = hh; + gamma[0] = ZERO; + sigma[0] = ONE; + for(i=1;i<=kk;i++){ + temp2 = psi[i-1]; + psi[i-1] = temp1; + beta[i] = beta[i-1] * psi[i-1] / temp2; + temp1 = temp2 + hh; + alpha[i] = hh / temp1; + sigma[i] = i * sigma[i-1] * alpha[i]; + gamma[i] = gamma[i-1] + alpha[i-1] / hh; + } + psi[kk] = temp1; + } + /* compute alphas, alpha0 */ + alphas = ZERO; + alpha0 = ZERO; + for(i=0;i temp2) callSetup = TRUE;} + {if (cj != cjlast) ss=HUNDRED;} + } + + /* Begin the main loop. This loop is traversed at most twice. + The second pass only occurs when the first pass had a recoverable + failure with old Jacobian data */ + loop{ + + /* Compute predicted values for yy and yp, and compute residual there. */ + IDAPredict(IDA_mem); + + retval = res(tn, yy, yp, delta, user_data); + nre++; + if (retval < 0) return(IDA_RES_FAIL); + if (retval > 0) return(IDA_RES_RECVR); + + /* If indicated, call linear solver setup function and reset parameters. */ + if (callSetup){ + nsetups++; + retval = lsetup(IDA_mem, yy, yp, delta, tempv1, tempv2, tempv3); + cjold = cj; + cjratio = ONE; + ss = TWENTY; + if (retval < 0) return(IDA_LSETUP_FAIL); + if (retval > 0) return(IDA_LSETUP_RECVR); + } + + /* Call the Newton iteration routine. */ + + retval = IDANewtonIter(IDA_mem); + + /* Retry the current step on recoverable failure with old Jacobian data. */ + + tryAgain = (retval>0)&&(setupNonNull) &&(!callSetup); + + if (tryAgain){ + callSetup = TRUE; + continue; + } + else break; + + } /* end of loop */ + + if (retval != IDA_SUCCESS) return(retval); + + /* If otherwise successful, check and enforce inequality constraints. */ + + if (constraintsSet){ /* Check constraints and get mask vector mm, + set where constraints failed */ + constraintsPassed = N_VConstrMask(constraints,yy,mm); + if (constraintsPassed) return(IDA_SUCCESS); + else { + N_VCompare(ONEPT5, constraints, tempv1); + /* a , where a[i] =1. when |c[i]| = 2 , c the vector of constraints */ + N_VProd(tempv1, constraints, tempv1); /* a * c */ + N_VDiv(tempv1, ewt, tempv1); /* a * c * wt */ + N_VLinearSum(ONE, yy, -PT1, tempv1, tempv1);/* y - 0.1 * a * c * wt */ + N_VProd(tempv1, mm, tempv1); /* v = mm*(y-.1*a*c*wt) */ + vnorm = IDAWrmsNorm(IDA_mem, tempv1, ewt, FALSE); /* ||v|| */ + + /* If vector v of constraint corrections is small + in norm, correct and accept this step */ + if (vnorm <= epsNewt){ + N_VLinearSum(ONE, ee, -ONE, tempv1, ee); /* ee <- ee - v */ + return(IDA_SUCCESS); + } + else { + /* Constraints not met -- reduce h by computing rr = h'/h */ + N_VLinearSum(ONE, phi[0], -ONE, yy, tempv1); + N_VProd(mm, tempv1, tempv1); + rr = PT9*N_VMinQuotient(phi[0], tempv1); + rr = MAX(rr,PT1); + return(IDA_CONSTR_RECVR); + } + } + } + return(IDA_SUCCESS); +} + + +/* + * IDAPredict + * + * This routine predicts the new values for vectors yy and yp. + */ + +static void IDAPredict(IDAMem IDA_mem) +{ + int j; + + N_VScale(ONE, phi[0], yy); + N_VConst(ZERO, yp); + + for(j=1; j<=kk; j++) { + N_VLinearSum(ONE, phi[j], ONE, yy, yy); + N_VLinearSum(gamma[j], phi[j], ONE, yp, yp); + } +} + +/* + * IDANewtonIter + * + * This routine performs the Newton iteration. + * It assumes that delta contains the initial residual vector on entry. + * If the iteration succeeds, it returns the value IDA_SUCCESS = 0. + * If not, it returns either: + * a positive value (for a recoverable failure), namely one of: + * IDA_RES_RECVR + * IDA_LSOLVE_RECVR + * IDA_NCONV_RECVR + * or + * a negative value (for a nonrecoverable failure), namely one of: + * IDA_RES_FAIL + * IDA_LSOLVE_FAIL + * + * NOTE: This routine uses N_Vector savres, which is preset to tempv1. + */ + +static int IDANewtonIter(IDAMem IDA_mem) +{ + int mnewt, retval; + realtype delnrm, oldnrm, rate; + + /* Initialize counter mnewt and cumulative correction vector ee. */ + mnewt = 0; + N_VConst(ZERO, ee); + + /* Initialize oldnrm to avoid compiler warning message */ + oldnrm = ZERO; + + /* Looping point for Newton iteration. Break out on any error. */ + loop { + + nni++; + + /* Save a copy of the residual vector in savres. */ + N_VScale(ONE, delta, savres); + + /* Call the lsolve function to get correction vector delta. */ + retval = lsolve(IDA_mem, delta, ewt, yy, yp, savres); + if (retval < 0) return(IDA_LSOLVE_FAIL); + if (retval > 0) return(IDA_LSOLVE_RECVR); + + /* Apply delta to yy, yp, and ee, and get norm(delta). */ + N_VLinearSum(ONE, yy, -ONE, delta, yy); + N_VLinearSum(ONE, ee, -ONE, delta, ee); + N_VLinearSum(ONE, yp, -cj, delta, yp); + delnrm = IDAWrmsNorm(IDA_mem, delta, ewt, FALSE); + + /* Test for convergence, first directly, then with rate estimate. */ + + if (mnewt == 0){ + oldnrm = delnrm; + if (delnrm <= toldel) return(IDA_SUCCESS); + } + else { + rate = RPowerR( delnrm/oldnrm, ONE/mnewt ); + if (rate > RATEMAX) return(IDA_NCONV_RECVR); + ss = rate/(ONE - rate); + } + + if (ss*delnrm <= epsNewt) return(IDA_SUCCESS); + + /* Not yet converged. Increment mnewt and test for max allowed. */ + mnewt++; + if (mnewt >= maxcor) {retval = IDA_NCONV_RECVR; break;} + + /* Call res for new residual and check error flag from res. */ + retval = res(tn, yy, yp, delta, user_data); + nre++; + if (retval < 0) return(IDA_RES_FAIL); + if (retval > 0) return(IDA_RES_RECVR); + + /* Loop for next iteration. */ + + } /* end of Newton iteration loop */ + + /* All error returns exit here. */ + return(retval); + +} + +/* + * ----------------------------------------------------------------- + * Error test + * ----------------------------------------------------------------- + */ + +/* + * IDATestError + * + * This routine estimates errors at orders k, k-1, k-2, decides + * whether or not to suggest an order decrease, and performs + * the local error test. + * + * IDATestError returns either IDA_SUCCESS or ERROR_TEST_FAIL. + */ + +static int IDATestError(IDAMem IDA_mem, realtype ck, + realtype *err_k, realtype *err_km1) +{ + realtype err_km2; /* estimated error at k-2 */ + realtype enorm_k, enorm_km1, enorm_km2; /* error norms */ + realtype terr_k, terr_km1, terr_km2; /* local truncation error norms */ + + /* Compute error for order k. */ + enorm_k = IDAWrmsNorm(IDA_mem, ee, ewt, suppressalg); + *err_k = sigma[kk] * enorm_k; + terr_k = (kk+1) * (*err_k); + + knew = kk; + + if ( kk > 1 ) { + + /* Compute error at order k-1 */ + N_VLinearSum(ONE, phi[kk], ONE, ee, delta); + enorm_km1 = IDAWrmsNorm(IDA_mem, delta, ewt, suppressalg); + *err_km1 = sigma[kk-1] * enorm_km1; + terr_km1 = kk * (*err_km1); + + if ( kk > 2 ) { + + /* Compute error at order k-2 */ + N_VLinearSum(ONE, phi[kk-1], ONE, delta, delta); + enorm_km2 = IDAWrmsNorm(IDA_mem, delta, ewt, suppressalg); + err_km2 = sigma[kk-2] * enorm_km2; + terr_km2 = (kk-1) * err_km2; + + /* Decrease order if errors are reduced */ + if (MAX(terr_km1, terr_km2) <= terr_k) knew = kk - 1; + + } else { + + /* Decrease order to 1 if errors are reduced by at least 1/2 */ + if (terr_km1 <= (HALF * terr_k) ) knew = kk - 1; + + } + + } + + /* Perform error test */ + if (ck * enorm_k > ONE) return(ERROR_TEST_FAIL); + else return(IDA_SUCCESS); +} + +/* + * IDARestore + * + * This routine restores tn, psi, and phi in the event of a failure. + * It changes back phi-star to phi (changed in IDASetCoeffs) + */ + +static void IDARestore(IDAMem IDA_mem, realtype saved_t) +{ + int j; + + tn = saved_t; + + for (j = 1; j <= kk; j++) + psi[j-1] = psi[j] - hh; + + for (j = ns; j <= kk; j++) + N_VScale(ONE/beta[j], phi[j], phi[j]); + +} + +/* + * ----------------------------------------------------------------- + * Handler for convergence and/or error test failures + * ----------------------------------------------------------------- + */ + +/* + * IDAHandleNFlag + * + * This routine handles failures indicated by the input variable nflag. + * Positive values indicate various recoverable failures while negative + * values indicate nonrecoverable failures. This routine adjusts the + * step size for recoverable failures. + * + * Possible nflag values (input): + * + * --convergence failures-- + * IDA_RES_RECVR > 0 + * IDA_LSOLVE_RECVR > 0 + * IDA_CONSTR_RECVR > 0 + * IDA_NCONV_RECVR > 0 + * IDA_RES_FAIL < 0 + * IDA_LSOLVE_FAIL < 0 + * IDA_LSETUP_FAIL < 0 + * + * --error test failure-- + * ERROR_TEST_FAIL > 0 + * + * Possible kflag values (output): + * + * --recoverable-- + * PREDICT_AGAIN + * + * --nonrecoverable-- + * IDA_CONSTR_FAIL + * IDA_REP_RES_ERR + * IDA_ERR_FAIL + * IDA_CONV_FAIL + * IDA_RES_FAIL + * IDA_LSETUP_FAIL + * IDA_LSOLVE_FAIL + */ + +static int IDAHandleNFlag(IDAMem IDA_mem, int nflag, realtype err_k, realtype err_km1, + long int *ncfnPtr, int *ncfPtr, long int *netfPtr, int *nefPtr) +{ + realtype err_knew; + + phase = 1; + + if (nflag != ERROR_TEST_FAIL) { + + /*----------------------- + Nonlinear solver failed + -----------------------*/ + + (*ncfPtr)++; /* local counter for convergence failures */ + (*ncfnPtr)++; /* global counter for convergence failures */ + + if (nflag < 0) { /* nonrecoverable failure */ + + return(nflag); + + } else { /* recoverable failure */ + + /* Reduce step size for a new prediction + Note that if nflag=IDA_CONSTR_RECVR then rr was already set in IDANls */ + if (nflag != IDA_CONSTR_RECVR) rr = QUARTER; + hh *= rr; + + /* Test if there were too many convergence failures */ + if (*ncfPtr < maxncf) return(PREDICT_AGAIN); + else if (nflag == IDA_RES_RECVR) return(IDA_REP_RES_ERR); + else if (nflag == IDA_CONSTR_RECVR) return(IDA_CONSTR_FAIL); + else return(IDA_CONV_FAIL); + } + + } else { + + /*----------------- + Error Test failed + -----------------*/ + + (*nefPtr)++; /* local counter for error test failures */ + (*netfPtr)++; /* global counter for error test failures */ + + if (*nefPtr == 1) { + + /* On first error test failure, keep current order or lower order by one. + Compute new stepsize based on differences of the solution. */ + + err_knew = (kk==knew)? err_k : err_km1; + + kk = knew; + rr = PT9 * RPowerR( TWO * err_knew + PT0001,(-ONE/(kk+1)) ); + rr = MAX(QUARTER, MIN(PT9,rr)); + hh *=rr; + return(PREDICT_AGAIN); + + } else if (*nefPtr == 2) { + + /* On second error test failure, use current order or decrease order by one. + Reduce stepsize by factor of 1/4. */ + + kk = knew; + rr = QUARTER; + hh *= rr; + return(PREDICT_AGAIN); + + } else if (*nefPtr < maxnef) { + + /* On third and subsequent error test failures, set order to 1. + Reduce stepsize by factor of 1/4. */ + kk = 1; + rr = QUARTER; + hh *= rr; + return(PREDICT_AGAIN); + + } else { + + /* Too many error test failures */ + return(IDA_ERR_FAIL); + + } + + } + +} + +/* + * IDAReset + * + * This routine is called only if we need to predict again at the + * very first step. In such a case, reset phi[1] and psi[0]. + */ + +static void IDAReset(IDAMem IDA_mem) +{ + psi[0] = hh; + + N_VScale(rr, phi[1], phi[1]); +} + +/* + * ----------------------------------------------------------------- + * Function called after a successful step + * ----------------------------------------------------------------- + */ + +/* + * IDACompleteStep + * + * This routine completes a successful step. It increments nst, + * saves the stepsize and order used, makes the final selection of + * stepsize and order for the next step, and updates the phi array. + */ + +static void IDACompleteStep(IDAMem IDA_mem, realtype err_k, realtype err_km1) +{ + int j, kdiff, action; + realtype terr_k, terr_km1, terr_kp1; + realtype err_knew, err_kp1; + realtype enorm, tmp, hnew; + + nst++; + kdiff = kk - kused; + kused = kk; + hused = hh; + + if ( (knew == kk-1) || (kk == maxord) ) phase = 1; + + /* For the first few steps, until either a step fails, or the order is + reduced, or the order reaches its maximum, we raise the order and double + the stepsize. During these steps, phase = 0. Thereafter, phase = 1, and + stepsize and order are set by the usual local error algorithm. + + Note that, after the first step, the order is not increased, as not all + of the neccessary information is available yet. */ + + if (phase == 0) { + + if(nst > 1) { + kk++; + hnew = TWO * hh; + if( (tmp = ABS(hnew)*hmax_inv) > ONE ) hnew /= tmp; + hh = hnew; + } + + } else { + + action = UNSET; + + /* Set action = LOWER/MAINTAIN/RAISE to specify order decision */ + + if (knew == kk-1) {action = LOWER; goto takeaction;} + if (kk == maxord) {action = MAINTAIN; goto takeaction;} + if ( (kk+1 >= ns ) || (kdiff == 1)) {action = MAINTAIN; goto takeaction;} + + /* Estimate the error at order k+1, unless already decided to + reduce order, or already using maximum order, or stepsize has not + been constant, or order was just raised. */ + + N_VLinearSum (ONE, ee, -ONE, phi[kk+1], tempv1); + enorm = IDAWrmsNorm(IDA_mem, tempv1, ewt, suppressalg); + err_kp1= enorm/(kk+2); + + /* Choose among orders k-1, k, k+1 using local truncation error norms. */ + + terr_k = (kk+1) * err_k; + terr_kp1 = (kk+2) * err_kp1; + + if (kk == 1) { + if (terr_kp1 >= HALF * terr_k) {action = MAINTAIN; goto takeaction;} + else {action = RAISE; goto takeaction;} + } else { + terr_km1 = kk * err_km1; + if (terr_km1 <= MIN(terr_k, terr_kp1)) {action = LOWER; goto takeaction;} + else if (terr_kp1 >= terr_k) {action = MAINTAIN; goto takeaction;} + else {action = RAISE; goto takeaction;} + } + + takeaction: + + /* Set the estimated error norm and, on change of order, reset kk. */ + if (action == RAISE) { kk++; err_knew = err_kp1; } + else if (action == LOWER) { kk--; err_knew = err_km1; } + else { err_knew = err_k; } + + /* Compute rr = tentative ratio hnew/hh from error norm estimate. + Reduce hh if rr <= 1, double hh if rr >= 2, else leave hh as is. + If hh is reduced, hnew/hh is restricted to be between .5 and .9. */ + + hnew = hh; + rr = RPowerR( (TWO * err_knew + PT0001) , (-ONE/(kk+1) ) ); + + if (rr >= TWO) { + hnew = TWO * hh; + if( (tmp = ABS(hnew)*hmax_inv) > ONE ) hnew /= tmp; + } else if (rr <= ONE ) { + rr = MAX(HALF, MIN(PT9,rr)); + hnew = hh * rr; + } + + hh = hnew; + + } /* end of phase if block */ + + /* Save ee for possible order increase on next step */ + if (kused < maxord) { + N_VScale(ONE, ee, phi[kused+1]); + } + + /* Update phi arrays */ + N_VLinearSum(ONE, ee, ONE, phi[kused], phi[kused]); + for (j= kused-1; j>=0; j--) + N_VLinearSum(ONE, phi[j], ONE, phi[j+1], phi[j]); + +} + +/* + * ----------------------------------------------------------------- + * Norm function + * ----------------------------------------------------------------- + */ + +/* + * IDAWrmsNorm + * + * Returns the WRMS norm of vector x with weights w. + * If mask = TRUE, the weight vector w is masked by id, i.e., + * nrm = N_VWrmsNormMask(x,w,id); + * Otherwise, + * nrm = N_VWrmsNorm(x,w); + * + * mask = FALSE when the call is made from the nonlinear solver. + * mask = suppressalg otherwise. + */ + +realtype IDAWrmsNorm(IDAMem IDA_mem, N_Vector x, N_Vector w, + booleantype mask) +{ + realtype nrm; + + if (mask) nrm = N_VWrmsNormMask(x, w, id); + else nrm = N_VWrmsNorm(x, w); + + return(nrm); +} + +/* + * ----------------------------------------------------------------- + * Functions for rootfinding + * ----------------------------------------------------------------- + */ + +/* + * IDARcheck1 + * + * This routine completes the initialization of rootfinding memory + * information, and checks whether g has a zero both at and very near + * the initial point of the IVP. + * + * This routine returns an int equal to: + * IDA_RTFUNC_FAIL < 0 if the g function failed, or + * IDA_SUCCESS = 0 otherwise. + */ + +static int IDARcheck1(IDAMem IDA_mem) +{ + int i, retval; + realtype smallh, hratio; + booleantype zroot; + + for (i = 0; i < nrtfn; i++) iroots[i] = 0; + tlo = tn; + ttol = (ABS(tn) + ABS(hh))*uround*HUNDRED; + + /* Evaluate g at initial t and check for zero values. */ + retval = gfun (tlo, phi[0], phi[1], glo, user_data); + nge = 1; + if (retval != 0) return(IDA_RTFUNC_FAIL); + + zroot = FALSE; + for (i = 0; i < nrtfn; i++) { + if (ABS(glo[i]) == ZERO) { + zroot = TRUE; + gactive[i] = FALSE; + } + } + if (!zroot) return(IDA_SUCCESS); + + /* Some g_i is zero at t0; look at g at t0+(small increment). */ + hratio = MAX(ttol/ABS(hh), PT1); + smallh = hratio*hh; + tlo += smallh; + N_VLinearSum(ONE, phi[0], smallh, phi[1], yy); + retval = gfun (tlo, yy, phi[1], glo, user_data); + nge++; + if (retval != 0) return(IDA_RTFUNC_FAIL); + + /* We check now only the components of g which were exactly 0.0 at t0 + * to see if we can 'activate' them. */ + + for (i = 0; i < nrtfn; i++) { + if (!gactive[i] && ABS(glo[i]) != ZERO) { + gactive[i] = TRUE; + + } + } + + return(IDA_SUCCESS); +} + +/* + * IDARcheck2 + * + * This routine checks for exact zeros of g at the last root found, + * if the last return was a root. It then checks for a close + * pair of zeros (an error condition), and for a new root at a + * nearby point. The left endpoint (tlo) of the search interval + * is adjusted if necessary to assure that all g_i are nonzero + * there, before returning to do a root search in the interval. + * + * On entry, tlo = tretlast is the last value of tret returned by + * IDASolve. This may be the previous tn, the previous tout value, + * or the last root location. + * + * This routine returns an int equal to: + * IDA_RTFUNC_FAIL (<0) if the g function failed, or + * CLOSERT (>0) if a close pair of zeros was found, or + * RTFOUND (>0) if a new zero of g was found near tlo, or + * IDA_SUCCESS (=0) otherwise. + */ + +static int IDARcheck2(IDAMem IDA_mem) +{ + int i, retval; + realtype smallh, hratio; + booleantype zroot; + + if (irfnd == 0) return(IDA_SUCCESS); + + (void) IDAGetSolution(IDA_mem, tlo, yy, yp); + retval = gfun (tlo, yy, yp, glo, user_data); + nge++; + if (retval != 0) return(IDA_RTFUNC_FAIL); + + zroot = FALSE; + for (i = 0; i < nrtfn; i++) iroots[i] = 0; + for (i = 0; i < nrtfn; i++) { + if (!gactive[i]) continue; + if (ABS(glo[i]) == ZERO) { + zroot = TRUE; + iroots[i] = 1; + } + } + if (!zroot) return(IDA_SUCCESS); + + /* One or more g_i has a zero at tlo. Check g at tlo+smallh. */ + ttol = (ABS(tn) + ABS(hh))*uround*HUNDRED; + smallh = (hh > ZERO) ? ttol : -ttol; + tlo += smallh; + if ( (tlo - tn)*hh >= ZERO) { + hratio = smallh/hh; + N_VLinearSum(ONE, yy, hratio, phi[1], yy); + } else { + (void) IDAGetSolution(IDA_mem, tlo, yy, yp); + } + retval = gfun (tlo, yy, yp, glo, user_data); + nge++; + if (retval != 0) return(IDA_RTFUNC_FAIL); + + zroot = FALSE; + for (i = 0; i < nrtfn; i++) { + if (!gactive[i]) continue; + if (ABS(glo[i]) == ZERO) { + if (iroots[i] == 1) return(CLOSERT); + zroot = TRUE; + iroots[i] = 1; + } + } + if (zroot) return(RTFOUND); + return(IDA_SUCCESS); + +} + +/* + * IDARcheck3 + * + * This routine interfaces to IDARootfind to look for a root of g + * between tlo and either tn or tout, whichever comes first. + * Only roots beyond tlo in the direction of integration are sought. + * + * This routine returns an int equal to: + * IDA_RTFUNC_FAIL (<0) if the g function failed, or + * RTFOUND (>0) if a root of g was found, or + * IDA_SUCCESS (=0) otherwise. + */ + +static int IDARcheck3(IDAMem IDA_mem) +{ + int i, ier, retval; + + /* Set thi = tn or tout, whichever comes first. */ + if (taskc == IDA_ONE_STEP) thi = tn; + if (taskc == IDA_NORMAL) { + thi = ( (toutc - tn)*hh >= ZERO) ? tn : toutc; + } + + /* Get y and y' at thi. */ + (void) IDAGetSolution(IDA_mem, thi, yy, yp); + + + /* Set ghi = g(thi) and call IDARootfind to search (tlo,thi) for roots. */ + retval = gfun (thi, yy, yp, ghi, user_data); + nge++; + if (retval != 0) return(IDA_RTFUNC_FAIL); + + ttol = (ABS(tn) + ABS(hh))*uround*HUNDRED; + ier = IDARootfind(IDA_mem); + if (ier == IDA_RTFUNC_FAIL) return(IDA_RTFUNC_FAIL); + for(i=0; i 0, search for roots of g_i only if + * g_i is increasing; if rootdir[i] < 0, search for + * roots of g_i only if g_i is decreasing; otherwise + * always search for roots of g_i. + * + * gactive = array specifying whether a component of g should + * or should not be monitored. gactive[i] is initially + * set to TRUE for all i=0,...,nrtfn-1, but it may be + * reset to FALSE if at the first step g[i] is 0.0 + * both at the I.C. and at a small perturbation of them. + * gactive[i] is then set back on TRUE only after the + * corresponding g function moves away from 0.0. + * + * nge = cumulative counter for gfun calls. + * + * ttol = a convergence tolerance for trout. Input only. + * When a root at trout is found, it is located only to + * within a tolerance of ttol. Typically, ttol should + * be set to a value on the order of + * 100 * UROUND * max (ABS(tlo), ABS(thi)) + * where UROUND is the unit roundoff of the machine. + * + * tlo, thi = endpoints of the interval in which roots are sought. + * On input, and must be distinct, but tlo - thi may + * be of either sign. The direction of integration is + * assumed to be from tlo to thi. On return, tlo and thi + * are the endpoints of the final relevant interval. + * + * glo, ghi = arrays of length nrtfn containing the vectors g(tlo) + * and g(thi) respectively. Input and output. On input, + * none of the glo[i] should be zero. + * + * trout = root location, if a root was found, or thi if not. + * Output only. If a root was found other than an exact + * zero of g, trout is the endpoint thi of the final + * interval bracketing the root, with size at most ttol. + * + * grout = array of length nrtfn containing g(trout) on return. + * + * iroots = int array of length nrtfn with root information. + * Output only. If a root was found, iroots indicates + * which components g_i have a root at trout. For + * i = 0, ..., nrtfn-1, iroots[i] = 1 if g_i has a root + * and g_i is increasing, iroots[i] = -1 if g_i has a + * root and g_i is decreasing, and iroots[i] = 0 if g_i + * has no roots or g_i varies in the direction opposite + * to that indicated by rootdir[i]. + * + * This routine returns an int equal to: + * IDA_RTFUNC_FAIL (<0) if the g function failed, or + * RTFOUND = 1 if a root of g was found, or + * IDA_SUCCESS = 0 otherwise. + * + */ + +static int IDARootfind(IDAMem IDA_mem) +{ + realtype alph, tmid, gfrac, maxfrac, fracint, fracsub; + int i, retval, imax, side, sideprev; + booleantype zroot, sgnchg; + + imax = 0; + + /* First check for change in sign in ghi or for a zero in ghi. */ + maxfrac = ZERO; + zroot = FALSE; + sgnchg = FALSE; + for (i = 0; i < nrtfn; i++) { + if(!gactive[i]) continue; + if (ABS(ghi[i]) == ZERO) { + if(rootdir[i]*glo[i] <= ZERO) { + zroot = TRUE; + } + } else { + if ( (glo[i]*ghi[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) { + gfrac = ABS(ghi[i]/(ghi[i] - glo[i])); + if (gfrac > maxfrac) { + sgnchg = TRUE; + maxfrac = gfrac; + imax = i; + } + } + } + } + + /* If no sign change was found, reset trout and grout. Then return + IDA_SUCCESS if no zero was found, or set iroots and return RTFOUND. */ + if (!sgnchg) { + trout = thi; + for (i = 0; i < nrtfn; i++) grout[i] = ghi[i]; + if (!zroot) return(IDA_SUCCESS); + for (i = 0; i < nrtfn; i++) { + iroots[i] = 0; + if(!gactive[i]) continue; + if (ABS(ghi[i]) == ZERO) iroots[i] = glo[i] > 0 ? -1:1; + } + return(RTFOUND); + } + + /* Initialize alph to avoid compiler warning */ + alph = ONE; + + /* A sign change was found. Loop to locate nearest root. */ + + side = 0; sideprev = -1; + loop { /* Looping point */ + + /* Set weight alph. + On the first two passes, set alph = 1. Thereafter, reset alph + according to the side (low vs high) of the subinterval in which + the sign change was found in the previous two passes. + If the sides were opposite, set alph = 1. + If the sides were the same, then double alph (if high side), + or halve alph (if low side). + The next guess tmid is the secant method value if alph = 1, but + is closer to tlo if alph < 1, and closer to thi if alph > 1. */ + + if (sideprev == side) { + alph = (side == 2) ? alph*TWO : alph*HALF; + } else { + alph = ONE; + } + + /* Set next root approximation tmid and get g(tmid). + If tmid is too close to tlo or thi, adjust it inward, + by a fractional distance that is between 0.1 and 0.5. */ + tmid = thi - (thi - tlo)*ghi[imax]/(ghi[imax] - alph*glo[imax]); + if (ABS(tmid - tlo) < HALF*ttol) { + fracint = ABS(thi - tlo)/ttol; + fracsub = (fracint > FIVE) ? PT1 : HALF/fracint; + tmid = tlo + fracsub*(thi - tlo); + } + if (ABS(thi - tmid) < HALF*ttol) { + fracint = ABS(thi - tlo)/ttol; + fracsub = (fracint > FIVE) ? PT1 : HALF/fracint; + tmid = thi - fracsub*(thi - tlo); + } + + (void) IDAGetSolution(IDA_mem, tmid, yy, yp); + retval = gfun (tmid, yy, yp, grout, user_data); + nge++; + if (retval != 0) return(IDA_RTFUNC_FAIL); + + /* Check to see in which subinterval g changes sign, and reset imax. + Set side = 1 if sign change is on low side, or 2 if on high side. */ + maxfrac = ZERO; + zroot = FALSE; + sgnchg = FALSE; + sideprev = side; + for (i = 0; i < nrtfn; i++) { + if(!gactive[i]) continue; + if (ABS(grout[i]) == ZERO) { + if(rootdir[i]*glo[i] <= ZERO) { + zroot = TRUE; + } + } else { + if ( (glo[i]*grout[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) { + gfrac = ABS(grout[i]/(grout[i] - glo[i])); + if (gfrac > maxfrac) { + sgnchg = TRUE; + maxfrac = gfrac; + imax = i; + } + } + } + } + if (sgnchg) { + /* Sign change found in (tlo,tmid); replace thi with tmid. */ + thi = tmid; + for (i = 0; i < nrtfn; i++) ghi[i] = grout[i]; + side = 1; + /* Stop at root thi if converged; otherwise loop. */ + if (ABS(thi - tlo) <= ttol) break; + continue; /* Return to looping point. */ + } + + if (zroot) { + /* No sign change in (tlo,tmid), but g = 0 at tmid; return root tmid. */ + thi = tmid; + for (i = 0; i < nrtfn; i++) ghi[i] = grout[i]; + break; + } + + /* No sign change in (tlo,tmid), and no zero at tmid. + Sign change must be in (tmid,thi). Replace tlo with tmid. */ + tlo = tmid; + for (i = 0; i < nrtfn; i++) glo[i] = grout[i]; + side = 2; + /* Stop at root thi if converged; otherwise loop back. */ + if (ABS(thi - tlo) <= ttol) break; + + } /* End of root-search loop */ + + /* Reset trout and grout, set iroots, and return RTFOUND. */ + trout = thi; + for (i = 0; i < nrtfn; i++) { + grout[i] = ghi[i]; + iroots[i] = 0; + if(!gactive[i]) continue; + if ( (ABS(ghi[i]) == ZERO) && (rootdir[i]*glo[i] <= ZERO) ) + iroots[i] = glo[i] > 0 ? -1:1; + if ( (glo[i]*ghi[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) + iroots[i] = glo[i] > 0 ? -1:1; + } + return(RTFOUND); +} + +/* + * ================================================================= + * IDA error message handling functions + * ================================================================= + */ + +/* + * IDAProcessError is a high level error handling function + * - if ida_mem==NULL it prints the error message to stderr + * - otherwise, it sets-up and calls the error hadling function + * pointed to by ida_ehfun + */ + +#define ehfun (IDA_mem->ida_ehfun) +#define eh_data (IDA_mem->ida_eh_data) + +void IDAProcessError(IDAMem IDA_mem, + int error_code, const char *module, const char *fname, + const char *msgfmt, ...) +{ + va_list ap; + char msg[256]; + + /* Initialize the argument pointer variable + (msgfmt is the last required argument to IDAProcessError) */ + + va_start(ap, msgfmt); + + if (IDA_mem == NULL) { /* We write to stderr */ + +#ifndef NO_FPRINTF_OUTPUT + fprintf(stderr, "\n[%s ERROR] %s\n ", module, fname); + fprintf(stderr, msgfmt); + fprintf(stderr, "\n\n"); +#endif + + } else { /* We can call ehfun */ + + /* Compose the message */ + + vsprintf(msg, msgfmt, ap); + + /* Call ehfun */ + + ehfun(error_code, module, fname, msg, eh_data); + + } + + /* Finalize argument processing */ + + va_end(ap); + + return; + +} + +/* IDAErrHandler is the default error handling function. + It sends the error message to the stream pointed to by ida_errfp */ + +#define errfp (IDA_mem->ida_errfp) + +void IDAErrHandler(int error_code, const char *module, + const char *function, char *msg, void *data) +{ + IDAMem IDA_mem; + char err_type[10]; + + /* data points to IDA_mem here */ + + IDA_mem = (IDAMem) data; + + if (error_code == IDA_WARNING) + sprintf(err_type,"WARNING"); + else + sprintf(err_type,"ERROR"); + +#ifndef NO_FPRINTF_OUTPUT + if (errfp!=NULL) { + fprintf(errfp,"\n[%s %s] %s\n",module,err_type,function); + fprintf(errfp," %s\n\n",msg); + } +#endif + + return; +} diff --git a/odemex/Parser/CVode/ida_src/src/ida/ida_band.c b/odemex/Parser/CVode/ida_src/src/ida/ida_band.c new file mode 100644 index 0000000..ad7c735 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/ida_band.c @@ -0,0 +1,320 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.11 $ + * $Date: 2009/02/17 02:42:29 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the IDA banded linear + * solver module, IDABAND. This module uses standard banded + * matrix techniques to solve the linear systems generated by the + * (nonlinear) Newton iteration process. The user may either + * supply a banded Jacobian routine or use the routine supplied + * with this module (IDABandDQJac). + * ----------------------------------------------------------------- + */ + +#include +#include +#include + +#include +#include "ida_direct_impl.h" +#include "ida_impl.h" + +#include + +/* Constants */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) +#define TWO RCONST(2.0) + +/* IDABAND linit, lsetup, lsolve, and lfree routines */ + +static int IDABandInit(IDAMem IDA_mem); + +static int IDABandSetup(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp, + N_Vector rrp, N_Vector tmp1, + N_Vector tmp2, N_Vector tmp3); + +static int IDABandSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight, + N_Vector ycur, N_Vector ypcur, N_Vector rrcur); + +static int IDABandFree(IDAMem IDA_mem); + +/* Readability Replacements */ + +#define res (IDA_mem->ida_res) +#define tn (IDA_mem->ida_tn) +#define hh (IDA_mem->ida_hh) +#define cj (IDA_mem->ida_cj) +#define cjratio (IDA_mem->ida_cjratio) +#define ewt (IDA_mem->ida_ewt) +#define constraints (IDA_mem->ida_constraints) +#define linit (IDA_mem->ida_linit) +#define lsetup (IDA_mem->ida_lsetup) +#define lsolve (IDA_mem->ida_lsolve) +#define lperf (IDA_mem->ida_lperf) +#define lfree (IDA_mem->ida_lfree) +#define lmem (IDA_mem->ida_lmem) +#define setupNonNull (IDA_mem->ida_setupNonNull) +#define vec_tmpl (IDA_mem->ida_tempv1) + +#define mtype (idadls_mem->d_type) +#define neq (idadls_mem->d_n) +#define ml (idadls_mem->d_ml) +#define mu (idadls_mem->d_mu) +#define jacDQ (idadls_mem->d_jacDQ) +#define bjac (idadls_mem->d_bjac) +#define JJ (idadls_mem->d_J) +#define smu (idadls_mem->d_smu) +#define pivots (idadls_mem->d_pivots) +#define nje (idadls_mem->d_nje) +#define nreDQ (idadls_mem->d_nreDQ) +#define jacdata (idadls_mem->d_J_data) +#define last_flag (idadls_mem->d_last_flag) + +/* + * ----------------------------------------------------------------- + * IDABand + * ----------------------------------------------------------------- + * This routine initializes the memory record and sets various function + * fields specific to the IDABAND linear solver module. + * IDABand first calls the existing lfree routine if this is not NULL. + * Then it sets the ida_linit, ida_lsetup, ida_lsolve, ida_lperf, and + * ida_lfree fields in (*IDA_mem) to be IDABandInit, IDABandSetup, + * IDABandSolve, NULL, and IDABandFree, respectively. + * It allocates memory for a structure of type IDADlsMemRec and sets + * the ida_lmem field in (*IDA_mem) to the address of this structure. + * It sets setupNonNull in (*IDA_mem) to TRUE, sets the d_jacdata field in + * the IDADlsMemRec structure to be the input parameter jdata, and sets + * the d_bjac field to be: + * (1) the input parameter bjac, if bjac != NULL, or + * (2) IDABandDQJac, if bjac == NULL. + * Finally, it allocates memory for JJ and pivots. + * IDABand returns IDADLS_SUCCESS = 0, IDADLS_LMEM_FAIL = -1, + * or IDADLS_ILL_INPUT = -2. + * + * NOTE: The band linear solver assumes a serial implementation + * of the NVECTOR package. Therefore, IDABand will first + * test for a compatible N_Vector internal representation by + * checking that the N_VGetArrayPointer function exists + * ----------------------------------------------------------------- + */ + +int IDABand(void *ida_mem, int Neq, int mupper, int mlower) +{ + IDAMem IDA_mem; + IDADlsMem idadls_mem; + int flag; + + /* Return immediately if ida_mem is NULL. */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDADLS_MEM_NULL, "IDABAND", "IDABand", MSGD_IDAMEM_NULL); + return(IDADLS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + /* Test if the NVECTOR package is compatible with the BAND solver */ + if(vec_tmpl->ops->nvgetarraypointer == NULL) { + IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDABAND", "IDABand", MSGD_BAD_NVECTOR); + return(IDADLS_ILL_INPUT); + } + + /* Test mlower and mupper for legality. */ + if ((mlower < 0) || (mupper < 0) || (mlower >= Neq) || (mupper >= Neq)) { + IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDABAND", "IDABand", MSGD_BAD_SIZES); + return(IDADLS_ILL_INPUT); + } + + if (lfree != NULL) flag = lfree((IDAMem) ida_mem); + + /* Set five main function fields in ida_mem. */ + linit = IDABandInit; + lsetup = IDABandSetup; + lsolve = IDABandSolve; + lperf = NULL; + lfree = IDABandFree; + + /* Get memory for IDADlsMemRec. */ + idadls_mem = NULL; + idadls_mem = (IDADlsMem) malloc(sizeof(struct IDADlsMemRec)); + if (idadls_mem == NULL) { + IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDABAND", "IDABand", MSGD_MEM_FAIL); + return(IDADLS_MEM_FAIL); + } + + /* Set matrix type */ + mtype = SUNDIALS_BAND; + + /* Set default Jacobian routine and Jacobian data */ + jacDQ = TRUE; + bjac = NULL; + jacdata = NULL; + + last_flag = IDADLS_SUCCESS; + + setupNonNull = TRUE; + + /* Store problem size */ + neq = Neq; + + idadls_mem->d_ml = mlower; + idadls_mem->d_mu = mupper; + + /* Set extended upper half-bandwidth for JJ (required for pivoting). */ + smu = MIN(Neq-1, mupper + mlower); + + /* Allocate memory for JJ and pivot array. */ + JJ = NULL; + JJ = NewBandMat(Neq, mupper, mlower, smu); + if (JJ == NULL) { + IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDABAND", "IDABand", MSGD_MEM_FAIL); + free(idadls_mem); idadls_mem = NULL; + return(IDADLS_MEM_FAIL); + } + + pivots = NULL; + pivots = NewIntArray(Neq); + if (pivots == NULL) { + IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDABAND", "IDABand", MSGD_MEM_FAIL); + DestroyMat(JJ); + free(idadls_mem); idadls_mem = NULL; + return(IDADLS_MEM_FAIL); + } + + /* Attach linear solver memory to the integrator memory */ + lmem = idadls_mem; + + return(IDADLS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * IDABAND interface functions + * ----------------------------------------------------------------- + */ + +/* + This routine does remaining initializations specific to the IDABAND + linear solver module. It returns 0. +*/ + +static int IDABandInit(IDAMem IDA_mem) +{ + IDADlsMem idadls_mem; + + idadls_mem = (IDADlsMem) lmem; + + /* Initialize nje and nreB */ + nje = 0; + nreDQ = 0; + + if (jacDQ) { + bjac = idaDlsBandDQJac; + jacdata = IDA_mem; + } else { + jacdata = IDA_mem->ida_user_data; + } + + last_flag = 0; + return(0); +} + + +/* + This routine does the setup operations for the IDABAND linear + solver module. It calls the Jacobian evaluation routine, + updates counters, and calls the band LU factorization routine. + The return value is either + IDADLS_SUCCESS = 0 if successful, + +1 if the jac routine failed recoverably or the + LU factorization failed, or + -1 if the jac routine failed unrecoverably. +*/ + +static int IDABandSetup(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp, + N_Vector rrp, N_Vector tmp1, N_Vector tmp2, + N_Vector tmp3) +{ + int retval; + long int retfac; + IDADlsMem idadls_mem; + + idadls_mem = (IDADlsMem) lmem; + + /* Increment nje counter. */ + nje++; + + /* Zero out JJ; call Jacobian routine jac; return if it failed. */ + SetToZero(JJ); + retval = bjac(neq, mu, ml, tn, cj, yyp, ypp, rrp, + JJ, jacdata, tmp1, tmp2, tmp3); + if (retval < 0) { + IDAProcessError(IDA_mem, IDADLS_JACFUNC_UNRECVR, "IDABAND", "IDABandSetup", MSGD_JACFUNC_FAILED); + last_flag = IDADLS_JACFUNC_UNRECVR; + return(-1); + } + if (retval > 0) { + last_flag = IDADLS_JACFUNC_RECVR; + return(+1); + } + + /* Do LU factorization of JJ; return success or fail flag. */ + retfac = BandGBTRF(JJ, pivots); + + if (retfac != 0) { + last_flag = retfac; + return(+1); + } + last_flag = IDADLS_SUCCESS; + return(0); +} +/* + This routine handles the solve operation for the IDABAND linear + solver module. It calls the band backsolve routine, scales the + solution vector according to cjratio, then returns IDADLS_SUCCESS = 0. +*/ + +static int IDABandSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight, + N_Vector ycur, N_Vector ypcur, N_Vector rrcur) +{ + IDADlsMem idadls_mem; + realtype *bd; + + idadls_mem = (IDADlsMem) lmem; + + bd = N_VGetArrayPointer(b); + BandGBTRS(JJ, pivots, bd); + + /* Scale the correction to account for change in cj. */ + if (cjratio != ONE) N_VScale(TWO/(ONE + cjratio), b, b); + + last_flag = 0; + return(0); +} + +/* + This routine frees memory specific to the IDABAND linear solver. +*/ + +static int IDABandFree(IDAMem IDA_mem) +{ + IDADlsMem idadls_mem; + + idadls_mem = (IDADlsMem) lmem; + + DestroyMat(JJ); + DestroyArray(pivots); + free(lmem); lmem = NULL; + + return(0); + +} + diff --git a/odemex/Parser/CVode/ida_src/src/ida/ida_bbdpre.c b/odemex/Parser/CVode/ida_src/src/ida/ida_bbdpre.c new file mode 100644 index 0000000..6faeeb2 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/ida_bbdpre.c @@ -0,0 +1,584 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.8 $ + * $Date: 2009/02/17 02:42:29 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This file contains implementations of routines for a + * band-block-diagonal preconditioner, i.e. a block-diagonal + * matrix with banded blocks, for use with IDA and an IDASPILS + * linear solver. + * + * NOTE: With only one processor in use, a banded matrix results + * rather than a block-diagonal matrix with banded blocks. + * Diagonal blocking occurs at the processor level. + * ----------------------------------------------------------------- + */ + +#include +#include +#include + +#include "ida_impl.h" +#include "ida_spils_impl.h" +#include "ida_bbdpre_impl.h" + +#include +#include +#include + +#include + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) +#define TWO RCONST(2.0) + +/* Prototypes of IDABBDPrecSetup and IDABBDPrecSolve */ + +static int IDABBDPrecSetup(realtype tt, + N_Vector yy, N_Vector yp, N_Vector rr, + realtype c_j, void *prec_data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +static int IDABBDPrecSolve(realtype tt, + N_Vector yy, N_Vector yp, N_Vector rr, + N_Vector rvec, N_Vector zvec, + realtype c_j, realtype delta, void *prec_data, + N_Vector tmp); + +/* Prototype for IDABBDPrecFree */ + +static void IDABBDPrecFree(IDAMem ida_mem); + +/* Prototype for difference quotient Jacobian calculation routine */ + +static int IBBDDQJac(IBBDPrecData pdata, realtype tt, realtype cj, + N_Vector yy, N_Vector yp, N_Vector gref, + N_Vector ytemp, N_Vector yptemp, N_Vector gtemp); + +/* + * ================================================================ + * User-Callable Functions: initialization, reinit and free + * ================================================================ + */ + +/* Readability Replacements */ + +#define uround (IDA_mem->ida_uround) +#define vec_tmpl (IDA_mem->ida_tempv1) + +/* + * ----------------------------------------------------------------- + * User-Callable Functions : malloc, reinit and free + * ----------------------------------------------------------------- + */ + +int IDABBDPrecInit(void *ida_mem, int Nlocal, + int mudq, int mldq, + int mukeep, int mlkeep, + realtype dq_rel_yy, + IDABBDLocalFn Gres, IDABBDCommFn Gcomm) +{ + IDAMem IDA_mem; + IDASpilsMem idaspils_mem; + IBBDPrecData pdata; + N_Vector tempv4; + int muk, mlk, storage_mu; + int flag; + + if (ida_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDABBDPRE", "IDABBDPrecInit", MSGBBD_MEM_NULL); + return(IDASPILS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + /* Test if one of the SPILS linear solvers has been attached */ + if (IDA_mem->ida_lmem == NULL) { + IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDABBDPRE", "IDABBDPrecInit", MSGBBD_LMEM_NULL); + return(IDASPILS_LMEM_NULL); + } + idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem; + + /* Test if the NVECTOR package is compatible with BLOCK BAND preconditioner */ + if(vec_tmpl->ops->nvgetarraypointer == NULL) { + IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDABBDPRE", "IDABBDPrecInit", MSGBBD_BAD_NVECTOR); + return(IDASPILS_ILL_INPUT); + } + + /* Allocate data memory. */ + pdata = NULL; + pdata = (IBBDPrecData) malloc(sizeof *pdata); + if (pdata == NULL) { + IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDABBDPRE", "IDABBDPrecInit", MSGBBD_MEM_FAIL); + return(IDASPILS_MEM_FAIL); + } + + /* Set pointers to glocal and gcomm; load half-bandwidths. */ + pdata->ida_mem = IDA_mem; + pdata->glocal = Gres; + pdata->gcomm = Gcomm; + pdata->mudq = MIN(Nlocal-1, MAX(0, mudq)); + pdata->mldq = MIN(Nlocal-1, MAX(0, mldq)); + muk = MIN(Nlocal-1, MAX(0, mukeep)); + mlk = MIN(Nlocal-1, MAX(0, mlkeep)); + pdata->mukeep = muk; + pdata->mlkeep = mlk; + + /* Set extended upper half-bandwidth for PP (required for pivoting). */ + storage_mu = MIN(Nlocal-1, muk+mlk); + + /* Allocate memory for preconditioner matrix. */ + pdata->PP = NULL; + pdata->PP = NewBandMat(Nlocal, muk, mlk, storage_mu); + if (pdata->PP == NULL) { + free(pdata); pdata = NULL; + IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDABBDPRE", "IDABBDPrecInit", MSGBBD_MEM_FAIL); + return(IDASPILS_MEM_FAIL); + } + + /* Allocate memory for pivots. */ + pdata->pivots = NULL; + pdata->pivots = NewIntArray(Nlocal); + if (pdata->PP == NULL) { + DestroyMat(pdata->PP); + free(pdata); pdata = NULL; + IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDABBDPRE", "IDABBDPrecInit", MSGBBD_MEM_FAIL); + return(IDASPILS_MEM_FAIL); + } + + /* Allocate tempv4 for use by IBBDDQJac */ + tempv4 = NULL; + tempv4 = N_VClone(vec_tmpl); + if (tempv4 == NULL){ + DestroyMat(pdata->PP); + DestroyArray(pdata->pivots); + free(pdata); pdata = NULL; + IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDABBDPRE", "IDABBDPrecInit", MSGBBD_MEM_FAIL); + return(IDASPILS_MEM_FAIL); + } + pdata->tempv4 = tempv4; + + /* Set rel_yy based on input value dq_rel_yy (0 implies default). */ + pdata->rel_yy = (dq_rel_yy > ZERO) ? dq_rel_yy : RSqrt(uround); + + /* Store Nlocal to be used in IDABBDPrecSetup */ + pdata->n_local = Nlocal; + + /* Set work space sizes and initialize nge. */ + pdata->rpwsize = Nlocal*(mlk + storage_mu + 1); + pdata->ipwsize = Nlocal; + pdata->nge = 0; + + /* Overwrite the pdata field in the SPILS memory */ + idaspils_mem->s_pdata = pdata; + + /* Attach the pfree function */ + idaspils_mem->s_pfree = IDABBDPrecFree; + + /* Attach preconditioner solve and setup functions */ + flag = IDASpilsSetPreconditioner(ida_mem, IDABBDPrecSetup, IDABBDPrecSolve); + + return(flag); +} + +int IDABBDPrecReInit(void *ida_mem, + int mudq, int mldq, + realtype dq_rel_yy) +{ + IDAMem IDA_mem; + IDASpilsMem idaspils_mem; + IBBDPrecData pdata; + int Nlocal; + + + if (ida_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDABBDPRE", "IDABBDPrecReInit", MSGBBD_MEM_NULL); + return(IDASPILS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + /* Test if one of the SPILS linear solvers has been attached */ + if (IDA_mem->ida_lmem == NULL) { + IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDABBDPRE", "IDABBDPrecReInit", MSGBBD_LMEM_NULL); + return(IDASPILS_LMEM_NULL); + } + idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem; + + /* Test if the preconditioner data is non-NULL */ + if (idaspils_mem->s_pdata == NULL) { + IDAProcessError(IDA_mem, IDASPILS_PMEM_NULL, "IDABBDPRE", "IDABBDPrecReInit", MSGBBD_PMEM_NULL); + return(IDASPILS_PMEM_NULL); + } + pdata = (IBBDPrecData) idaspils_mem->s_pdata; + + /* Load half-bandwidths. */ + Nlocal = pdata->n_local; + pdata->mudq = MIN(Nlocal-1, MAX(0, mudq)); + pdata->mldq = MIN(Nlocal-1, MAX(0, mldq)); + + /* Set rel_yy based on input value dq_rel_yy (0 implies default). */ + pdata->rel_yy = (dq_rel_yy > ZERO) ? dq_rel_yy : RSqrt(uround); + + /* Re-initialize nge */ + pdata->nge = 0; + + return(IDASPILS_SUCCESS); +} + +int IDABBDPrecGetWorkSpace(void *ida_mem, long int *lenrwBBDP, long int *leniwBBDP) +{ + IDAMem IDA_mem; + IDASpilsMem idaspils_mem; + IBBDPrecData pdata; + + if (ida_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDABBDPRE", "IDABBDPrecGetWorkSpace", MSGBBD_MEM_NULL); + return(IDASPILS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + if (IDA_mem->ida_lmem == NULL) { + IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDABBDPRE", "IDABBDPrecGetWorkSpace", MSGBBD_LMEM_NULL); + return(IDASPILS_LMEM_NULL); + } + idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem; + + if (idaspils_mem->s_pdata == NULL) { + IDAProcessError(IDA_mem, IDASPILS_PMEM_NULL, "IDABBDPRE", "IDABBDPrecGetWorkSpace", MSGBBD_PMEM_NULL); + return(IDASPILS_PMEM_NULL); + } + pdata = (IBBDPrecData) idaspils_mem->s_pdata; + + *lenrwBBDP = pdata->rpwsize; + *leniwBBDP = pdata->ipwsize; + + return(IDASPILS_SUCCESS); +} + +int IDABBDPrecGetNumGfnEvals(void *ida_mem, long int *ngevalsBBDP) +{ + IDAMem IDA_mem; + IDASpilsMem idaspils_mem; + IBBDPrecData pdata; + + if (ida_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDABBDPRE", "IDABBDPrecGetNumGfnEvals", MSGBBD_MEM_NULL); + return(IDASPILS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + if (IDA_mem->ida_lmem == NULL) { + IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDABBDPRE", "IDABBDPrecGetNumGfnEvals", MSGBBD_LMEM_NULL); + return(IDASPILS_LMEM_NULL); + } + idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem; + + if (idaspils_mem->s_pdata == NULL) { + IDAProcessError(IDA_mem, IDASPILS_PMEM_NULL, "IDABBDPRE", "IDABBDPrecGetNumGfnEvals", MSGBBD_PMEM_NULL); + return(IDASPILS_PMEM_NULL); + } + pdata = (IBBDPrecData) idaspils_mem->s_pdata; + + *ngevalsBBDP = pdata->nge; + + return(IDASPILS_SUCCESS); +} + + +/* Readability Replacements */ + +#define Nlocal (pdata->n_local) +#define mudq (pdata->mudq) +#define mldq (pdata->mldq) +#define mukeep (pdata->mukeep) +#define mlkeep (pdata->mlkeep) +#define glocal (pdata->glocal) +#define gcomm (pdata->gcomm) +#define pivots (pdata->pivots) +#define PP (pdata->PP) +#define tempv4 (pdata->tempv4) +#define nge (pdata->nge) +#define rel_yy (pdata->rel_yy) + +/* + * ----------------------------------------------------------------- + * Function : IDABBDPrecSetup + * ----------------------------------------------------------------- + * IDABBDPrecSetup generates a band-block-diagonal preconditioner + * matrix, where the local block (on this processor) is a band + * matrix. Each local block is computed by a difference quotient + * scheme via calls to the user-supplied routines glocal, gcomm. + * After generating the block in the band matrix PP, this routine + * does an LU factorization in place in PP. + * + * The IDABBDPrecSetup parameters used here are as follows: + * + * tt is the current value of the independent variable t. + * + * yy is the current value of the dependent variable vector, + * namely the predicted value of y(t). + * + * yp is the current value of the derivative vector y', + * namely the predicted value of y'(t). + * + * c_j is the scalar in the system Jacobian, proportional to 1/hh. + * + * bbd_data is the pointer to BBD memory set by IDABBDInit + * + * tmp1, tmp2, tmp3 are pointers to vectors of type + * N_Vector, used for temporary storage or + * work space. + * + * The arguments Neq, rr, res, uround, and nrePtr are not used. + * + * Return value: + * The value returned by this IDABBDPrecSetup function is a int + * flag indicating whether it was successful. This value is + * 0 if successful, + * > 0 for a recoverable error (step will be retried), or + * < 0 for a nonrecoverable error (step fails). + * ----------------------------------------------------------------- + */ + +static int IDABBDPrecSetup(realtype tt, + N_Vector yy, N_Vector yp, N_Vector rr, + realtype c_j, void *bbd_data, + N_Vector tempv1, N_Vector tempv2, N_Vector tempv3) +{ + int ier, retval; + IBBDPrecData pdata; + IDAMem IDA_mem; + + pdata =(IBBDPrecData) bbd_data; + + IDA_mem = (IDAMem) pdata->ida_mem; + + /* Call IBBDDQJac for a new Jacobian calculation and store in PP. */ + SetToZero(PP); + retval = IBBDDQJac(pdata, tt, c_j, yy, yp, + tempv1, tempv2, tempv3, tempv4); + if (retval < 0) { + IDAProcessError(IDA_mem, -1, "IDABBDPRE", "IDABBDPrecSetup", MSGBBD_FUNC_FAILED); + return(-1); + } + if (retval > 0) { + return(+1); + } + + /* Do LU factorization of preconditioner block in place (in PP). */ + ier = BandGBTRF(PP, pivots); + + /* Return 0 if the LU was complete, or +1 otherwise. */ + if (ier > 0) return(+1); + return(0); +} + +/* + * ----------------------------------------------------------------- + * Function: IDABBDPrecSolve + * ----------------------------------------------------------------- + * The function IDABBDPrecSolve computes a solution to the linear + * system P z = r, where P is the left preconditioner defined by + * the routine IDABBDPrecSetup. + * + * The IDABBDPrecSolve parameters used here are as follows: + * + * rvec is the input right-hand side vector r. + * + * zvec is the computed solution vector z. + * + * bbd_data is the pointer to BBD data set by IDABBDInit. + * + * The arguments tt, yy, yp, rr, c_j, delta, and tmp are NOT used. + * + * IDABBDPrecSolve always returns 0, indicating success. + * ----------------------------------------------------------------- + */ + +static int IDABBDPrecSolve(realtype tt, + N_Vector yy, N_Vector yp, N_Vector rr, + N_Vector rvec, N_Vector zvec, + realtype c_j, realtype delta, void *bbd_data, + N_Vector tmp) +{ + IBBDPrecData pdata; + realtype *zd; + + pdata = (IBBDPrecData) bbd_data; + + /* Copy rvec to zvec, do the backsolve, and return. */ + N_VScale(ONE, rvec, zvec); + + zd = N_VGetArrayPointer(zvec); + + BandGBTRS(PP, pivots, zd); + + return(0); +} + + + +static void IDABBDPrecFree(IDAMem IDA_mem) +{ + IDASpilsMem idaspils_mem; + IBBDPrecData pdata; + + if (IDA_mem->ida_lmem == NULL) return; + idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem; + + if (idaspils_mem->s_pdata == NULL) return; + pdata = (IBBDPrecData) idaspils_mem->s_pdata; + + DestroyMat(PP); + DestroyArray(pivots); + N_VDestroy(tempv4); + + free(pdata); + pdata = NULL; +} + + +#define ewt (IDA_mem->ida_ewt) +#define user_data (IDA_mem->ida_user_data) +#define hh (IDA_mem->ida_hh) +#define constraints (IDA_mem->ida_constraints) + +/* + * ----------------------------------------------------------------- + * IBBDDQJac + * ----------------------------------------------------------------- + * This routine generates a banded difference quotient approximation + * to the local block of the Jacobian of G(t,y,y'). It assumes that + * a band matrix of type BandMat is stored column-wise, and that + * elements within each column are contiguous. + * + * All matrix elements are generated as difference quotients, by way + * of calls to the user routine glocal. By virtue of the band + * structure, the number of these calls is bandwidth + 1, where + * bandwidth = mldq + mudq + 1. But the band matrix kept has + * bandwidth = mlkeep + mukeep + 1. This routine also assumes that + * the local elements of a vector are stored contiguously. + * + * Return values are: 0 (success), > 0 (recoverable error), + * or < 0 (nonrecoverable error). + * ----------------------------------------------------------------- + */ + +static int IBBDDQJac(IBBDPrecData pdata, realtype tt, realtype cj, + N_Vector yy, N_Vector yp, N_Vector gref, + N_Vector ytemp, N_Vector yptemp, N_Vector gtemp) +{ + IDAMem IDA_mem; + realtype inc, inc_inv; + int retval; + int group, i, j, width, ngroups, i1, i2; + realtype *ydata, *ypdata, *ytempdata, *yptempdata, *grefdata, *gtempdata; + realtype *cnsdata = NULL, *ewtdata; + realtype *col_j, conj, yj, ypj, ewtj; + + IDA_mem = (IDAMem) pdata->ida_mem; + + /* Initialize ytemp and yptemp. */ + + N_VScale(ONE, yy, ytemp); + N_VScale(ONE, yp, yptemp); + + /* Obtain pointers as required to the data array of vectors. */ + + ydata = N_VGetArrayPointer(yy); + ypdata = N_VGetArrayPointer(yp); + gtempdata = N_VGetArrayPointer(gtemp); + ewtdata = N_VGetArrayPointer(ewt); + if (constraints != NULL) + cnsdata = N_VGetArrayPointer(constraints); + ytempdata = N_VGetArrayPointer(ytemp); + yptempdata= N_VGetArrayPointer(yptemp); + grefdata = N_VGetArrayPointer(gref); + + /* Call gcomm and glocal to get base value of G(t,y,y'). */ + + if (gcomm != NULL) { + retval = gcomm(Nlocal, tt, yy, yp, user_data); + if (retval != 0) return(retval); + } + + retval = glocal(Nlocal, tt, yy, yp, gref, user_data); + nge++; + if (retval != 0) return(retval); + + + /* Set bandwidth and number of column groups for band differencing. */ + + width = mldq + mudq + 1; + ngroups = MIN(width, Nlocal); + + /* Loop over groups. */ + for(group = 1; group <= ngroups; group++) { + + /* Loop over the components in this group. */ + for(j = group-1; j < Nlocal; j += width) { + yj = ydata[j]; + ypj = ypdata[j]; + ewtj = ewtdata[j]; + + /* Set increment inc to yj based on rel_yy*abs(yj), with + adjustments using ypj and ewtj if this is small, and a further + adjustment to give it the same sign as hh*ypj. */ + inc = rel_yy*MAX(ABS(yj), MAX( ABS(hh*ypj), ONE/ewtj)); + if (hh*ypj < ZERO) inc = -inc; + inc = (yj + inc) - yj; + + /* Adjust sign(inc) again if yj has an inequality constraint. */ + if (constraints != NULL) { + conj = cnsdata[j]; + if (ABS(conj) == ONE) {if ((yj+inc)*conj < ZERO) inc = -inc;} + else if (ABS(conj) == TWO) {if ((yj+inc)*conj <= ZERO) inc = -inc;} + } + + /* Increment yj and ypj. */ + ytempdata[j] += inc; + yptempdata[j] += cj*inc; + + } + + /* Evaluate G with incremented y and yp arguments. */ + + retval = glocal(Nlocal, tt, ytemp, yptemp, gtemp, user_data); + nge++; + if (retval != 0) return(retval); + + /* Loop over components of the group again; restore ytemp and yptemp. */ + for(j = group-1; j < Nlocal; j += width) { + yj = ytempdata[j] = ydata[j]; + ypj = yptempdata[j] = ypdata[j]; + ewtj = ewtdata[j]; + + /* Set increment inc as before .*/ + inc = rel_yy*MAX(ABS(yj), MAX( ABS(hh*ypj), ONE/ewtj)); + if (hh*ypj < ZERO) inc = -inc; + inc = (yj + inc) - yj; + if (constraints != NULL) { + conj = cnsdata[j]; + if (ABS(conj) == ONE) {if ((yj+inc)*conj < ZERO) inc = -inc;} + else if (ABS(conj) == TWO) {if ((yj+inc)*conj <= ZERO) inc = -inc;} + } + + /* Form difference quotients and load into PP. */ + inc_inv = ONE/inc; + col_j = BAND_COL(PP,j); + i1 = MAX(0, j-mukeep); + i2 = MIN(j+mlkeep, Nlocal-1); + for(i = i1; i <= i2; i++) BAND_COL_ELEM(col_j,i,j) = + inc_inv * (gtempdata[i] - grefdata[i]); + } + } + + return(0); +} + diff --git a/odemex/Parser/CVode/ida_src/src/ida/ida_bbdpre_impl.h b/odemex/Parser/CVode/ida_src/src/ida/ida_bbdpre_impl.h new file mode 100644 index 0000000..11897bf --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/ida_bbdpre_impl.h @@ -0,0 +1,88 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.4 $ + * $Date: 2007/04/30 17:43:09 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file (private version) for the IDABBDPRE + * module, for a band-block-diagonal preconditioner, i.e. a + * block-diagonal matrix with banded blocks, for use with IDA + * and an IDASPILS linear solver. + * ----------------------------------------------------------------- + */ + +#ifndef _IDABBDPRE_IMPL_H +#define _IDABBDPRE_IMPL_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * Definition of IBBDPrecData + * ----------------------------------------------------------------- + */ + +typedef struct IBBDPrecDataRec { + + /* passed by user to IDABBDPrecAlloc and used by + IDABBDPrecSetup/IDABBDPrecSolve functions */ + + int mudq, mldq, mukeep, mlkeep; + realtype rel_yy; + IDABBDLocalFn glocal; + IDABBDCommFn gcomm; + + /* allocated for use by IDABBDPrecSetup */ + + N_Vector tempv4; + + /* set by IDABBDPrecon and used by IDABBDPrecSolve */ + + DlsMat PP; + int *pivots; + + /* set by IDABBDPrecAlloc and used by IDABBDPrecSetup */ + + int n_local; + + /* available for optional output */ + + long int rpwsize; + long int ipwsize; + long int nge; + + /* pointer to ida_mem */ + + void *ida_mem; + +} *IBBDPrecData; + +/* + * ----------------------------------------------------------------- + * IDABBDPRE error messages + * ----------------------------------------------------------------- + */ + +#define MSGBBD_MEM_NULL "Integrator memory is NULL." +#define MSGBBD_LMEM_NULL "Linear solver memory is NULL. One of the SPILS linear solvers must be attached." +#define MSGBBD_MEM_FAIL "A memory request failed." +#define MSGBBD_BAD_NVECTOR "A required vector operation is not implemented." +#define MSGBBD_PMEM_NULL "BBD peconditioner memory is NULL. IDABBDPrecInit must be called." +#define MSGBBD_FUNC_FAILED "The Glocal or Gcomm routine failed in an unrecoverable manner." + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/src/ida/ida_dense.c b/odemex/Parser/CVode/ida_src/src/ida/ida_dense.c new file mode 100644 index 0000000..10e5485 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/ida_dense.c @@ -0,0 +1,301 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.11 $ + * $Date: 2009/02/17 02:42:29 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the IDADENSE linear solver. + * ----------------------------------------------------------------- + */ + +#include +#include +#include + +#include +#include "ida_direct_impl.h" +#include "ida_impl.h" + +#include + +/* Constants */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) +#define TWO RCONST(2.0) + +/* IDADENSE linit, lsetup, lsolve, and lfree routines */ + +static int IDADenseInit(IDAMem IDA_mem); + +static int IDADenseSetup(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp, + N_Vector rrp, N_Vector tmp1, + N_Vector tmp2, N_Vector tmp3); + +static int IDADenseSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight, + N_Vector ycur, N_Vector ypcur, N_Vector rrcur); + +static int IDADenseFree(IDAMem IDA_mem); + +/* Readability Replacements */ + +#define res (IDA_mem->ida_res) +#define tn (IDA_mem->ida_tn) +#define hh (IDA_mem->ida_hh) +#define cj (IDA_mem->ida_cj) +#define cjratio (IDA_mem->ida_cjratio) +#define ewt (IDA_mem->ida_ewt) +#define constraints (IDA_mem->ida_constraints) +#define linit (IDA_mem->ida_linit) +#define lsetup (IDA_mem->ida_lsetup) +#define lsolve (IDA_mem->ida_lsolve) +#define lperf (IDA_mem->ida_lperf) +#define lfree (IDA_mem->ida_lfree) +#define lmem (IDA_mem->ida_lmem) +#define setupNonNull (IDA_mem->ida_setupNonNull) +#define vec_tmpl (IDA_mem->ida_tempv1) + +#define mtype (idadls_mem->d_type) +#define neq (idadls_mem->d_n) +#define jacDQ (idadls_mem->d_jacDQ) +#define djac (idadls_mem->d_djac) +#define JJ (idadls_mem->d_J) +#define pivots (idadls_mem->d_pivots) +#define nje (idadls_mem->d_nje) +#define nreDQ (idadls_mem->d_nreDQ) +#define jacdata (idadls_mem->d_J_data) +#define last_flag (idadls_mem->d_last_flag) + +/* + * ----------------------------------------------------------------- + * IDADense + * ----------------------------------------------------------------- + * This routine initializes the memory record and sets various function + * fields specific to the IDADENSE linear solver module. + * IDADense first calls the existing lfree routine if this is not NULL. + * Then it sets the ida_linit, ida_lsetup, ida_lsolve, ida_lperf, and + * ida_lfree fields in (*IDA_mem) to be IDADenseInit, IDADenseSetup, + * IDADenseSolve, NULL, and IDADenseFree, respectively. + * It allocates memory for a structure of type IDADlsMemRec and sets + * the ida_lmem field in (*IDA_mem) to the address of this structure. + * It sets setupNonNull in (*IDA_mem) to TRUE, sets the d_jdata field + * in the IDADlsMemRec structure to be the input parameter jdata, + * and sets the d_jac field to be: + * (1) the input parameter djac, if djac != NULL, or + * (2) IDADenseDQJac, if djac == NULL. + * Finally, it allocates memory for JJ and pivots. + * The return value is IDADLS_SUCCESS = 0, IDADLS_LMEM_FAIL = -1, + * or IDADLS_ILL_INPUT = -2. + * + * NOTE: The dense linear solver assumes a serial implementation + * of the NVECTOR package. Therefore, IDADense will first + * test for a compatible N_Vector internal + * representation by checking that the functions N_VGetArrayPointer + * and N_VSetArrayPointer exist. + * ----------------------------------------------------------------- + */ + +int IDADense(void *ida_mem, int Neq) +{ + IDAMem IDA_mem; + IDADlsMem idadls_mem; + int flag; + + /* Return immediately if ida_mem is NULL. */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDADLS_MEM_NULL, "IDADENSE", "IDADense", MSGD_IDAMEM_NULL); + return(IDADLS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + /* Test if the NVECTOR package is compatible with the DENSE solver */ + if(vec_tmpl->ops->nvgetarraypointer == NULL || + vec_tmpl->ops->nvsetarraypointer == NULL) { + IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDADENSE", "IDADense", MSGD_BAD_NVECTOR); + return(IDADLS_ILL_INPUT); + } + + if (lfree != NULL) flag = lfree(IDA_mem); + + /* Set five main function fields in IDA_mem. */ + linit = IDADenseInit; + lsetup = IDADenseSetup; + lsolve = IDADenseSolve; + lperf = NULL; + lfree = IDADenseFree; + + /* Get memory for IDADlsMemRec. */ + idadls_mem = NULL; + idadls_mem = (IDADlsMem) malloc(sizeof(struct IDADlsMemRec)); + if (idadls_mem == NULL) { + IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDADENSE", "IDADense", MSGD_MEM_FAIL); + return(IDADLS_MEM_FAIL); + } + + /* Set matrix type */ + mtype = SUNDIALS_DENSE; + + /* Set default Jacobian routine and Jacobian data */ + jacDQ = TRUE; + djac = NULL; + jacdata = NULL; + + last_flag = IDADLS_SUCCESS; + + setupNonNull = TRUE; + + /* Store problem size */ + neq = Neq; + + /* Allocate memory for JJ and pivot array. */ + JJ = NULL; + JJ = NewDenseMat(Neq, Neq); + if (JJ == NULL) { + IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDADENSE", "IDADense", MSGD_MEM_FAIL); + free(idadls_mem); idadls_mem = NULL; + return(IDADLS_MEM_FAIL); + } + + pivots = NULL; + pivots = NewIntArray(Neq); + if (pivots == NULL) { + IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDADENSE", "IDADense", MSGD_MEM_FAIL); + DestroyMat(JJ); + free(idadls_mem); idadls_mem = NULL; + return(IDADLS_MEM_FAIL); + } + + /* Attach linear solver memory to the integrator memory */ + lmem = idadls_mem; + + return(IDADLS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * IDADENSE interface functions + * ----------------------------------------------------------------- + */ + +/* + This routine does remaining initializations specific to the IDADENSE + linear solver module. It returns 0. +*/ + +static int IDADenseInit(IDAMem IDA_mem) +{ + IDADlsMem idadls_mem; + + idadls_mem = (IDADlsMem) lmem; + + + nje = 0; + nreDQ = 0; + + if (jacDQ) { + djac = idaDlsDenseDQJac; + jacdata = IDA_mem; + } else { + jacdata = IDA_mem->ida_user_data; + } + + last_flag = 0; + return(0); +} + +/* + This routine does the setup operations for the IDADENSE linear + solver module. It calls the Jacobian evaluation routine, + updates counters, and calls the dense LU factorization routine. + The return value is either + IDADLS_SUCCESS = 0 if successful, + +1 if the jac routine failed recoverably or the + LU factorization failed, or + -1 if the jac routine failed unrecoverably. +*/ + +static int IDADenseSetup(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp, + N_Vector rrp, N_Vector tmp1, N_Vector tmp2, + N_Vector tmp3) +{ + int retval; + long int retfac; + IDADlsMem idadls_mem; + + idadls_mem = (IDADlsMem) lmem; + + /* Increment nje counter. */ + nje++; + + /* Zero out JJ; call Jacobian routine jac; return if it failed. */ + SetToZero(JJ); + retval = djac(neq, tn, cj, yyp, ypp, rrp, JJ, jacdata, + tmp1, tmp2, tmp3); + if (retval < 0) { + IDAProcessError(IDA_mem, IDADLS_JACFUNC_UNRECVR, "IDADENSE", "IDADenseSetup", MSGD_JACFUNC_FAILED); + last_flag = IDADLS_JACFUNC_UNRECVR; + return(-1); + } + if (retval > 0) { + last_flag = IDADLS_JACFUNC_RECVR; + return(+1); + } + + /* Do LU factorization of JJ; return success or fail flag. */ + retfac = DenseGETRF(JJ, pivots); + + if (retfac != 0) { + last_flag = retfac; + return(+1); + } + last_flag = IDADLS_SUCCESS; + return(0); +} + +/* + This routine handles the solve operation for the IDADENSE linear + solver module. It calls the dense backsolve routine, scales the + solution vector according to cjratio, then returns IDADLS_SUCCESS = 0. +*/ + +static int IDADenseSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight, + N_Vector ycur, N_Vector ypcur, N_Vector rrcur) +{ + IDADlsMem idadls_mem; + realtype *bd; + + idadls_mem = (IDADlsMem) lmem; + + bd = N_VGetArrayPointer(b); + + DenseGETRS(JJ, pivots, bd); + + /* Scale the correction to account for change in cj. */ + if (cjratio != ONE) N_VScale(TWO/(ONE + cjratio), b, b); + + last_flag = 0; + return(0); +} + +/* + This routine frees memory specific to the IDADENSE linear solver. +*/ + +static int IDADenseFree(IDAMem IDA_mem) +{ + IDADlsMem idadls_mem; + + idadls_mem = (IDADlsMem) lmem; + + DestroyMat(JJ); + DestroyArray(pivots); + free(lmem); lmem = NULL; + + return(0); +} diff --git a/odemex/Parser/CVode/ida_src/src/ida/ida_direct.c b/odemex/Parser/CVode/ida_src/src/ida/ida_direct.c new file mode 100644 index 0000000..d7d1ef6 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/ida_direct.c @@ -0,0 +1,546 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.5 $ + * $Date: 2008/04/18 19:42:41 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for an IDADLS linear solver. + * ----------------------------------------------------------------- + */ + +/* + * ================================================================= + * IMPORTED HEADER FILES + * ================================================================= + */ + +#include +#include + +#include "ida_impl.h" +#include "ida_direct_impl.h" +#include + +/* + * ================================================================= + * FUNCTION SPECIFIC CONSTANTS + * ================================================================= + */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) +#define TWO RCONST(2.0) + +/* + * ================================================================= + * READIBILITY REPLACEMENTS + * ================================================================= + */ + +#define res (IDA_mem->ida_res) +#define user_data (IDA_mem->ida_user_data) +#define uround (IDA_mem->ida_uround) +#define nst (IDA_mem->ida_nst) +#define tn (IDA_mem->ida_tn) +#define hh (IDA_mem->ida_hh) +#define cj (IDA_mem->ida_cj) +#define cjratio (IDA_mem->ida_cjratio) +#define ewt (IDA_mem->ida_ewt) +#define constraints (IDA_mem->ida_constraints) + +#define linit (IDA_mem->ida_linit) +#define lsetup (IDA_mem->ida_lsetup) +#define lsolve (IDA_mem->ida_lsolve) +#define lfree (IDA_mem->ida_lfree) +#define lperf (IDA_mem->ida_lperf) +#define lmem (IDA_mem->ida_lmem) +#define tempv (IDA_mem->ida_tempv1) +#define setupNonNull (IDA_mem->ida_setupNonNull) + +#define mtype (idadls_mem->d_type) +#define n (idadls_mem->d_n) +#define ml (idadls_mem->d_ml) +#define mu (idadls_mem->d_mu) +#define smu (idadls_mem->d_smu) +#define jacDQ (idadls_mem->d_jacDQ) +#define djac (idadls_mem->d_djac) +#define bjac (idadls_mem->d_bjac) +#define M (idadls_mem->d_J) +#define pivots (idadls_mem->d_pivots) +#define nje (idadls_mem->d_nje) +#define nreDQ (idadls_mem->d_nreDQ) +#define last_flag (idadls_mem->d_last_flag) + +/* + * ================================================================= + * EXPORTED FUNCTIONS FOR IMPLICIT INTEGRATION + * ================================================================= + */ + +/* + * IDADlsSetDenseJacFn specifies the dense Jacobian function. + */ +int IDADlsSetDenseJacFn(void *ida_mem, IDADlsDenseJacFn jac) +{ + IDAMem IDA_mem; + IDADlsMem idadls_mem; + + /* Return immediately if ida_mem is NULL */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDADLS_MEM_NULL, "IDADLS", "IDADlsSetDenseJacFn", MSGD_IDAMEM_NULL); + return(IDADLS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + if (lmem == NULL) { + IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDADLS", "IDADlsSetDenseJacFn", MSGD_LMEM_NULL); + return(IDADLS_LMEM_NULL); + } + idadls_mem = (IDADlsMem) lmem; + + if (jac != NULL) { + jacDQ = FALSE; + djac = jac; + } else { + jacDQ = TRUE; + } + + return(IDADLS_SUCCESS); +} + +/* + * IDADlsSetBandJacFn specifies the band Jacobian function. + */ +int IDADlsSetBandJacFn(void *ida_mem, IDADlsBandJacFn jac) +{ + IDAMem IDA_mem; + IDADlsMem idadls_mem; + + /* Return immediately if ida_mem is NULL */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDADLS_MEM_NULL, "IDADLS", "IDADlsSetBandJacFn", MSGD_IDAMEM_NULL); + return(IDADLS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + if (lmem == NULL) { + IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDADLS", "IDADlsSetBandJacFn", MSGD_LMEM_NULL); + return(IDADLS_LMEM_NULL); + } + idadls_mem = (IDADlsMem) lmem; + + if (jac != NULL) { + jacDQ = FALSE; + bjac = jac; + } else { + jacDQ = TRUE; + } + + return(IDADLS_SUCCESS); +} + +/* + * IDADlsGetWorkSpace returns the length of workspace allocated for the + * IDALAPACK linear solver. + */ +int IDADlsGetWorkSpace(void *ida_mem, long int *lenrwLS, long int *leniwLS) +{ + IDAMem IDA_mem; + IDADlsMem idadls_mem; + + /* Return immediately if ida_mem is NULL */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDADLS_MEM_NULL, "IDADLS", "IDADlsGetWorkSpace", MSGD_IDAMEM_NULL); + return(IDADLS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + if (lmem == NULL) { + IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDADLS", "IDADlsGetWorkSpace", MSGD_LMEM_NULL); + return(IDADLS_LMEM_NULL); + } + idadls_mem = (IDADlsMem) lmem; + + if (mtype == SUNDIALS_DENSE) { + *lenrwLS = n*n; + *leniwLS = n; + } else if (mtype == SUNDIALS_BAND) { + *lenrwLS = n*(smu + ml + 1); + *leniwLS = n; + } + + return(IDADLS_SUCCESS); +} + +/* + * IDADlsGetNumJacEvals returns the number of Jacobian evaluations. + */ +int IDADlsGetNumJacEvals(void *ida_mem, long int *njevals) +{ + IDAMem IDA_mem; + IDADlsMem idadls_mem; + + /* Return immediately if ida_mem is NULL */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDADLS_MEM_NULL, "IDADLS", "IDADlsGetNumJacEvals", MSGD_IDAMEM_NULL); + return(IDADLS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + if (lmem == NULL) { + IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDADLS", "IDADlsGetNumJacEvals", MSGD_LMEM_NULL); + return(IDADLS_LMEM_NULL); + } + idadls_mem = (IDADlsMem) lmem; + + *njevals = nje; + + return(IDADLS_SUCCESS); +} + +/* + * IDADlsGetNumResEvals returns the number of calls to the DAE function + * needed for the DQ Jacobian approximation. + */ +int IDADlsGetNumResEvals(void *ida_mem, long int *nrevalsLS) +{ + IDAMem IDA_mem; + IDADlsMem idadls_mem; + + /* Return immediately if ida_mem is NULL */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDADLS_MEM_NULL, "IDADLS", "IDADlsGetNumFctEvals", MSGD_IDAMEM_NULL); + return(IDADLS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + if (lmem == NULL) { + IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDADLS", "IDADlsGetNumFctEvals", MSGD_LMEM_NULL); + return(IDADLS_LMEM_NULL); + } + idadls_mem = (IDADlsMem) lmem; + + *nrevalsLS = nreDQ; + + return(IDADLS_SUCCESS); +} + +/* + * IDADlsGetReturnFlagName returns the name associated with a IDALAPACK + * return value. + */ +char *IDADlsGetReturnFlagName(int flag) +{ + char *name; + + name = (char *)malloc(30*sizeof(char)); + + switch(flag) { + case IDADLS_SUCCESS: + sprintf(name,"IDADLS_SUCCESS"); + break; + case IDADLS_MEM_NULL: + sprintf(name,"IDADLS_MEM_NULL"); + break; + case IDADLS_LMEM_NULL: + sprintf(name,"IDADLS_LMEM_NULL"); + break; + case IDADLS_ILL_INPUT: + sprintf(name,"IDADLS_ILL_INPUT"); + break; + case IDADLS_MEM_FAIL: + sprintf(name,"IDADLS_MEM_FAIL"); + break; + case IDADLS_JACFUNC_UNRECVR: + sprintf(name,"IDADLS_JACFUNC_UNRECVR"); + break; + case IDADLS_JACFUNC_RECVR: + sprintf(name,"IDADLS_JACFUNC_RECVR"); + break; + default: + sprintf(name,"NONE"); + } + + return(name); +} + +/* + * IDADlsGetLastFlag returns the last flag set in a IDALAPACK function. + */ +int IDADlsGetLastFlag(void *ida_mem, int *flag) +{ + IDAMem IDA_mem; + IDADlsMem idadls_mem; + + /* Return immediately if ida_mem is NULL */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDADLS_MEM_NULL, "IDADLS", "IDADlsGetLastFlag", MSGD_IDAMEM_NULL); + return(IDADLS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + if (lmem == NULL) { + IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDADLS", "IDADlsGetLastFlag", MSGD_LMEM_NULL); + return(IDADLS_LMEM_NULL); + } + idadls_mem = (IDADlsMem) lmem; + + *flag = last_flag; + + return(IDADLS_SUCCESS); +} + +/* + * ================================================================= + * DQ JACOBIAN APPROXIMATIONS + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * idaDlsDenseDQJac + * ----------------------------------------------------------------- + * This routine generates a dense difference quotient approximation to + * the Jacobian F_y + c_j*F_y'. It assumes that a dense matrix of type + * DlsMat is stored column-wise, and that elements within each column + * are contiguous. The address of the jth column of J is obtained via + * the macro LAPACK_DENSE_COL and this pointer is associated with an N_Vector + * using the N_VGetArrayPointer/N_VSetArrayPointer functions. + * Finally, the actual computation of the jth column of the Jacobian is + * done with a call to N_VLinearSum. + * ----------------------------------------------------------------- + */ +int idaDlsDenseDQJac(int N, realtype tt, realtype c_j, + N_Vector yy, N_Vector yp, N_Vector rr, + DlsMat Jac, void *data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + realtype inc, inc_inv, yj, ypj, srur, conj; + realtype *tmp2_data, *y_data, *yp_data, *ewt_data, *cns_data = NULL; + N_Vector rtemp, jthCol; + int j; + int retval = 0; + + IDAMem IDA_mem; + IDADlsMem idadls_mem; + + /* data points to IDA_mem */ + IDA_mem = (IDAMem) data; + idadls_mem = (IDADlsMem) lmem; + + /* Save pointer to the array in tmp2 */ + tmp2_data = N_VGetArrayPointer(tmp2); + + /* Rename work vectors for readibility */ + rtemp = tmp1; + jthCol = tmp2; + + /* Obtain pointers to the data for ewt, yy, yp. */ + ewt_data = N_VGetArrayPointer(ewt); + y_data = N_VGetArrayPointer(yy); + yp_data = N_VGetArrayPointer(yp); + if(constraints!=NULL) cns_data = N_VGetArrayPointer(constraints); + + srur = RSqrt(uround); + + for (j=0; j < N; j++) { + + /* Generate the jth col of J(tt,yy,yp) as delta(F)/delta(y_j). */ + + /* Set data address of jthCol, and save y_j and yp_j values. */ + N_VSetArrayPointer(DENSE_COL(Jac,j), jthCol); + yj = y_data[j]; + ypj = yp_data[j]; + + /* Set increment inc to y_j based on sqrt(uround)*abs(y_j), with + adjustments using yp_j and ewt_j if this is small, and a further + adjustment to give it the same sign as hh*yp_j. */ + + inc = MAX( srur * MAX( ABS(yj), ABS(hh*ypj) ) , ONE/ewt_data[j] ); + + if (hh*ypj < ZERO) inc = -inc; + inc = (yj + inc) - yj; + + /* Adjust sign(inc) again if y_j has an inequality constraint. */ + if (constraints != NULL) { + conj = cns_data[j]; + if (ABS(conj) == ONE) {if((yj+inc)*conj < ZERO) inc = -inc;} + else if (ABS(conj) == TWO) {if((yj+inc)*conj <= ZERO) inc = -inc;} + } + + /* Increment y_j and yp_j, call res, and break on error return. */ + y_data[j] += inc; + yp_data[j] += c_j*inc; + + retval = res(tt, yy, yp, rtemp, user_data); + nreDQ++; + if (retval != 0) break; + + /* Construct difference quotient in jthCol */ + inc_inv = ONE/inc; + N_VLinearSum(inc_inv, rtemp, -inc_inv, rr, jthCol); + + DENSE_COL(Jac,j) = N_VGetArrayPointer(jthCol); + + /* reset y_j, yp_j */ + y_data[j] = yj; + yp_data[j] = ypj; + } + + /* Restore original array pointer in tmp2 */ + N_VSetArrayPointer(tmp2_data, tmp2); + + return(retval); + +} + +/* + * ----------------------------------------------------------------- + * idaDlsBandDQJac + * ----------------------------------------------------------------- + * This routine generates a banded difference quotient approximation JJ + * to the DAE system Jacobian J. It assumes that a band matrix of type + * BandMat is stored column-wise, and that elements within each column + * are contiguous. The address of the jth column of JJ is obtained via + * the macros BAND_COL and BAND_COL_ELEM. The columns of the Jacobian are + * constructed using mupper + mlower + 1 calls to the res routine, and + * appropriate differencing. + * The return value is either IDABAND_SUCCESS = 0, or the nonzero value returned + * by the res routine, if any. + */ + +int idaDlsBandDQJac(int N, int mupper, int mlower, + realtype tt, realtype c_j, + N_Vector yy, N_Vector yp, N_Vector rr, + DlsMat Jac, void *data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + realtype inc, inc_inv, yj, ypj, srur, conj, ewtj; + realtype *y_data, *yp_data, *ewt_data, *cns_data = NULL; + realtype *ytemp_data, *yptemp_data, *rtemp_data, *r_data, *col_j; + int group; + + N_Vector rtemp, ytemp, yptemp; + int i, j, i1, i2, width, ngroups; + int retval = 0; + + IDAMem IDA_mem; + IDADlsMem idadls_mem; + + /* data points to IDA_mem */ + IDA_mem = (IDAMem) data; + idadls_mem = (IDADlsMem) lmem; + + rtemp = tmp1; /* Rename work vector for use as the perturbed residual. */ + + ytemp = tmp2; /* Rename work vector for use as a temporary for yy. */ + + + yptemp= tmp3; /* Rename work vector for use as a temporary for yp. */ + + /* Obtain pointers to the data for all eight vectors used. */ + + ewt_data = N_VGetArrayPointer(ewt); + r_data = N_VGetArrayPointer(rr); + y_data = N_VGetArrayPointer(yy); + yp_data = N_VGetArrayPointer(yp); + + rtemp_data = N_VGetArrayPointer(rtemp); + ytemp_data = N_VGetArrayPointer(ytemp); + yptemp_data = N_VGetArrayPointer(yptemp); + + if (constraints != NULL) cns_data = N_VGetArrayPointer(constraints); + + /* Initialize ytemp and yptemp. */ + + N_VScale(ONE, yy, ytemp); + N_VScale(ONE, yp, yptemp); + + /* Compute miscellaneous values for the Jacobian computation. */ + + srur = RSqrt(uround); + width = mlower + mupper + 1; + ngroups = MIN(width, N); + + /* Loop over column groups. */ + for (group=1; group <= ngroups; group++) { + + /* Increment all yy[j] and yp[j] for j in this group. */ + + for (j=group-1; j + +/* + * ================================================================= + * I D A D I R E C T I N T E R N A L C O N S T A N T S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Types : IDADlsMemRec, IDADlsMem + * ----------------------------------------------------------------- + * IDADlsMem is pointer to a IDADlsMemRec structure. + * ----------------------------------------------------------------- + */ + +typedef struct IDADlsMemRec { + + int d_type; /* Type of Jacobians (DENSE or BAND) */ + + int d_n; /* problem dimension */ + + int d_ml; /* b_ml = lower bandwidth of savedJ */ + int d_mu; /* b_mu = upper bandwidth of savedJ */ + int d_smu; /* upper bandwith of M = MIN(N-1,b_mu+b_ml) */ + + booleantype d_jacDQ; /* TRUE if using internal DQ Jacobian approx. */ + IDADlsDenseJacFn d_djac; /* dense Jacobian routine to be called */ + IDADlsBandJacFn d_bjac; /* band Jacobian routine to be called */ + void *d_J_data; /* J_data is passed to djac or bjac */ + + DlsMat d_J; /* J = dF/dy + cj*dF/dy' */ + int *d_pivots; /* pivots = pivot array for PM = LU */ + + long int d_nje; /* nje = no. of calls to jac */ + + long int d_nreDQ; /* no. of calls to res due to DQ Jacobian approx.*/ + + int d_last_flag; /* last error return flag */ + +} *IDADlsMem; + +/* + * ----------------------------------------------------------------- + * Prototypes of internal functions + * ----------------------------------------------------------------- + */ + +int idaDlsDenseDQJac(int N, realtype tt, realtype c_j, + N_Vector yy, N_Vector yp, N_Vector rr, + DlsMat Jac, void *data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +int idaDlsBandDQJac(int N, int mupper, int mlower, + realtype tt, realtype c_j, + N_Vector yy, N_Vector yp, N_Vector rr, + DlsMat Jac, void *data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +/* + * ================================================================= + * E R R O R M E S S A G E S + * ================================================================= + */ + +#define MSGD_IDAMEM_NULL "Integrator memory is NULL." +#define MSGD_BAD_NVECTOR "A required vector operation is not implemented." +#define MSGD_BAD_SIZES "Illegal bandwidth parameter(s). Must have 0 <= ml, mu <= N-1." +#define MSGD_MEM_FAIL "A memory request failed." +#define MSGD_LMEM_NULL "Linear solver memory is NULL." +#define MSGD_JACFUNC_FAILED "The Jacobian routine failed in an unrecoverable manner." + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/src/ida/ida_ic.c b/odemex/Parser/CVode/ida_src/src/ida/ida_ic.c new file mode 100644 index 0000000..43bafc2 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/ida_ic.c @@ -0,0 +1,728 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.3 $ + * $Date: 2007/04/30 19:29:00 $ + * ----------------------------------------------------------------- + * Programmers: Alan C. Hindmarsh, and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California + * Produced at the Lawrence Livermore National Laboratory + * All rights reserved + * For details, see the LICENSE file + * ----------------------------------------------------------------- + * This is the implementation file for the IC calculation for IDA. + * It is independent of the linear solver in use. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "ida_impl.h" +#include + +/* Macro: loop */ +#define loop for(;;) + +/* + * ================================================================= + * IDA Constants + * ================================================================= + */ + +/* Private Constants */ + +#define ZERO RCONST(0.0) /* real 0.0 */ +#define HALF RCONST(0.5) /* real 0.5 */ +#define ONE RCONST(1.0) /* real 1.0 */ +#define TWO RCONST(2.0) /* real 2.0 */ +#define PT99 RCONST(0.99) /* real 0.99 */ +#define PT1 RCONST(0.1) /* real 0.1 */ +#define PT001 RCONST(0.001) /* real 0.001 */ + +/* IDACalcIC control constants */ + +#define ICRATEMAX RCONST(0.9) /* max. Newton conv. rate */ +#define ALPHALS RCONST(0.0001) /* alpha in linesearch conv. test */ + +/* Return values for lower level routines used by IDACalcIC */ + +#define IC_FAIL_RECOV 1 +#define IC_CONSTR_FAILED 2 +#define IC_LINESRCH_FAILED 3 +#define IC_CONV_FAIL 4 +#define IC_SLOW_CONVRG 5 + +/* + * ================================================================= + * Private Helper Functions Prototypes + * ================================================================= + */ + +extern int IDAInitialSetup(IDAMem IDA_mem); +extern realtype IDAWrmsNorm(IDAMem IDA_mem, N_Vector x, N_Vector w, + booleantype mask); + +static int IDAnlsIC(IDAMem IDA_mem); +static int IDANewtonIC(IDAMem IDA_mem); +static int IDALineSrch(IDAMem IDA_mem, realtype *delnorm, realtype *fnorm); +static int IDAfnorm(IDAMem IDA_mem, realtype *fnorm); +static int IDANewyyp(IDAMem IDA_mem, realtype lambda); +static int IDANewy(IDAMem IDA_mem); +static int IDAICFailFlag(IDAMem IDA_mem, int retval); + +/* + * ================================================================= + * Readibility Constants + * ================================================================= + */ + +#define t0 (IDA_mem->ida_t0) +#define yy0 (IDA_mem->ida_yy0) +#define yp0 (IDA_mem->ida_yp0) + +#define user_data (IDA_mem->ida_user_data) +#define res (IDA_mem->ida_res) +#define efun (IDA_mem->ida_efun) +#define edata (IDA_mem->ida_edata) +#define uround (IDA_mem->ida_uround) +#define phi (IDA_mem->ida_phi) +#define ewt (IDA_mem->ida_ewt) +#define delta (IDA_mem->ida_delta) +#define ee (IDA_mem->ida_ee) +#define savres (IDA_mem->ida_savres) +#define tempv2 (IDA_mem->ida_tempv2) +#define hh (IDA_mem->ida_hh) +#define tn (IDA_mem->ida_tn) +#define cj (IDA_mem->ida_cj) +#define cjratio (IDA_mem->ida_cjratio) +#define nbacktr (IDA_mem->ida_nbacktr) +#define nre (IDA_mem->ida_nre) +#define ncfn (IDA_mem->ida_ncfn) +#define nni (IDA_mem->ida_nni) +#define nsetups (IDA_mem->ida_nsetups) +#define ns (IDA_mem->ida_ns) +#define lsetup (IDA_mem->ida_lsetup) +#define lsolve (IDA_mem->ida_lsolve) +#define hused (IDA_mem->ida_hused) +#define epsNewt (IDA_mem->ida_epsNewt) +#define id (IDA_mem->ida_id) +#define setupNonNull (IDA_mem->ida_setupNonNull) +#define suppressalg (IDA_mem->ida_suppressalg) +#define constraints (IDA_mem->ida_constraints) +#define constraintsSet (IDA_mem->ida_constraintsSet) + +#define epiccon (IDA_mem->ida_epiccon) +#define maxnh (IDA_mem->ida_maxnh) +#define maxnj (IDA_mem->ida_maxnj) +#define maxnit (IDA_mem->ida_maxnit) +#define lsoff (IDA_mem->ida_lsoff) +#define steptol (IDA_mem->ida_steptol) + +/* + * ================================================================= + * EXPORTED FUNCTIONS IMPLEMENTATION + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * IDACalcIC + * ----------------------------------------------------------------- + * IDACalcIC computes consistent initial conditions, given the + * user's initial guess for unknown components of yy0 and/or yp0. + * + * The return value is IDA_SUCCESS = 0 if no error occurred. + * + * The error return values (fully described in ida.h) are: + * IDA_MEM_NULL ida_mem is NULL + * IDA_NO_MALLOC ida_mem was not allocated + * IDA_ILL_INPUT bad value for icopt, tout1, or id + * IDA_LINIT_FAIL the linear solver linit routine failed + * IDA_BAD_EWT zero value of some component of ewt + * IDA_RES_FAIL res had a non-recoverable error + * IDA_FIRST_RES_FAIL res failed recoverably on the first call + * IDA_LSETUP_FAIL lsetup had a non-recoverable error + * IDA_LSOLVE_FAIL lsolve had a non-recoverable error + * IDA_NO_RECOVERY res, lsetup, or lsolve had a recoverable + * error, but IDACalcIC could not recover + * IDA_CONSTR_FAIL the inequality constraints could not be met + * IDA_LINESEARCH_FAIL the linesearch failed (on steptol test) + * IDA_CONV_FAIL the Newton iterations failed to converge + * ----------------------------------------------------------------- + */ + +int IDACalcIC(void *ida_mem, int icopt, realtype tout1) +{ + int ewtsetOK; + int ier, nwt, nh, mxnh, icret, retval=0; + realtype tdist, troundoff, minid, hic, ypnorm; + IDAMem IDA_mem; + + /* Check if IDA memory exists */ + + if(ida_mem == NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDACalcIC", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + /* Check if problem was malloc'ed */ + + if(IDA_mem->ida_MallocDone == FALSE) { + IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDA", "IDACalcIC", MSG_NO_MALLOC); + return(IDA_NO_MALLOC); + } + + /* Check inputs to IDA for correctness and consistency */ + + ier = IDAInitialSetup(IDA_mem); + if(ier != IDA_SUCCESS) return(IDA_ILL_INPUT); + IDA_mem->ida_SetupDone = TRUE; + + /* Check legality of input arguments, and set IDA memory copies. */ + + if(icopt != IDA_YA_YDP_INIT && icopt != IDA_Y_INIT) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDACalcIC", MSG_IC_BAD_ICOPT); + return(IDA_ILL_INPUT); + } + IDA_mem->ida_icopt = icopt; + + if(icopt == IDA_YA_YDP_INIT && (id == NULL)) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDACalcIC", MSG_IC_MISSING_ID); + return(IDA_ILL_INPUT); + } + + tdist = ABS(tout1 - tn); + troundoff = TWO*uround*(ABS(tn) + ABS(tout1)); + if(tdist < troundoff) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDACalcIC", MSG_IC_TOO_CLOSE); + return(IDA_ILL_INPUT); + } + + /* Allocate space and initialize temporary vectors */ + + yy0 = N_VClone(ee); + yp0 = N_VClone(ee); + t0 = tn; + N_VScale(ONE, phi[0], yy0); + N_VScale(ONE, phi[1], yp0); + + /* For use in the IDA_YA_YP_INIT case, set sysindex and tscale. */ + + IDA_mem->ida_sysindex = 1; + IDA_mem->ida_tscale = tdist; + if(icopt == IDA_YA_YDP_INIT) { + minid = N_VMin(id); + if(minid < ZERO) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDACalcIC", MSG_IC_BAD_ID); + return(IDA_ILL_INPUT); + } + if(minid > HALF) IDA_mem->ida_sysindex = 0; + } + + /* Set the test constant in the Newton convergence test */ + + IDA_mem->ida_epsNewt = epiccon; + + /* Initializations: + cjratio = 1 (for use in direct linear solvers); + set nbacktr = 0; */ + + cjratio = ONE; + nbacktr = 0; + + /* Set hic, hh, cj, and mxnh. */ + + hic = PT001*tdist; + ypnorm = IDAWrmsNorm(IDA_mem, yp0, ewt, suppressalg); + if(ypnorm > HALF/hic) hic = HALF/ypnorm; + if(tout1 < tn) hic = -hic; + hh = hic; + if(icopt == IDA_YA_YDP_INIT) { + cj = ONE/hic; + mxnh = maxnh; + } + else { + cj = ZERO; + mxnh = 1; + } + + /* Loop over nwt = number of evaluations of ewt vector. */ + + for(nwt = 1; nwt <= 2; nwt++) { + + /* Loop over nh = number of h values. */ + for(nh = 1; nh <= mxnh; nh++) { + + /* Call the IC nonlinear solver function. */ + retval = IDAnlsIC(IDA_mem); + + /* Cut h and loop on recoverable IDA_YA_YDP_INIT failure; else break. */ + if(retval == IDA_SUCCESS) break; + ncfn++; + if(retval < 0) break; + if(nh == mxnh) break; + /* If looping to try again, reset yy0 and yp0 if not converging. */ + if(retval != IC_SLOW_CONVRG) { + N_VScale(ONE, phi[0], yy0); + N_VScale(ONE, phi[1], yp0); + } + hic *= PT1; + cj = ONE/hic; + hh = hic; + } /* End of nh loop */ + + /* Break on failure; else reset ewt, save yy0, yp0 in phi, and loop. */ + if(retval != IDA_SUCCESS) break; + ewtsetOK = efun(yy0, ewt, edata); + if(ewtsetOK != 0) { + retval = IDA_BAD_EWT; + break; + } + N_VScale(ONE, yy0, phi[0]); + N_VScale(ONE, yp0, phi[1]); + + } /* End of nwt loop */ + + /* Free temporary space */ + + N_VDestroy(yy0); + N_VDestroy(yp0); + + /* Load the optional outputs. */ + + if(icopt == IDA_YA_YDP_INIT) hused = hic; + + /* On any failure, print message and return proper flag. */ + + if(retval != IDA_SUCCESS) { + icret = IDAICFailFlag(IDA_mem, retval); + return(icret); + } + + /* Otherwise return success flag. */ + + return(IDA_SUCCESS); + +} + +/* + * ================================================================= + * PRIVATE FUNCTIONS IMPLEMENTATION + * ================================================================= + */ + +#define icopt (IDA_mem->ida_icopt) +#define sysindex (IDA_mem->ida_sysindex) +#define tscale (IDA_mem->ida_tscale) +#define ynew (IDA_mem->ida_ynew) +#define ypnew (IDA_mem->ida_ypnew) +#define delnew (IDA_mem->ida_delnew) +#define dtemp (IDA_mem->ida_dtemp) + +/* + * ----------------------------------------------------------------- + * IDAnlsIC + * ----------------------------------------------------------------- + * IDAnlsIC solves a nonlinear system for consistent initial + * conditions. It calls IDANewtonIC to do most of the work. + * + * The return value is IDA_SUCCESS = 0 if no error occurred. + * The error return values (positive) considered recoverable are: + * IC_FAIL_RECOV if res, lsetup, or lsolve failed recoverably + * IC_CONSTR_FAILED if the constraints could not be met + * IC_LINESRCH_FAILED if the linesearch failed (on steptol test) + * IC_CONV_FAIL if the Newton iterations failed to converge + * IC_SLOW_CONVRG if the iterations are converging slowly + * (failed the convergence test, but showed + * norm reduction or convergence rate < 1) + * The error return values (negative) considered non-recoverable are: + * IDA_RES_FAIL if res had a non-recoverable error + * IDA_FIRST_RES_FAIL if res failed recoverably on the first call + * IDA_LSETUP_FAIL if lsetup had a non-recoverable error + * IDA_LSOLVE_FAIL if lsolve had a non-recoverable error + * ----------------------------------------------------------------- + */ + +static int IDAnlsIC (IDAMem IDA_mem) +{ + int retval, nj; + N_Vector tv1, tv2, tv3; + + tv1 = ee; + tv2 = tempv2; + tv3 = phi[2]; + + retval = res(t0, yy0, yp0, delta, user_data); + nre++; + if(retval < 0) return(IDA_RES_FAIL); + if(retval > 0) return(IDA_FIRST_RES_FAIL); + + N_VScale(ONE, delta, savres); + + /* Loop over nj = number of linear solve Jacobian setups. */ + + for(nj = 1; nj <= maxnj; nj++) { + + /* If there is a setup routine, call it. */ + if(setupNonNull) { + nsetups++; + retval = lsetup(IDA_mem, yy0, yp0, delta, tv1, tv2, tv3); + if(retval < 0) return(IDA_LSETUP_FAIL); + if(retval > 0) return(IC_FAIL_RECOV); + } + + /* Call the Newton iteration routine, and return if successful. */ + retval = IDANewtonIC(IDA_mem); + if(retval == IDA_SUCCESS) return(IDA_SUCCESS); + + /* If converging slowly and lsetup is nontrivial, retry. */ + if(retval == IC_SLOW_CONVRG && setupNonNull) { + N_VScale(ONE, savres, delta); + continue; + } else { + return(retval); + } + + } /* End of nj loop */ + + /* No convergence after maxnj tries; return with retval=IC_SLOW_CONVRG */ + return(retval); + +} + +/* + * ----------------------------------------------------------------- + * IDANewtonIC + * ----------------------------------------------------------------- + * IDANewtonIC performs the Newton iteration to solve for consistent + * initial conditions. It calls IDALineSrch within each iteration. + * On return, savres contains the current residual vector. + * + * The return value is IDA_SUCCESS = 0 if no error occurred. + * The error return values (positive) considered recoverable are: + * IC_FAIL_RECOV if res or lsolve failed recoverably + * IC_CONSTR_FAILED if the constraints could not be met + * IC_LINESRCH_FAILED if the linesearch failed (on steptol test) + * IC_CONV_FAIL if the Newton iterations failed to converge + * IC_SLOW_CONVRG if the iterations appear to be converging slowly. + * They failed the convergence test, but showed + * an overall norm reduction (by a factor of < 0.1) + * or a convergence rate <= ICRATEMAX). + * The error return values (negative) considered non-recoverable are: + * IDA_RES_FAIL if res had a non-recoverable error + * IDA_LSOLVE_FAIL if lsolve had a non-recoverable error + * ----------------------------------------------------------------- + */ + +static int IDANewtonIC(IDAMem IDA_mem) +{ + int retval, mnewt; + realtype delnorm, fnorm, fnorm0, oldfnrm, rate; + + /* Set pointer for vector delnew */ + delnew = phi[2]; + + /* Call the linear solve function to get the Newton step, delta. */ + retval = lsolve(IDA_mem, delta, ewt, yy0, yp0, savres); + if(retval < 0) return(IDA_LSOLVE_FAIL); + if(retval > 0) return(IC_FAIL_RECOV); + + /* Compute the norm of the step; return now if this is small. */ + fnorm = IDAWrmsNorm(IDA_mem, delta, ewt, FALSE); + if(sysindex == 0) fnorm *= tscale*ABS(cj); + if(fnorm <= epsNewt) return(IDA_SUCCESS); + fnorm0 = fnorm; + + /* Initialize rate to avoid compiler warning message */ + rate = ZERO; + + /* Newton iteration loop */ + + for(mnewt = 0; mnewt < maxnit; mnewt++) { + + nni++; + delnorm = fnorm; + oldfnrm = fnorm; + + /* Call the Linesearch function and return if it failed. */ + retval = IDALineSrch(IDA_mem, &delnorm, &fnorm); + if(retval != IDA_SUCCESS) return(retval); + + /* Set the observed convergence rate and test for convergence. */ + rate = fnorm/oldfnrm; + if(fnorm <= epsNewt) return(IDA_SUCCESS); + + /* If not converged, copy new step vector, and loop. */ + N_VScale(ONE, delnew, delta); + + } /* End of Newton iteration loop */ + + /* Return either IC_SLOW_CONVRG or recoverable fail flag. */ + if(rate <= ICRATEMAX || fnorm < PT1*fnorm0) return(IC_SLOW_CONVRG); + return(IC_CONV_FAIL); + +} + + +/* + * ----------------------------------------------------------------- + * IDALineSrch + * ----------------------------------------------------------------- + * IDALineSrch performs the Linesearch algorithm with the + * calculation of consistent initial conditions. + * + * On entry, yy0 and yp0 are the current values of y and y', the + * Newton step is delta, the current residual vector F is savres, + * delnorm is WRMS-norm(delta), and fnorm is the norm of the vector + * J-inverse F. + * + * On a successful return, yy0, yp0, and savres have been updated, + * delnew contains the current value of J-inverse F, and fnorm is + * WRMS-norm(delnew). + * + * The return value is IDA_SUCCESS = 0 if no error occurred. + * The error return values (positive) considered recoverable are: + * IC_FAIL_RECOV if res or lsolve failed recoverably + * IC_CONSTR_FAILED if the constraints could not be met + * IC_LINESRCH_FAILED if the linesearch failed (on steptol test) + * The error return values (negative) considered non-recoverable are: + * IDA_RES_FAIL if res had a non-recoverable error + * IDA_LSOLVE_FAIL if lsolve had a non-recoverable error + * ----------------------------------------------------------------- + */ + +static int IDALineSrch(IDAMem IDA_mem, realtype *delnorm, realtype *fnorm) +{ + booleantype conOK; + int retval; + realtype f1norm, fnormp, f1normp, ratio, lambda, minlam, slpi; + N_Vector mc; + + /* Initialize work space pointers, f1norm, ratio. + (Use of mc in constraint check does not conflict with ypnew.) */ + mc = ee; + dtemp = phi[3]; + ynew = tempv2; + ypnew = ee; + f1norm = (*fnorm)*(*fnorm)*HALF; + ratio = ONE; + + /* If there are constraints, check and reduce step if necessary. */ + if(constraintsSet) { + + /* Update y and check constraints. */ + IDANewy(IDA_mem); + conOK = N_VConstrMask(constraints, ynew, mc); + + if(!conOK) { + /* Not satisfied. Compute scaled step to satisfy constraints. */ + N_VProd(mc, delta, dtemp); + ratio = PT99*N_VMinQuotient(yy0, dtemp); + (*delnorm) *= ratio; + if((*delnorm) <= steptol) return(IC_CONSTR_FAILED); + N_VScale(ratio, delta, delta); + } + + } /* End of constraints check */ + + slpi = -TWO*f1norm*ratio; + minlam = steptol/(*delnorm); + lambda = ONE; + + /* In IDA_Y_INIT case, set ypnew = yp0 (fixed) for linesearch. */ + if(icopt == IDA_Y_INIT) N_VScale(ONE, yp0, ypnew); + + /* Loop on linesearch variable lambda. */ + + loop { + + /* Get new (y,y') = (ynew,ypnew) and norm of new function value. */ + IDANewyyp(IDA_mem, lambda); + retval = IDAfnorm(IDA_mem, &fnormp); + if(retval != IDA_SUCCESS) return(retval); + + /* If lsoff option is on, break out. */ + if(lsoff) break; + + /* Do alpha-condition test. */ + f1normp = fnormp*fnormp*HALF; + if(f1normp <= f1norm + ALPHALS*slpi*lambda) break; + if(lambda < minlam) return(IC_LINESRCH_FAILED); + lambda /= TWO; + nbacktr++; + + } /* End of breakout linesearch loop */ + + /* Update yy0, yp0, and fnorm, then return. */ + N_VScale(ONE, ynew, yy0); + if(icopt == IDA_YA_YDP_INIT) N_VScale(ONE, ypnew, yp0); + *fnorm = fnormp; + return(IDA_SUCCESS); + +} + +/* + * ----------------------------------------------------------------- + * IDAfnorm + * ----------------------------------------------------------------- + * IDAfnorm computes the norm of the current function value, by + * evaluating the DAE residual function, calling the linear + * system solver, and computing a WRMS-norm. + * + * On return, savres contains the current residual vector F, and + * delnew contains J-inverse F. + * + * The return value is IDA_SUCCESS = 0 if no error occurred, or + * IC_FAIL_RECOV if res or lsolve failed recoverably, or + * IDA_RES_FAIL if res had a non-recoverable error, or + * IDA_LSOLVE_FAIL if lsolve had a non-recoverable error. + * ----------------------------------------------------------------- + */ + +static int IDAfnorm(IDAMem IDA_mem, realtype *fnorm) +{ + + int retval; + + /* Get residual vector F, return if failed, and save F in savres. */ + retval = res(t0, ynew, ypnew, delnew, user_data); + nre++; + if(retval < 0) return(IDA_RES_FAIL); + if(retval > 0) return(IC_FAIL_RECOV); + + N_VScale(ONE, delnew, savres); + + /* Call the linear solve function to get J-inverse F; return if failed. */ + retval = lsolve(IDA_mem, delnew, ewt, ynew, ypnew, savres); + if(retval < 0) return(IDA_LSOLVE_FAIL); + if(retval > 0) return(IC_FAIL_RECOV); + + /* Compute the WRMS-norm; rescale if index = 0. */ + *fnorm = IDAWrmsNorm(IDA_mem, delnew, ewt, FALSE); + if(sysindex == 0) (*fnorm) *= tscale*ABS(cj); + + return(IDA_SUCCESS); + +} + +/* + * ----------------------------------------------------------------- + * IDANewyyp + * ----------------------------------------------------------------- + * IDANewyyp updates the vectors ynew and ypnew from yy0 and yp0, + * using the current step vector lambda*delta, in a manner + * depending on icopt and the input id vector. + * + * The return value is always IDA_SUCCESS = 0. + * ----------------------------------------------------------------- + */ + +static int IDANewyyp(IDAMem IDA_mem, realtype lambda) +{ + + /* IDA_YA_YDP_INIT case: ynew = yy0 - lambda*delta where id_i = 0 + ypnew = yp0 - cj*lambda*delta where id_i = 1. */ + if(icopt == IDA_YA_YDP_INIT) { + N_VProd(id, delta, dtemp); + N_VLinearSum(ONE, yp0, -cj*lambda, dtemp, ypnew); + N_VLinearSum(ONE, delta, -ONE, dtemp, dtemp); + N_VLinearSum(ONE, yy0, -lambda, dtemp, ynew); + return(IDA_SUCCESS); + } + + /* IDA_Y_INIT case: ynew = yy0 - lambda*delta. (ypnew = yp0 preset.) */ + N_VLinearSum(ONE, yy0, -lambda, delta, ynew); + return(IDA_SUCCESS); + +} + +/* + * ----------------------------------------------------------------- + * IDANewy + * ----------------------------------------------------------------- + * IDANewy updates the vector ynew from yy0, + * using the current step vector delta, in a manner + * depending on icopt and the input id vector. + * + * The return value is always IDA_SUCCESS = 0. + * ----------------------------------------------------------------- + */ + +static int IDANewy(IDAMem IDA_mem) +{ + + /* IDA_YA_YDP_INIT case: ynew = yy0 - delta where id_i = 0. */ + if(icopt == IDA_YA_YDP_INIT) { + N_VProd(id, delta, dtemp); + N_VLinearSum(ONE, delta, -ONE, dtemp, dtemp); + N_VLinearSum(ONE, yy0, -ONE, dtemp, ynew); + return(IDA_SUCCESS); + } + + /* IDA_Y_INIT case: ynew = yy0 - delta. */ + N_VLinearSum(ONE, yy0, -ONE, delta, ynew); + return(IDA_SUCCESS); + +} + +/* + * ----------------------------------------------------------------- + * IDAICFailFlag + * ----------------------------------------------------------------- + * IDAICFailFlag prints a message and sets the IDACalcIC return + * value appropriate to the flag retval returned by IDAnlsIC. + * ----------------------------------------------------------------- + */ + +static int IDAICFailFlag(IDAMem IDA_mem, int retval) +{ + + /* Depending on retval, print error message and return error flag. */ + switch(retval) { + + case IDA_RES_FAIL: + IDAProcessError(IDA_mem, IDA_RES_FAIL, "IDA", "IDACalcIC", MSG_IC_RES_NONREC); + return(IDA_RES_FAIL); + + case IDA_FIRST_RES_FAIL: + IDAProcessError(IDA_mem, IDA_FIRST_RES_FAIL, "IDA", "IDACalcIC", MSG_IC_RES_FAIL); + return(IDA_FIRST_RES_FAIL); + + case IDA_LSETUP_FAIL: + IDAProcessError(IDA_mem, IDA_LSETUP_FAIL, "IDA", "IDACalcIC", MSG_IC_SETUP_FAIL); + return(IDA_LSETUP_FAIL); + + case IDA_LSOLVE_FAIL: + IDAProcessError(IDA_mem, IDA_LSOLVE_FAIL, "IDA", "IDACalcIC", MSG_IC_SOLVE_FAIL); + return(IDA_LSOLVE_FAIL); + + case IC_FAIL_RECOV: + IDAProcessError(IDA_mem, IDA_NO_RECOVERY, "IDA", "IDACalcIC", MSG_IC_NO_RECOVERY); + return(IDA_NO_RECOVERY); + + case IC_CONSTR_FAILED: + IDAProcessError(IDA_mem, IDA_CONSTR_FAIL, "IDA", "IDACalcIC", MSG_IC_FAIL_CONSTR); + return(IDA_CONSTR_FAIL); + + case IC_LINESRCH_FAILED: + IDAProcessError(IDA_mem, IDA_LINESEARCH_FAIL, "IDA", "IDACalcIC", MSG_IC_FAILED_LINS); + return(IDA_LINESEARCH_FAIL); + + case IC_CONV_FAIL: + IDAProcessError(IDA_mem, IDA_CONV_FAIL, "IDA", "IDACalcIC", MSG_IC_CONV_FAILED); + return(IDA_CONV_FAIL); + + case IC_SLOW_CONVRG: + IDAProcessError(IDA_mem, IDA_CONV_FAIL, "IDA", "IDACalcIC", MSG_IC_CONV_FAILED); + return(IDA_CONV_FAIL); + + case IDA_BAD_EWT: + IDAProcessError(IDA_mem, IDA_BAD_EWT, "IDA", "IDACalcIC", MSG_IC_BAD_EWT); + return(IDA_BAD_EWT); + + } + return -99; +} + diff --git a/odemex/Parser/CVode/ida_src/src/ida/ida_impl.h b/odemex/Parser/CVode/ida_src/src/ida/ida_impl.h new file mode 100644 index 0000000..497e52b --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/ida_impl.h @@ -0,0 +1,483 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.14 $ + * $Date: 2008/10/15 22:04:21 $ + * ----------------------------------------------------------------- + * Programmer(s): Allan G. Taylor, Alan C. Hindmarsh, Radu Serban, + * and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file (private version) for the main IDA solver. + * ----------------------------------------------------------------- + */ + +#ifndef _IDA_IMPL_H +#define _IDA_IMPL_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +#include + +/* + * ================================================================= + * M A I N I N T E G R A T O R M E M O R Y B L O C K + * ================================================================= + */ + + +/* Basic IDA constants */ + +#define HMAX_INV_DEFAULT RCONST(0.0) /* hmax_inv default value */ +#define MAXORD_DEFAULT 5 /* maxord default value */ +#define MXORDP1 6 /* max. number of N_Vectors in phi */ +#define MXSTEP_DEFAULT 500 /* mxstep default value */ + +/* + * ---------------------------------------------------------------- + * Types : struct IDAMemRec, IDAMem + * ---------------------------------------------------------------- + * The type IDAMem is type pointer to struct IDAMemRec. This + * structure contains fields to keep track of problem state. + * ---------------------------------------------------------------- + */ + +typedef struct IDAMemRec { + + realtype ida_uround; /* machine unit roundoff */ + + /* Problem Specification Data */ + + IDAResFn ida_res; /* F(t,y(t),y'(t))=0; the function F */ + void *ida_user_data; /* user pointer passed to res */ + + int ida_itol; /* itol = IDA_SS, IDA_SV, IDA_WF, IDA_NN */ + realtype ida_rtol; /* relative tolerance */ + realtype ida_Satol; /* scalar absolute tolerance */ + N_Vector ida_Vatol; /* vector absolute tolerance */ + booleantype ida_user_efun; /* TRUE if user provides efun */ + IDAEwtFn ida_efun; /* function to set ewt */ + void *ida_edata; /* user pointer passed to efun */ + double tMax; /* Maximum integration time, Added by Joep Vanlier */ + + booleantype ida_setupNonNull; /* Does setup do something? */ + booleantype ida_constraintsSet; /* constraints vector present: + do constraints calc */ + booleantype ida_suppressalg; /* true means suppress algebraic vars + in local error tests */ + + /* Divided differences array and associated minor arrays */ + + N_Vector ida_phi[MXORDP1]; /* phi = (maxord+1) arrays of divided differences */ + + realtype ida_psi[MXORDP1]; /* differences in t (sums of recent step sizes) */ + realtype ida_alpha[MXORDP1]; /* ratios of current stepsize to psi values */ + realtype ida_beta[MXORDP1]; /* ratios of current to previous product of psi's */ + realtype ida_sigma[MXORDP1]; /* product successive alpha values and factorial */ + realtype ida_gamma[MXORDP1]; /* sum of reciprocals of psi values */ + + /* N_Vectors */ + + N_Vector ida_ewt; /* error weight vector */ + N_Vector ida_yy; /* work space for y vector (= user's yret) */ + N_Vector ida_yp; /* work space for y' vector (= user's ypret) */ + N_Vector ida_delta; /* residual vector */ + N_Vector ida_id; /* bit vector for diff./algebraic components */ + N_Vector ida_constraints; /* vector of inequality constraint options */ + N_Vector ida_savres; /* saved residual vector (= tempv1) */ + N_Vector ida_ee; /* accumulated corrections to y vector, but + set equal to estimated local errors upon + successful return */ + N_Vector ida_mm; /* mask vector in constraints tests (= tempv2) */ + N_Vector ida_tempv1; /* work space vector */ + N_Vector ida_tempv2; /* work space vector */ + N_Vector ida_ynew; /* work vector for y in IDACalcIC (= tempv2) */ + N_Vector ida_ypnew; /* work vector for yp in IDACalcIC (= ee) */ + N_Vector ida_delnew; /* work vector for delta in IDACalcIC (= phi[2]) */ + N_Vector ida_dtemp; /* work vector in IDACalcIC (= phi[3]) */ + + /* Variables for use by IDACalcIC*/ + + realtype ida_t0; /* initial t */ + N_Vector ida_yy0; /* initial y vector (user-supplied). */ + N_Vector ida_yp0; /* initial y' vector (user-supplied). */ + + int ida_icopt; /* IC calculation user option */ + booleantype ida_lsoff; /* IC calculation linesearch turnoff option */ + int ida_maxnh; /* max. number of h tries in IC calculation */ + int ida_maxnj; /* max. number of J tries in IC calculation */ + int ida_maxnit; /* max. number of Netwon iterations in IC calc. */ + int ida_nbacktr; /* number of IC linesearch backtrack operations */ + int ida_sysindex; /* computed system index (0 or 1) */ + realtype ida_epiccon; /* IC nonlinear convergence test constant */ + realtype ida_steptol; /* minimum Newton step size in IC calculation */ + realtype ida_tscale; /* time scale factor = abs(tout1 - t0) */ + + /* Tstop information */ + + booleantype ida_tstopset; + realtype ida_tstop; + + /* Step Data */ + + int ida_kk; /* current BDF method order */ + int ida_kused; /* method order used on last successful step */ + int ida_knew; /* order for next step from order decrease decision */ + int ida_phase; /* flag to trigger step doubling in first few steps */ + int ida_ns; /* counts steps at fixed stepsize and order */ + + realtype ida_hin; /* initial step */ + realtype ida_h0u; /* actual initial stepsize */ + realtype ida_hh; /* current step size h */ + realtype ida_hused; /* step size used on last successful step */ + realtype ida_rr; /* rr = hnext / hused */ + realtype ida_tn; /* current internal value of t */ + realtype ida_tretlast; /* value of tret previously returned by IDASolve */ + realtype ida_cj; /* current value of scalar (-alphas/hh) in Jacobian */ + realtype ida_cjlast; /* cj value saved from last successful step */ + realtype ida_cjold; /* cj value saved from last call to lsetup */ + realtype ida_cjratio; /* ratio of cj values: cj/cjold */ + realtype ida_ss; /* scalar used in Newton iteration convergence test */ + realtype ida_epsNewt; /* test constant in Newton convergence test */ + realtype ida_epcon; /* coeficient of the Newton covergence test */ + realtype ida_toldel; /* tolerance in direct test on Newton corrections */ + + /* Limits */ + + int ida_maxncf; /* max numer of convergence failures */ + int ida_maxcor; /* max number of Newton corrections */ + int ida_maxnef; /* max number of error test failures */ + + int ida_maxord; /* max value of method order k: */ + int ida_maxord_alloc; /* value of maxord used when allocating memory */ + long int ida_mxstep; /* max number of internal steps for one user call */ + realtype ida_hmax_inv; /* inverse of max. step size hmax (default = 0.0) */ + + /* Counters */ + + long int ida_nst; /* number of internal steps taken */ + long int ida_nre; /* number of function (res) calls */ + long int ida_ncfn; /* number of corrector convergence failures */ + long int ida_netf; /* number of error test failures */ + long int ida_nni; /* number of Newton iterations performed */ + long int ida_nsetups; /* number of lsetup calls */ + + /* Space requirements for IDA */ + + long int ida_lrw1; /* no. of realtype words in 1 N_Vector */ + long int ida_liw1; /* no. of integer words in 1 N_Vector */ + long int ida_lrw; /* number of realtype words in IDA work vectors */ + long int ida_liw; /* no. of integer words in IDA work vectors */ + + realtype ida_tolsf; /* tolerance scale factor (saved value) */ + + /* Error handler function and error ouput file */ + + IDAErrHandlerFn ida_ehfun; /* Error messages are handled by ehfun */ + void *ida_eh_data; /* dats pointer passed to ehfun */ + FILE *ida_errfp; /* IDA error messages are sent to errfp */ + + /* Flags to verify correct calling sequence */ + + booleantype ida_SetupDone; /* set to FALSE by IDAMalloc and IDAReInit + set to TRUE by IDACalcIC or IDASolve */ + + booleantype ida_VatolMallocDone; + booleantype ida_constraintsMallocDone; + booleantype ida_idMallocDone; + + booleantype ida_MallocDone; /* set to FALSE by IDACreate + set to TRUE by IDAMAlloc + tested by IDAReInit and IDASolve */ + + /* Linear Solver Data */ + + /* Linear Solver functions to be called */ + + int (*ida_linit)(struct IDAMemRec *idamem); + + int (*ida_lsetup)(struct IDAMemRec *idamem, N_Vector yyp, + N_Vector ypp, N_Vector resp, + N_Vector tempv1, N_Vector tempv2, N_Vector tempv3); + + int (*ida_lsolve)(struct IDAMemRec *idamem, N_Vector b, N_Vector weight, + N_Vector ycur, N_Vector ypcur, N_Vector rescur); + + int (*ida_lperf)(struct IDAMemRec *idamem, int perftask); + + int (*ida_lfree)(struct IDAMemRec *idamem); + + /* Linear Solver specific memory */ + + void *ida_lmem; + + /* Flag to indicate successful ida_linit call */ + + booleantype ida_linitOK; + + /* Rootfinding Data */ + + IDARootFn ida_gfun; /* Function g for roots sought */ + int ida_nrtfn; /* number of components of g */ + int *ida_iroots; /* array for root information */ + int *ida_rootdir; /* array specifying direction of zero-crossing */ + realtype ida_tlo; /* nearest endpoint of interval in root search */ + realtype ida_thi; /* farthest endpoint of interval in root search */ + realtype ida_trout; /* t return value from rootfinder routine */ + realtype *ida_glo; /* saved array of g values at t = tlo */ + realtype *ida_ghi; /* saved array of g values at t = thi */ + realtype *ida_grout; /* array of g values at t = trout */ + realtype ida_toutc; /* copy of tout (if NORMAL mode) */ + realtype ida_ttol; /* tolerance on root location */ + int ida_taskc; /* copy of parameter itask */ + int ida_irfnd; /* flag showing whether last step had a root */ + long int ida_nge; /* counter for g evaluations */ + booleantype *ida_gactive; /* array with active/inactive event functions */ + int ida_mxgnull; /* number of warning messages about possible g==0 */ + + +} *IDAMem; + +/* + * ================================================================= + * I N T E R F A C E T O L I N E A R S O L V E R S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * int (*ida_linit)(IDAMem IDA_mem); + * ----------------------------------------------------------------- + * The purpose of ida_linit is to allocate memory for the + * solver-specific fields in the structure *(idamem->ida_lmem) and + * perform any needed initializations of solver-specific memory, + * such as counters/statistics. An (*ida_linit) should return + * 0 if it has successfully initialized the IDA linear solver and + * a non-zero value otherwise. If an error does occur, an appropriate + * message should be sent to the error handler function. + * ---------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * int (*ida_lsetup)(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp, + * N_Vector resp, + * N_Vector tempv1, N_Vector tempv2, N_Vector tempv3); + * ----------------------------------------------------------------- + * The job of ida_lsetup is to prepare the linear solver for + * subsequent calls to ida_lsolve. Its parameters are as follows: + * + * idamem - problem memory pointer of type IDAMem. See the big + * typedef earlier in this file. + * + * + * yyp - the predicted y vector for the current IDA internal + * step. + * + * ypp - the predicted y' vector for the current IDA internal + * step. + * + * resp - F(tn, yyp, ypp). + * + * tempv1, tempv2, tempv3 - temporary N_Vectors provided for use + * by ida_lsetup. + * + * The ida_lsetup routine should return 0 if successful, + * a positive value for a recoverable error, and a negative value + * for an unrecoverable error. + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * int (*ida_lsolve)(IDAMem IDA_mem, N_Vector b, N_Vector weight, + * N_Vector ycur, N_Vector ypcur, N_Vector rescur); + * ----------------------------------------------------------------- + * ida_lsolve must solve the linear equation P x = b, where + * P is some approximation to the system Jacobian + * J = (dF/dy) + cj (dF/dy') + * evaluated at (tn,ycur,ypcur) and the RHS vector b is input. + * The N-vector ycur contains the solver's current approximation + * to y(tn), ypcur contains that for y'(tn), and the vector rescur + * contains the N-vector residual F(tn,ycur,ypcur). + * The solution is to be returned in the vector b. + * + * The ida_lsolve routine should return 0 if successful, + * a positive value for a recoverable error, and a negative value + * for an unrecoverable error. + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * int (*ida_lperf)(IDAMem IDA_mem, int perftask); + * ----------------------------------------------------------------- + * ida_lperf is called two places in IDA where linear solver + * performance data is required by IDA. For perftask = 0, an + * initialization of performance variables is performed, while for + * perftask = 1, the performance is evaluated. + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * int (*ida_lfree)(IDAMem IDA_mem); + * ----------------------------------------------------------------- + * ida_lfree should free up any memory allocated by the linear + * solver. This routine is called once a problem has been + * completed and the linear solver is no longer needed. + * ----------------------------------------------------------------- + */ + +/* + * ================================================================= + * I D A I N T E R N A L F U N C T I O N S + * ================================================================= + */ + +/* Prototype of internal ewtSet function */ + +int IDAEwtSet(N_Vector ycur, N_Vector weight, void *data); + +/* High level error handler */ + +void IDAProcessError(IDAMem IDA_mem, + int error_code, const char *module, const char *fname, + const char *msgfmt, ...); + +/* Prototype of internal errHandler function */ + +void IDAErrHandler(int error_code, const char *module, const char *function, + char *msg, void *data); + +/* + * ================================================================= + * I D A E R R O R M E S S A G E S + * ================================================================= + */ + +#if defined(SUNDIALS_EXTENDED_PRECISION) + +#define MSG_TIME "t = %Lg, " +#define MSG_TIME_H "t = %Lg and h = %Lg, " +#define MSG_TIME_INT "t = %Lg is not between tcur - hu = %Lg and tcur = %Lg." +#define MSG_TIME_TOUT "tout = %Lg" +#define MSG_TIME_TSTOP "tstop = %Lg" + +#elif defined(SUNDIALS_DOUBLE_PRECISION) + +#define MSG_TIME "t = %lg, " +#define MSG_TIME_H "t = %lg and h = %lg, " +#define MSG_TIME_INT "t = %lg is not between tcur - hu = %lg and tcur = %lg." +#define MSG_TIME_TOUT "tout = %lg" +#define MSG_TIME_TSTOP "tstop = %lg" + +#else + +#define MSG_TIME "t = %g, " +#define MSG_TIME_H "t = %g and h = %g, " +#define MSG_TIME_INT "t = %g is not between tcur - hu = %g and tcur = %g." +#define MSG_TIME_TOUT "tout = %g" +#define MSG_TIME_TSTOP "tstop = %g" + +#endif + +/* General errors */ + +#define MSG_MEM_FAIL "A memory request failed." +#define MSG_NO_MEM "ida_mem = NULL illegal." +#define MSG_NO_MALLOC "Attempt to call before IDAMalloc." +#define MSG_BAD_NVECTOR "A required vector operation is not implemented." + +/* Initialization errors */ + +#define MSG_Y0_NULL "y0 = NULL illegal." +#define MSG_YP0_NULL "yp0 = NULL illegal." +#define MSG_BAD_ITOL "Illegal value for itol. The legal values are IDA_SS, IDA_SV, and IDA_WF." +#define MSG_RES_NULL "res = NULL illegal." +#define MSG_BAD_RTOL "reltol < 0 illegal." +#define MSG_ATOL_NULL "abstol = NULL illegal." +#define MSG_BAD_ATOL "Some abstol component < 0.0 illegal." +#define MSG_ROOT_FUNC_NULL "g = NULL illegal." + +#define MSG_MISSING_ID "id = NULL but suppressalg option on." +#define MSG_NO_TOLS "No integration tolerances have been specified." +#define MSG_FAIL_EWT "The user-provide EwtSet function failed." +#define MSG_BAD_EWT "Some initial ewt component = 0.0 illegal." +#define MSG_Y0_FAIL_CONSTR "y0 fails to satisfy constraints." +#define MSG_LSOLVE_NULL "The linear solver's solve routine is NULL." +#define MSG_LINIT_FAIL "The linear solver's init routine failed." + +/* IDACalcIC error messages */ + +#define MSG_IC_BAD_ICOPT "icopt has an illegal value." +#define MSG_IC_MISSING_ID "id = NULL conflicts with icopt." +#define MSG_IC_TOO_CLOSE "tout1 too close to t0 to attempt initial condition calculation." +#define MSG_IC_BAD_ID "id has illegal values." +#define MSG_IC_BAD_EWT "Some initial ewt component = 0.0 illegal." +#define MSG_IC_RES_NONREC "The residual function failed unrecoverably. " +#define MSG_IC_RES_FAIL "The residual function failed at the first call. " +#define MSG_IC_SETUP_FAIL "The linear solver setup failed unrecoverably." +#define MSG_IC_SOLVE_FAIL "The linear solver solve failed unrecoverably." +#define MSG_IC_NO_RECOVERY "The residual routine or the linear setup or solve routine had a recoverable error, but IDACalcIC was unable to recover." +#define MSG_IC_FAIL_CONSTR "Unable to satisfy the inequality constraints." +#define MSG_IC_FAILED_LINS "The linesearch algorithm failed with too small a step." +#define MSG_IC_CONV_FAILED "Newton/Linesearch algorithm failed to converge." + +/* IDASolve error messages */ + +#define MSG_YRET_NULL "yret = NULL illegal." +#define MSG_YPRET_NULL "ypret = NULL illegal." +#define MSG_TRET_NULL "tret = NULL illegal." +#define MSG_BAD_ITASK "itask has an illegal value." +#define MSG_TOO_CLOSE "tout too close to t0 to start integration." +#define MSG_BAD_HINIT "Initial step is not towards tout." +#define MSG_BAD_TSTOP "The value " MSG_TIME_TSTOP " is behind current " MSG_TIME "in the direction of integration." +#define MSG_CLOSE_ROOTS "Root found at and very near " MSG_TIME "." +#define MSG_MAX_STEPS "At " MSG_TIME ", mxstep steps taken before reaching tout." +#define MSG_EWT_NOW_FAIL "At " MSG_TIME "the user-provide EwtSet function failed." +#define MSG_EWT_NOW_BAD "At " MSG_TIME "some ewt component has become <= 0.0." +#define MSG_TOO_MUCH_ACC "At " MSG_TIME "too much accuracy requested." + +#define MSG_BAD_T "Illegal value for t." MSG_TIME_INT +#define MSG_BAD_TOUT "Trouble interpolating at " MSG_TIME_TOUT ". tout too far back in direction of integration." + +#define MSG_ERR_FAILS "At " MSG_TIME_H "the error test failed repeatedly or with |h| = hmin." +#define MSG_CONV_FAILS "At " MSG_TIME_H "the corrector convergence failed repeatedly or with |h| = hmin." +#define MSG_SETUP_FAILED "At " MSG_TIME "the linear solver setup failed unrecoverably." +#define MSG_SOLVE_FAILED "At " MSG_TIME "the linear solver solve failed unrecoverably." +#define MSG_REP_RES_ERR "At " MSG_TIME "repeated recoverable residual errors." +#define MSG_RES_NONRECOV "At " MSG_TIME "the residual function failed unrecoverably." +#define MSG_FAILED_CONSTR "At " MSG_TIME "unable to satisfy inequality constraints." +#define MSG_RTFUNC_FAILED "At " MSG_TIME ", the rootfinding routine failed in an unrecoverable manner." +#define MSG_NO_ROOT "Rootfinding was not initialized." +#define MSG_INACTIVE_ROOTS "At the end of the first step, there are still some root functions identically 0. This warning will not be issued again." + + +/* IDASet* / IDAGet* error messages */ + +#define MSG_NEG_MAXORD "maxord <= 0 illegal." +#define MSG_BAD_MAXORD "Illegal attempt to increase maximum order." +#define MSG_NEG_HMAX "hmax < 0 illegal." +#define MSG_NEG_EPCON "epcon <= 0.0 illegal." +#define MSG_BAD_CONSTR "Illegal values in constraints vector." +#define MSG_BAD_EPICCON "epiccon <= 0.0 illegal." +#define MSG_BAD_MAXNH "maxnh <= 0 illegal." +#define MSG_BAD_MAXNJ "maxnj <= 0 illegal." +#define MSG_BAD_MAXNIT "maxnit <= 0 illegal." +#define MSG_BAD_STEPTOL "steptol <= 0.0 illegal." + +#define MSG_TOO_LATE "IDAGetConsistentIC can only be called before IDASolve." + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/src/ida/ida_io.c b/odemex/Parser/CVode/ida_src/src/ida/ida_io.c new file mode 100644 index 0000000..74a6455 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/ida_io.c @@ -0,0 +1,1152 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.14 $ + * $Date: 2009/02/10 04:15:36 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan Hindmarsh, Radu Serban and + * Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California + * Produced at the Lawrence Livermore National Laboratory + * All rights reserved + * For details, see the LICENSE file + * ----------------------------------------------------------------- + * This is the implementation file for the optional inputs and + * outputs for the IDA solver. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "ida_impl.h" + +#include + +#define ZERO RCONST(0.0) +#define HALF RCONST(0.5) +#define ONE RCONST(1.0) +#define TWOPT5 RCONST(2.5) + +/* + * ================================================================= + * IDA optional input functions + * ================================================================= + */ + +/* + * Readability constants + */ + +#define lrw (IDA_mem->ida_lrw) +#define liw (IDA_mem->ida_liw) +#define lrw1 (IDA_mem->ida_lrw1) +#define liw1 (IDA_mem->ida_liw1) + +int IDASetErrHandlerFn(void *ida_mem, IDAErrHandlerFn ehfun, void *eh_data) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetErrHandlerFn", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + IDA_mem->ida_ehfun = ehfun; + IDA_mem->ida_eh_data = eh_data; + + return(IDA_SUCCESS); +} + + +int IDASetErrFile(void *ida_mem, FILE *errfp) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetErrFile", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + IDA_mem->ida_errfp = errfp; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDASetUserData(void *ida_mem, void *user_data) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetUserData", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + IDA_mem->ida_user_data = user_data; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDASetMaxOrd(void *ida_mem, int maxord) +{ + IDAMem IDA_mem; + int maxord_alloc; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetMaxOrd", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + if (maxord <= 0) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASetMaxOrd", MSG_NEG_MAXORD); + return(IDA_ILL_INPUT); + } + + /* Cannot increase maximum order beyond the value that + was used when allocating memory */ + maxord_alloc = IDA_mem->ida_maxord_alloc; + + if (maxord > maxord_alloc) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASetMaxOrd", MSG_BAD_MAXORD); + return(IDA_ILL_INPUT); + } + + IDA_mem->ida_maxord = MIN(maxord,MAXORD_DEFAULT); + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDASetMaxNumSteps(void *ida_mem, long int mxsteps) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetMaxNumSteps", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + /* Passing mxsteps=0 sets the default. Passing mxsteps<0 disables the test. */ + + if (mxsteps == 0) + IDA_mem->ida_mxstep = MXSTEP_DEFAULT; + else + IDA_mem->ida_mxstep = mxsteps; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDASetInitStep(void *ida_mem, realtype hin) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetInitStep", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + IDA_mem->ida_hin = hin; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDASetMaxStep(void *ida_mem, realtype hmax) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetMaxStep", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + if (hmax < 0) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASetMaxStep", MSG_NEG_HMAX); + return(IDA_ILL_INPUT); + } + + /* Passing 0 sets hmax = infinity */ + if (hmax == ZERO) { + IDA_mem->ida_hmax_inv = HMAX_INV_DEFAULT; + return(IDA_SUCCESS); + } + + IDA_mem->ida_hmax_inv = ONE/hmax; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDASetStopTime(void *ida_mem, realtype tstop) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetStopTime", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + /* If IDASolve was called at least once, test if tstop is legal + * (i.e. if it was not already passed). + * If IDASetStopTime is called before the first call to IDASolve, + * tstop will be checked in IDASolve. */ + if (IDA_mem->ida_nst > 0) { + + if ( (tstop - IDA_mem->ida_tn) * IDA_mem->ida_hh < ZERO ) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASetStopTime", MSG_BAD_TSTOP, IDA_mem->ida_tn); + return(IDA_ILL_INPUT); + } + + } + + IDA_mem->ida_tstop = tstop; + IDA_mem->ida_tstopset = TRUE; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDASetNonlinConvCoef(void *ida_mem, realtype epcon) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetNonlinConvCoef", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + if (epcon <= ZERO) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASetNonlinConvCoef", MSG_NEG_EPCON); + return(IDA_ILL_INPUT); + } + + IDA_mem->ida_epcon = epcon; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDASetMaxErrTestFails(void *ida_mem, int maxnef) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetMaxErrTestFails", MSG_NO_MEM); + return (IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + IDA_mem->ida_maxnef = maxnef; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDASetMaxConvFails(void *ida_mem, int maxncf) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetMaxConvFails", MSG_NO_MEM); + return (IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + IDA_mem->ida_maxncf = maxncf; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDASetMaxNonlinIters(void *ida_mem, int maxcor) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetMaxNonlinIters", MSG_NO_MEM); + return (IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + IDA_mem->ida_maxcor = maxcor; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDASetSuppressAlg(void *ida_mem, booleantype suppressalg) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetSuppressAlg", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + IDA_mem->ida_suppressalg = suppressalg; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDASetId(void *ida_mem, N_Vector id) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetId", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + if (id == NULL) { + if (IDA_mem->ida_idMallocDone) { + N_VDestroy(IDA_mem->ida_id); + lrw -= lrw1; + liw -= liw1; + } + IDA_mem->ida_idMallocDone = FALSE; + return(IDA_SUCCESS); + } + + if ( !(IDA_mem->ida_idMallocDone) ) { + IDA_mem->ida_id = N_VClone(id); + lrw += lrw1; + liw += liw1; + IDA_mem->ida_idMallocDone = TRUE; + } + + /* Load the id vector */ + + N_VScale(ONE, id, IDA_mem->ida_id); + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDASetConstraints(void *ida_mem, N_Vector constraints) +{ + IDAMem IDA_mem; + realtype temptest; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetConstraints", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + if (constraints == NULL) { + if (IDA_mem->ida_constraintsMallocDone) { + N_VDestroy(IDA_mem->ida_constraints); + lrw -= lrw1; + liw -= liw1; + } + IDA_mem->ida_constraintsMallocDone = FALSE; + IDA_mem->ida_constraintsSet = FALSE; + return(IDA_SUCCESS); + } + + /* Test if required vector ops. are defined */ + + if (constraints->ops->nvdiv == NULL || + constraints->ops->nvmaxnorm == NULL || + constraints->ops->nvcompare == NULL || + constraints->ops->nvconstrmask == NULL || + constraints->ops->nvminquotient == NULL) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASetConstraints", MSG_BAD_NVECTOR); + return(IDA_ILL_INPUT); + } + + /* Check the constraints vector */ + + temptest = N_VMaxNorm(constraints); + if((temptest > TWOPT5) || (temptest < HALF)){ + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASetConstraints", MSG_BAD_CONSTR); + return(IDA_ILL_INPUT); + } + + if ( !(IDA_mem->ida_constraintsMallocDone) ) { + IDA_mem->ida_constraints = N_VClone(constraints); + lrw += lrw1; + liw += liw1; + IDA_mem->ida_constraintsMallocDone = TRUE; + } + + /* Load the constraints vector */ + + N_VScale(ONE, constraints, IDA_mem->ida_constraints); + + IDA_mem->ida_constraintsSet = TRUE; + + return(IDA_SUCCESS); +} + +/* + * IDASetRootDirection + * + * Specifies the direction of zero-crossings to be monitored. + * The default is to monitor both crossings. + */ + +int IDASetRootDirection(void *ida_mem, int *rootdir) +{ + IDAMem IDA_mem; + int i, nrt; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetRootDirection", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + nrt = IDA_mem->ida_nrtfn; + if (nrt==0) { + IDAProcessError(NULL, IDA_ILL_INPUT, "IDA", "IDASetRootDirection", MSG_NO_ROOT); + return(IDA_ILL_INPUT); + } + + for(i=0; iida_rootdir[i] = rootdir[i]; + + return(IDA_SUCCESS); +} + +/* + * IDASetNoInactiveRootWarn + * + * Disables issuing a warning if some root function appears + * to be identically zero at the beginning of the integration + */ + +int IDASetNoInactiveRootWarn(void *ida_mem) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetNoInactiveRootWarn", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + IDA_mem->ida_mxgnull = 0; + + return(IDA_SUCCESS); +} + + +/* + * ================================================================= + * IDA IC optional input functions + * ================================================================= + */ + +int IDASetNonlinConvCoefIC(void *ida_mem, realtype epiccon) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetNonlinConvCoefIC", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + if (epiccon <= ZERO) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASetNonlinConvCoefIC", MSG_BAD_EPICCON); + return(IDA_ILL_INPUT); + } + + IDA_mem->ida_epiccon = epiccon; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDASetMaxNumStepsIC(void *ida_mem, int maxnh) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetMaxNumStepsIC", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + if (maxnh <= 0) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASetMaxNumStepsIC", MSG_BAD_MAXNH); + return(IDA_ILL_INPUT); + } + + IDA_mem->ida_maxnh = maxnh; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDASetMaxNumJacsIC(void *ida_mem, int maxnj) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetMaxNumJacsIC", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + if (maxnj <= 0) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASetMaxNumJacsIC", MSG_BAD_MAXNJ); + return(IDA_ILL_INPUT); + } + + IDA_mem->ida_maxnj = maxnj; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDASetMaxNumItersIC(void *ida_mem, int maxnit) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetMaxNumItersIC", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + if (maxnit <= 0) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASetMaxNumItersIC", MSG_BAD_MAXNIT); + return(IDA_ILL_INPUT); + } + + IDA_mem->ida_maxnit = maxnit; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDASetLineSearchOffIC(void *ida_mem, booleantype lsoff) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetLineSearchOffIC", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + IDA_mem->ida_lsoff = lsoff; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDASetStepToleranceIC(void *ida_mem, realtype steptol) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDASetStepToleranceIC", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + if (steptol <= ZERO) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASetStepToleranceIC", MSG_BAD_STEPTOL); + return(IDA_ILL_INPUT); + } + + IDA_mem->ida_steptol = steptol; + + return(IDA_SUCCESS); +} + +/* + * ================================================================= + * Readability constants + * ================================================================= + */ + +#define ewt (IDA_mem->ida_ewt) +#define kk (IDA_mem->ida_kk) +#define hh (IDA_mem->ida_hh) +#define h0u (IDA_mem->ida_h0u) +#define tn (IDA_mem->ida_tn) +#define nbacktr (IDA_mem->ida_nbacktr) +#define nst (IDA_mem->ida_nst) +#define nre (IDA_mem->ida_nre) +#define ncfn (IDA_mem->ida_ncfn) +#define netf (IDA_mem->ida_netf) +#define nni (IDA_mem->ida_nni) +#define nsetups (IDA_mem->ida_nsetups) +#define lrw (IDA_mem->ida_lrw) +#define liw (IDA_mem->ida_liw) +#define kused (IDA_mem->ida_kused) +#define hused (IDA_mem->ida_hused) +#define tolsf (IDA_mem->ida_tolsf) +#define efun (IDA_mem->ida_efun) +#define edata (IDA_mem->ida_edata) +#define nge (IDA_mem->ida_nge) +#define iroots (IDA_mem->ida_iroots) +#define ee (IDA_mem->ida_ee) + +/* + * ================================================================= + * IDA optional input functions + * ================================================================= + */ + +int IDAGetNumSteps(void *ida_mem, long int *nsteps) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetNumSteps", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + *nsteps = nst; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDAGetNumResEvals(void *ida_mem, long int *nrevals) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetNumResEvals", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + *nrevals = nre; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDAGetNumLinSolvSetups(void *ida_mem, long int *nlinsetups) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetNumLinSolvSetups", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + *nlinsetups = nsetups; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDAGetNumErrTestFails(void *ida_mem, long int *netfails) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetNumErrTestFails", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + *netfails = netf; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDAGetNumBacktrackOps(void *ida_mem, long int *nbacktracks) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetNumBacktrackOps", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + *nbacktracks = nbacktr; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDAGetConsistentIC(void *ida_mem, N_Vector yy0, N_Vector yp0) +{ + IDAMem IDA_mem; + + if (ida_mem == NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetConsistentIC", MSG_NO_MEM); + return (IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + if (IDA_mem->ida_kused != 0) { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAGetConsistentIC", MSG_TOO_LATE); + return(IDA_ILL_INPUT); + } + + if(yy0 != NULL) N_VScale(ONE, IDA_mem->ida_phi[0], yy0); + if(yp0 != NULL) N_VScale(ONE, IDA_mem->ida_phi[1], yp0); + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDAGetLastOrder(void *ida_mem, int *klast) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetLastOrder", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + *klast = kused; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDAGetCurrentOrder(void *ida_mem, int *kcur) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetCurrentOrder", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + *kcur = kk; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDAGetActualInitStep(void *ida_mem, realtype *hinused) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetActualInitStep", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + *hinused = h0u; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDAGetLastStep(void *ida_mem, realtype *hlast) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetLastStep", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + *hlast = hused; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDAGetCurrentStep(void *ida_mem, realtype *hcur) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetCurrentStep", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + *hcur = hh; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDAGetCurrentTime(void *ida_mem, realtype *tcur) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetCurrentTime", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + *tcur = tn; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDAGetTolScaleFactor(void *ida_mem, realtype *tolsfact) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetTolScaleFactor", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + *tolsfact = tolsf; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDAGetErrWeights(void *ida_mem, N_Vector eweight) +{ + IDAMem IDA_mem; + + if (ida_mem == NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetErrWeights", MSG_NO_MEM); + return (IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + N_VScale(ONE, ewt, eweight); + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDAGetEstLocalErrors(void *ida_mem, N_Vector ele) +{ + IDAMem IDA_mem; + + if (ida_mem == NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetEstLocalErrors", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + N_VScale(ONE, ee, ele); + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDAGetWorkSpace(void *ida_mem, long int *lenrw, long int *leniw) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetWorkSpace", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + *leniw = liw; + *lenrw = lrw; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDAGetIntegratorStats(void *ida_mem, long int *nsteps, long int *nrevals, + long int *nlinsetups, long int *netfails, + int *klast, int *kcur, realtype *hinused, realtype *hlast, + realtype *hcur, realtype *tcur) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetIntegratorStats", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + *nsteps = nst; + *nrevals = nre; + *nlinsetups = nsetups; + *netfails = netf; + *klast = kused; + *kcur = kk; + *hinused = h0u; + *hlast = hused; + *hcur = hh; + *tcur = tn; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDAGetNumGEvals(void *ida_mem, long int *ngevals) +{ + IDAMem IDA_mem; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetNumGEvals", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + *ngevals = nge; + + return(IDA_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +int IDAGetRootInfo(void *ida_mem, int *rootsfound) +{ + IDAMem IDA_mem; + int i, nrt; + + if (ida_mem==NULL) { + IDAProcessError(NULL, IDA_MEM_NULL, "IDA", "IDAGetRootInfo", MSG_NO_MEM); + return(IDA_MEM_NULL); + } + + IDA_mem = (IDAMem) ida_mem; + + nrt = IDA_mem->ida_nrtfn; + + for (i=0; i +#include + +#include +#include "ida_direct_impl.h" +#include "ida_impl.h" + +#include + +/* + * ================================================================= + * FUNCTION SPECIFIC CONSTANTS + * ================================================================= + */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) +#define TWO RCONST(2.0) + +/* + * ================================================================= + * PROTOTYPES FOR PRIVATE FUNCTIONS + * ================================================================= + */ + +/* IDALAPACK DENSE linit, lsetup, lsolve, and lfree routines */ +static int idaLapackDenseInit(IDAMem IDA_mem); +static int idaLapackDenseSetup(IDAMem IDA_mem, + N_Vector yP, N_Vector ypP, N_Vector fctP, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); +static int idaLapackDenseSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight, + N_Vector yC, N_Vector ypC, N_Vector fctC); +static int idaLapackDenseFree(IDAMem IDA_mem); + +/* IDALAPACK BAND linit, lsetup, lsolve, and lfree routines */ +static int idaLapackBandInit(IDAMem IDA_mem); +static int idaLapackBandSetup(IDAMem IDA_mem, + N_Vector yP, N_Vector ypP, N_Vector fctP, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); +static int idaLapackBandSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight, + N_Vector yC, N_Vector ypC, N_Vector fctC); +static int idaLapackBandFree(IDAMem IDA_mem); + +/* + * ================================================================= + * READIBILITY REPLACEMENTS + * ================================================================= + */ + +#define res (IDA_mem->ida_res) +#define nst (IDA_mem->ida_nst) +#define tn (IDA_mem->ida_tn) +#define hh (IDA_mem->ida_hh) +#define cj (IDA_mem->ida_cj) +#define cjratio (IDA_mem->ida_cjratio) +#define ewt (IDA_mem->ida_ewt) +#define constraints (IDA_mem->ida_constraints) + +#define linit (IDA_mem->ida_linit) +#define lsetup (IDA_mem->ida_lsetup) +#define lsolve (IDA_mem->ida_lsolve) +#define lfree (IDA_mem->ida_lfree) +#define lperf (IDA_mem->ida_lperf) +#define lmem (IDA_mem->ida_lmem) +#define tempv (IDA_mem->ida_tempv1) +#define setupNonNull (IDA_mem->ida_setupNonNull) + +#define mtype (idadls_mem->d_type) +#define n (idadls_mem->d_n) +#define ml (idadls_mem->d_ml) +#define mu (idadls_mem->d_mu) +#define smu (idadls_mem->d_smu) +#define jacDQ (idadls_mem->d_jacDQ) +#define djac (idadls_mem->d_djac) +#define bjac (idadls_mem->d_bjac) +#define JJ (idadls_mem->d_J) +#define pivots (idadls_mem->d_pivots) +#define nje (idadls_mem->d_nje) +#define nreDQ (idadls_mem->d_nreDQ) +#define J_data (idadls_mem->d_J_data) +#define last_flag (idadls_mem->d_last_flag) + +/* + * ================================================================= + * EXPORTED FUNCTIONS FOR IMPLICIT INTEGRATION + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * IDALapackDense + * ----------------------------------------------------------------- + * This routine initializes the memory record and sets various function + * fields specific to the linear solver module. IDALapackDense first + * calls the existing lfree routine if this is not NULL. Then it sets + * the ida_linit, ida_lsetup, ida_lsolve, ida_lfree fields in (*ida_mem) + * to be idaLapackDenseInit, idaLapackDenseSetup, idaLapackDenseSolve, + * and idaLapackDenseFree, respectively. It allocates memory for a + * structure of type IDADlsMemRec and sets the ida_lmem field in + * (*ida_mem) to the address of this structure. It sets setupNonNull + * in (*ida_mem) to TRUE, and the d_jac field to the default + * idaLapackDenseDQJac. Finally, it allocates memory for M, pivots. + * + * The return value is SUCCESS = 0, or LMEM_FAIL = -1. + * + * NOTE: The dense linear solver assumes a serial implementation + * of the NVECTOR package. Therefore, IDALapackDense will first + * test for a compatible N_Vector internal representation + * by checking that N_VGetArrayPointer and N_VSetArrayPointer + * exist. + * ----------------------------------------------------------------- + */ +int IDALapackDense(void *ida_mem, int N) +{ + IDAMem IDA_mem; + IDADlsMem idadls_mem; + + /* Return immediately if ida_mem is NULL */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDADLS_MEM_NULL, "IDALAPACK", "IDALapackDense", MSGD_IDAMEM_NULL); + return(IDADLS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + /* Test if the NVECTOR package is compatible with the LAPACK solver */ + if (tempv->ops->nvgetarraypointer == NULL || + tempv->ops->nvsetarraypointer == NULL) { + IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDALAPACK", "IDALapackDense", MSGD_BAD_NVECTOR); + return(IDADLS_ILL_INPUT); + } + + if (lfree !=NULL) lfree(IDA_mem); + + /* Set four main function fields in IDA_mem */ + linit = idaLapackDenseInit; + lsetup = idaLapackDenseSetup; + lsolve = idaLapackDenseSolve; + lperf = NULL; + lfree = idaLapackDenseFree; + + /* Get memory for IDADlsMemRec */ + idadls_mem = NULL; + idadls_mem = (IDADlsMem) malloc(sizeof(struct IDADlsMemRec)); + if (idadls_mem == NULL) { + IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDALAPACK", "IDALapackDense", MSGD_MEM_FAIL); + return(IDADLS_MEM_FAIL); + } + + /* Set matrix type */ + mtype = SUNDIALS_DENSE; + + /* Set default Jacobian routine and Jacobian data */ + jacDQ = TRUE; + djac = NULL; + J_data = NULL; + + last_flag = IDADLS_SUCCESS; + setupNonNull = TRUE; + + /* Set problem dimension */ + n = N; + + /* Allocate memory for JJ and pivot array */ + JJ = NULL; + pivots = NULL; + + JJ = NewDenseMat(N, N); + if (JJ == NULL) { + IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDALAPACK", "IDALapackDense", MSGD_MEM_FAIL); + free(idadls_mem); + return(IDADLS_MEM_FAIL); + } + pivots = NewIntArray(N); + if (pivots == NULL) { + IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDALAPACK", "IDALapackDense", MSGD_MEM_FAIL); + DestroyMat(JJ); + free(idadls_mem); + return(IDADLS_MEM_FAIL); + } + + /* Attach linear solver memory to integrator memory */ + lmem = idadls_mem; + + return(IDADLS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * IDALapackBand + * ----------------------------------------------------------------- + * This routine initializes the memory record and sets various function + * fields specific to the band linear solver module. It first calls + * the existing lfree routine if this is not NULL. It then sets the + * ida_linit, ida_lsetup, ida_lsolve, and ida_lfree fields in (*ida_mem) + * to be idaLapackBandInit, idaLapackBandSetup, idaLapackBandSolve, + * and idaLapackBandFree, respectively. It allocates memory for a + * structure of type IDALapackBandMemRec and sets the ida_lmem field in + * (*ida_mem) to the address of this structure. It sets setupNonNull + * in (*ida_mem) to be TRUE, mu to be mupper, ml to be mlower, and + * the jacE and jacI field to NULL. + * Finally, it allocates memory for M and pivots. + * The IDALapackBand return value is IDADLS_SUCCESS = 0, + * IDADLS_MEM_FAIL = -1, or IDADLS_ILL_INPUT = -2. + * + * NOTE: The IDALAPACK linear solver assumes a serial implementation + * of the NVECTOR package. Therefore, IDALapackBand will first + * test for compatible a compatible N_Vector internal + * representation by checking that the function + * N_VGetArrayPointer exists. + * ----------------------------------------------------------------- + */ +int IDALapackBand(void *ida_mem, int N, int mupper, int mlower) +{ + IDAMem IDA_mem; + IDADlsMem idadls_mem; + + /* Return immediately if ida_mem is NULL */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDADLS_MEM_NULL, "IDALAPACK", "IDALapackBand", MSGD_IDAMEM_NULL); + return(IDADLS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + /* Test if the NVECTOR package is compatible with the BAND solver */ + if (tempv->ops->nvgetarraypointer == NULL) { + IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDALAPACK", "IDALapackBand", MSGD_BAD_NVECTOR); + return(IDADLS_ILL_INPUT); + } + + if (lfree != NULL) lfree(IDA_mem); + + /* Set four main function fields in IDA_mem */ + linit = idaLapackBandInit; + lsetup = idaLapackBandSetup; + lsolve = idaLapackBandSolve; + lperf = NULL; + lfree = idaLapackBandFree; + + /* Get memory for IDADlsMemRec */ + idadls_mem = NULL; + idadls_mem = (IDADlsMem) malloc(sizeof(struct IDADlsMemRec)); + if (idadls_mem == NULL) { + IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDALAPACK", "IDALapackBand", MSGD_MEM_FAIL); + return(IDADLS_MEM_FAIL); + } + + /* Set matrix type */ + mtype = SUNDIALS_BAND; + + /* Set default Jacobian routine and Jacobian data */ + jacDQ = TRUE; + bjac = NULL; + J_data = NULL; + + last_flag = IDADLS_SUCCESS; + setupNonNull = TRUE; + + /* Load problem dimension */ + n = N; + + /* Load half-bandwiths in idadls_mem */ + ml = mlower; + mu = mupper; + + /* Test ml and mu for legality */ + if ((ml < 0) || (mu < 0) || (ml >= N) || (mu >= N)) { + IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDALAPACK", "IDALapackBand", MSGD_BAD_SIZES); + return(IDADLS_ILL_INPUT); + } + + /* Set extended upper half-bandwith for M (required for pivoting) */ + smu = MIN(N-1, mu + ml); + + /* Allocate memory for JJ and pivot arrays */ + JJ = NULL; + pivots = NULL; + + JJ = NewBandMat(N, mu, ml, smu); + if (JJ == NULL) { + IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDALAPACK", "IDALapackBand", MSGD_MEM_FAIL); + free(idadls_mem); + return(IDADLS_MEM_FAIL); + } + pivots = NewIntArray(N); + if (pivots == NULL) { + IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDALAPACK", "IDALapackBand", MSGD_MEM_FAIL); + DestroyMat(JJ); + free(idadls_mem); + return(IDADLS_MEM_FAIL); + } + + /* Attach linear solver memory to integrator memory */ + lmem = idadls_mem; + + return(IDADLS_SUCCESS); +} + +/* + * ================================================================= + * PRIVATE FUNCTIONS FOR IMPLICIT INTEGRATION WITH DENSE JACOBIANS + * ================================================================= + */ + +/* + * idaLapackDenseInit does remaining initializations specific to the dense + * linear solver. + */ +static int idaLapackDenseInit(IDAMem IDA_mem) +{ + IDADlsMem idadls_mem; + + idadls_mem = (IDADlsMem) lmem; + + nje = 0; + nreDQ = 0; + + if (jacDQ) { + djac = idaDlsDenseDQJac; + J_data = IDA_mem; + } else { + J_data = IDA_mem->ida_user_data; + } + + last_flag = IDADLS_SUCCESS; + return(0); +} + +/* + * idaLapackDenseSetup does the setup operations for the dense linear solver. + * It calls the Jacobian function to obtain the Newton matrix M = F_y + c_j*F_y', + * updates counters, and calls the dense LU factorization routine. + */ +static int idaLapackDenseSetup(IDAMem IDA_mem, + N_Vector yP, N_Vector ypP, N_Vector fctP, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + IDADlsMem idadls_mem; + int ier, retval; + + idadls_mem = (IDADlsMem) lmem; + + /* Call Jacobian function */ + nje++; + SetToZero(JJ); + retval = djac(n, tn, cj, yP, ypP, fctP, JJ, J_data, tmp1, tmp2, tmp3); + if (retval < 0) { + IDAProcessError(IDA_mem, IDADLS_JACFUNC_UNRECVR, "IDALAPACK", "idaLapackDenseSetup", MSGD_JACFUNC_FAILED); + last_flag = IDADLS_JACFUNC_UNRECVR; + return(-1); + } else if (retval > 0) { + last_flag = IDADLS_JACFUNC_RECVR; + return(1); + } + + /* Do LU factorization of M */ + dgetrf_f77(&n, &n, JJ->data, &(JJ->ldim), pivots, &ier); + + /* Return 0 if the LU was complete; otherwise return 1 */ + last_flag = ier; + if (ier > 0) return(1); + return(0); +} + +/* + * idaLapackDenseSolve handles the solve operation for the dense linear solver + * by calling the dense backsolve routine. + */ +static int idaLapackDenseSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight, + N_Vector yC, N_Vector ypC, N_Vector fctC) +{ + IDADlsMem idadls_mem; + realtype *bd, fact; + int ier, one = 1; + + idadls_mem = (IDADlsMem) lmem; + + bd = N_VGetArrayPointer(b); + + dgetrs_f77("N", &n, &one, JJ->data, &(JJ->ldim), pivots, bd, &n, &ier, 1); + if (ier > 0) return(1); + + /* Scale the correction to account for change in cj. */ + if (cjratio != ONE) { + fact = TWO/(ONE + cjratio); + dscal_f77(&n, &fact, bd, &one); + } + + last_flag = IDADLS_SUCCESS; + return(0); +} + +/* + * idaLapackDenseFree frees memory specific to the dense linear solver. + */ +static int idaLapackDenseFree(IDAMem IDA_mem) +{ + IDADlsMem idadls_mem; + + idadls_mem = (IDADlsMem) lmem; + + DestroyMat(JJ); + DestroyArray(pivots); + free(idadls_mem); + idadls_mem = NULL; + + return(0); +} + +/* + * ================================================================= + * PRIVATE FUNCTIONS FOR IMPLICIT INTEGRATION WITH BAND JACOBIANS + * ================================================================= + */ + +/* + * idaLapackBandInit does remaining initializations specific to the band + * linear solver. + */ +static int idaLapackBandInit(IDAMem IDA_mem) +{ + IDADlsMem idadls_mem; + + idadls_mem = (IDADlsMem) lmem; + + nje = 0; + nreDQ = 0; + + if (jacDQ) { + bjac = idaDlsBandDQJac; + J_data = IDA_mem; + } else { + J_data = IDA_mem->ida_user_data; + } + + last_flag = IDADLS_SUCCESS; + return(0); +} + +/* + * idaLapackBandSetup does the setup operations for the band linear solver. + * It calls the Jacobian function to obtain the Newton matrix M = F_y + c_j*F_y', + * updates counters, and calls the band LU factorization routine. + */ +static int idaLapackBandSetup(IDAMem IDA_mem, + N_Vector yP, N_Vector ypP, N_Vector fctP, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + IDADlsMem idadls_mem; + int ier, retval; + + idadls_mem = (IDADlsMem) lmem; + + /* Call Jacobian function */ + nje++; + SetToZero(JJ); + retval = bjac(n, mu, ml, tn, cj, yP, ypP, fctP, JJ, J_data, tmp1, tmp2, tmp3); + if (retval < 0) { + IDAProcessError(IDA_mem, IDADLS_JACFUNC_UNRECVR, "IDALAPACK", "idaLapackBandSetup", MSGD_JACFUNC_FAILED); + last_flag = IDADLS_JACFUNC_UNRECVR; + return(-1); + } else if (retval > 0) { + last_flag = IDADLS_JACFUNC_RECVR; + return(+1); + } + + /* Do LU factorization of M */ + dgbtrf_f77(&n, &n, &ml, &mu, JJ->data, &(JJ->ldim), pivots, &ier); + + /* Return 0 if the LU was complete; otherwise return 1 */ + last_flag = ier; + if (ier > 0) return(1); + return(0); + +} + +/* + * idaLapackBandSolve handles the solve operation for the band linear solver + * by calling the band backsolve routine. + */ +static int idaLapackBandSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight, + N_Vector yC, N_Vector ypC, N_Vector fctC) +{ + IDADlsMem idadls_mem; + realtype *bd, fact; + int ier, one = 1; + + idadls_mem = (IDADlsMem) lmem; + + bd = N_VGetArrayPointer(b); + + dgbtrs_f77("N", &n, &ml, &mu, &one, JJ->data, &(JJ->ldim), pivots, bd, &n, &ier, 1); + if (ier > 0) return(1); + + /* For BDF, scale the correction to account for change in cj */ + if (cjratio != ONE) { + fact = TWO/(ONE + cjratio); + dscal_f77(&n, &fact, bd, &one); + } + + last_flag = IDADLS_SUCCESS; + return(0); +} + +/* + * idaLapackBandFree frees memory specific to the band linear solver. + */ +static int idaLapackBandFree(IDAMem IDA_mem) +{ + IDADlsMem idadls_mem; + + idadls_mem = (IDADlsMem) lmem; + + DestroyMat(JJ); + DestroyArray(pivots); + free(idadls_mem); + idadls_mem = NULL; + + return(0); +} + diff --git a/odemex/Parser/CVode/ida_src/src/ida/ida_spbcgs.c b/odemex/Parser/CVode/ida_src/src/ida/ida_spbcgs.c new file mode 100644 index 0000000..654afd0 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/ida_spbcgs.c @@ -0,0 +1,476 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2007/11/26 16:20:00 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2004, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the IDA scaled preconditioned + * Bi-CGSTAB linear solver module, IDASPBCG. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include "ida_spils_impl.h" +#include "ida_impl.h" + +#include +#include + +/* Constants */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) +#define PT9 RCONST(0.9) +#define PT05 RCONST(0.05) + +/* IDASPBCG linit, lsetup, lsolve, lperf, and lfree routines */ + +static int IDASpbcgInit(IDAMem IDA_mem); + +static int IDASpbcgSetup(IDAMem IDA_mem, + N_Vector yy_p, N_Vector yp_p, N_Vector rr_p, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +static int IDASpbcgSolve(IDAMem IDA_mem, N_Vector bb, N_Vector weight, + N_Vector yy_now, N_Vector yp_now, N_Vector rr_now); + +static int IDASpbcgPerf(IDAMem IDA_mem, int perftask); + +static int IDASpbcgFree(IDAMem IDA_mem); + + +/* Readability Replacements */ + +#define nst (IDA_mem->ida_nst) +#define tn (IDA_mem->ida_tn) +#define cj (IDA_mem->ida_cj) +#define epsNewt (IDA_mem->ida_epsNewt) +#define res (IDA_mem->ida_res) +#define user_data (IDA_mem->ida_user_data) +#define ewt (IDA_mem->ida_ewt) +#define errfp (IDA_mem->ida_errfp) +#define linit (IDA_mem->ida_linit) +#define lsetup (IDA_mem->ida_lsetup) +#define lsolve (IDA_mem->ida_lsolve) +#define lperf (IDA_mem->ida_lperf) +#define lfree (IDA_mem->ida_lfree) +#define lmem (IDA_mem->ida_lmem) +#define nni (IDA_mem->ida_nni) +#define ncfn (IDA_mem->ida_ncfn) +#define setupNonNull (IDA_mem->ida_setupNonNull) +#define vec_tmpl (IDA_mem->ida_tempv1) + +#define sqrtN (idaspils_mem->s_sqrtN) +#define epslin (idaspils_mem->s_epslin) +#define ytemp (idaspils_mem->s_ytemp) +#define yptemp (idaspils_mem->s_yptemp) +#define xx (idaspils_mem->s_xx) +#define ycur (idaspils_mem->s_ycur) +#define ypcur (idaspils_mem->s_ypcur) +#define rcur (idaspils_mem->s_rcur) +#define npe (idaspils_mem->s_npe) +#define nli (idaspils_mem->s_nli) +#define nps (idaspils_mem->s_nps) +#define ncfl (idaspils_mem->s_ncfl) +#define nst0 (idaspils_mem->s_nst0) +#define nni0 (idaspils_mem->s_nni0) +#define nli0 (idaspils_mem->s_nli0) +#define ncfn0 (idaspils_mem->s_ncfn0) +#define ncfl0 (idaspils_mem->s_ncfl0) +#define nwarn (idaspils_mem->s_nwarn) +#define njtimes (idaspils_mem->s_njtimes) +#define nres (idaspils_mem->s_nres) +#define spils_mem (idaspils_mem->s_spils_mem) + +#define jtimesDQ (idaspils_mem->s_jtimesDQ) +#define jtimes (idaspils_mem->s_jtimes) +#define jdata (idaspils_mem->s_jdata) + +#define last_flag (idaspils_mem->s_last_flag) + +/* + * ----------------------------------------------------------------- + * Function : IDASpbcg + * ----------------------------------------------------------------- + * This routine initializes the memory record and sets various function + * fields specific to the IDASPBCG linear solver module. + * + * IDASpbcg first calls the existing lfree routine if this is not NULL. + * It then sets the ida_linit, ida_lsetup, ida_lsolve, ida_lperf, and + * ida_lfree fields in (*IDA_mem) to be IDASpbcgInit, IDASpbcgSetup, + * IDASpbcgSolve, IDASpbcgPerf, and IDASpbcgFree, respectively. + * It allocates memory for a structure of type IDASpilsMemRec and sets + * the ida_lmem field in (*IDA_mem) to the address of this structure. + * It sets setupNonNull in (*IDA_mem). It then sets various fields + * in the IDASpilsMemRec structure. Finally, IDASpbcg allocates memory + * for ytemp, yptemp, and xx, and calls SpbcgMalloc to allocate memory + * for the Spbcg solver. + * + * The return value of IDASpbcg is: + * IDASPILS_SUCCESS = 0 if successful + * IDASPILS_MEM_FAIL = -1 if IDA_mem is NULL or a memory + * allocation failed + * IDASPILS_ILL_INPUT = -2 if a required vector operation is not + * implemented. + * ----------------------------------------------------------------- + */ + +int IDASpbcg(void *ida_mem, int maxl) +{ + IDAMem IDA_mem; + IDASpilsMem idaspils_mem; + SpbcgMem spbcg_mem; + int flag, maxl1; + + /* Return immediately if ida_mem is NULL */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPBCG", "IDASpbcg", MSGS_IDAMEM_NULL); + return(IDASPILS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + /* Check if N_VDotProd is present */ + if (vec_tmpl->ops->nvdotprod == NULL) { + IDAProcessError(NULL, IDASPILS_ILL_INPUT, "IDASPBCG", "IDASpbcg", MSGS_BAD_NVECTOR); + return(IDASPILS_ILL_INPUT); + } + + if (lfree != NULL) flag = lfree((IDAMem) ida_mem); + + /* Set five main function fields in ida_mem */ + linit = IDASpbcgInit; + lsetup = IDASpbcgSetup; + lsolve = IDASpbcgSolve; + lperf = IDASpbcgPerf; + lfree = IDASpbcgFree; + + /* Get memory for IDASpilsMemRec */ + idaspils_mem = NULL; + idaspils_mem = (IDASpilsMem) malloc(sizeof(struct IDASpilsMemRec)); + if (idaspils_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPBCG", "IDASpbcg", MSGS_MEM_FAIL); + return(IDASPILS_MEM_FAIL); + } + + /* Set ILS type */ + idaspils_mem->s_type = SPILS_SPBCG; + + /* Set SPBCG parameters that were passed in call sequence */ + maxl1 = (maxl <= 0) ? IDA_SPILS_MAXL : maxl; + idaspils_mem->s_maxl = maxl1; + + /* Set defaults for Jacobian-related fileds */ + jtimesDQ = TRUE; + jtimes = NULL; + jdata = NULL; + + /* Set defaults for preconditioner-related fields */ + idaspils_mem->s_pset = NULL; + idaspils_mem->s_psolve = NULL; + idaspils_mem->s_pfree = NULL; + idaspils_mem->s_pdata = IDA_mem->ida_user_data; + + /* Set default values for the rest of the Spbcg parameters */ + idaspils_mem->s_eplifac = PT05; + idaspils_mem->s_dqincfac = ONE; + + idaspils_mem->s_last_flag = IDASPILS_SUCCESS; + + /* Set setupNonNull to FALSE */ + setupNonNull = FALSE; + + /* Allocate memory for ytemp, yptemp, and xx */ + + ytemp = N_VClone(vec_tmpl); + if (ytemp == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPBCG", "IDASpbcg", MSGS_MEM_FAIL); + free(idaspils_mem); idaspils_mem = NULL; + return(IDASPILS_MEM_FAIL); + } + + yptemp = N_VClone(vec_tmpl); + if (yptemp == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPBCG", "IDASpbcg", MSGS_MEM_FAIL); + N_VDestroy(ytemp); + free(idaspils_mem); idaspils_mem = NULL; + return(IDASPILS_MEM_FAIL); + } + + xx = N_VClone(vec_tmpl); + if (xx == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPBCG", "IDASpbcg", MSGS_MEM_FAIL); + N_VDestroy(ytemp); + N_VDestroy(yptemp); + free(idaspils_mem); idaspils_mem = NULL; + return(IDASPILS_MEM_FAIL); + } + + /* Compute sqrtN from a dot product */ + N_VConst(ONE, ytemp); + sqrtN = RSqrt(N_VDotProd(ytemp, ytemp)); + + /* Call SpbcgMalloc to allocate workspace for Spbcg */ + spbcg_mem = NULL; + spbcg_mem = SpbcgMalloc(maxl1, vec_tmpl); + if (spbcg_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPBCG", "IDASpbcg", MSGS_MEM_FAIL); + N_VDestroy(ytemp); + N_VDestroy(yptemp); + N_VDestroy(xx); + free(idaspils_mem); idaspils_mem = NULL; + return(IDASPILS_MEM_FAIL); + } + + /* Attach SPBCG memory to spils memory structure */ + spils_mem = (void *)spbcg_mem; + + /* Attach linear solver memory to the integrator memory */ + lmem = idaspils_mem; + + return(IDASPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * IDASPBCG interface routines + * ----------------------------------------------------------------- + */ + +/* Additional readability Replacements */ + +#define maxl (idaspils_mem->s_maxl) +#define eplifac (idaspils_mem->s_eplifac) +#define psolve (idaspils_mem->s_psolve) +#define pset (idaspils_mem->s_pset) +#define pdata (idaspils_mem->s_pdata) + +static int IDASpbcgInit(IDAMem IDA_mem) +{ + IDASpilsMem idaspils_mem; + SpbcgMem spbcg_mem; + + idaspils_mem = (IDASpilsMem) lmem; + spbcg_mem = (SpbcgMem) spils_mem; + + /* Initialize counters */ + npe = nli = nps = ncfl = 0; + njtimes = nres = 0; + + /* Set setupNonNull to TRUE iff there is preconditioning with setup */ + setupNonNull = (psolve != NULL) && (pset != NULL); + + /* Set Jacobian-related fields, based on jtimesDQ */ + if (jtimesDQ) { + jtimes = IDASpilsDQJtimes; + jdata = IDA_mem; + } else { + jdata = user_data; + } + + /* Set maxl in the SPBCG memory in case it was changed by the user */ + spbcg_mem->l_max = maxl; + + last_flag = IDASPILS_SUCCESS; + + return(0); +} + +static int IDASpbcgSetup(IDAMem IDA_mem, + N_Vector yy_p, N_Vector yp_p, N_Vector rr_p, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + int retval; + IDASpilsMem idaspils_mem; + + idaspils_mem = (IDASpilsMem) lmem; + + /* Call user setup routine pset and update counter npe */ + retval = pset(tn, yy_p, yp_p, rr_p, cj, pdata, + tmp1, tmp2, tmp3); + npe++; + + if (retval < 0) { + IDAProcessError(IDA_mem, SPBCG_PSET_FAIL_UNREC, "IDASPBCG", "IDASpbcgSetup", MSGS_PSET_FAILED); + last_flag = SPBCG_PSET_FAIL_UNREC; + return(-1); + } + if (retval > 0) { + last_flag = SPBCG_PSET_FAIL_REC; + return(+1); + } + + last_flag = SPBCG_SUCCESS; + + return(0); +} + +/* + * ----------------------------------------------------------------- + * Function : IDASpbcgSolve + * ----------------------------------------------------------------- + * Note: The x-scaling and b-scaling arrays are both equal to weight. + * + * We set the initial guess, x = 0, then call SpbcgSolve. + * We copy the solution x into b, and update the counters nli, nps, + * and ncfl. If SpbcgSolve returned nli_inc = 0 (hence x = 0), we + * take the SPBCG vtemp vector (= P_inverse F) as the correction + * vector instead. Finally, we set the return value according to the + * success of SpbcgSolve. + * ----------------------------------------------------------------- + */ + +static int IDASpbcgSolve(IDAMem IDA_mem, N_Vector bb, N_Vector weight, + N_Vector yy_now, N_Vector yp_now, N_Vector rr_now) +{ + IDASpilsMem idaspils_mem; + SpbcgMem spbcg_mem; + int pretype, nli_inc, nps_inc, retval; + realtype res_norm; + + idaspils_mem = (IDASpilsMem) lmem; + + spbcg_mem = (SpbcgMem)spils_mem; + + /* Set SpbcgSolve convergence test constant epslin, in terms of the + Newton convergence test constant epsNewt and safety factors. The factor + sqrt(Neq) assures that the Bi-CGSTAB convergence test is applied to the + WRMS norm of the residual vector, rather than the weighted L2 norm. */ + epslin = sqrtN*eplifac*epsNewt; + + /* Set vectors ycur, ypcur, and rcur for use by the Atimes and Psolve */ + ycur = yy_now; + ypcur = yp_now; + rcur = rr_now; + + /* Set SpbcgSolve inputs pretype and initial guess xx = 0 */ + pretype = (psolve == NULL) ? PREC_NONE : PREC_LEFT; + N_VConst(ZERO, xx); + + /* Call SpbcgSolve and copy xx to bb */ + retval = SpbcgSolve(spbcg_mem, IDA_mem, xx, bb, pretype, epslin, + IDA_mem, weight, weight, IDASpilsAtimes, + IDASpilsPSolve, &res_norm, &nli_inc, &nps_inc); + + if (nli_inc == 0) N_VScale(ONE, SPBCG_VTEMP(spbcg_mem), bb); + else N_VScale(ONE, xx, bb); + + /* Increment counters nli, nps, and return if successful */ + nli += nli_inc; + nps += nps_inc; + if (retval != SPBCG_SUCCESS) ncfl++; + + /* Interpret return value from SpbcgSolve */ + + last_flag = retval; + + switch(retval) { + + case SPBCG_SUCCESS: + return(0); + break; + case SPBCG_RES_REDUCED: + return(1); + break; + case SPBCG_CONV_FAIL: + return(1); + break; + case SPBCG_PSOLVE_FAIL_REC: + return(1); + break; + case SPBCG_ATIMES_FAIL_REC: + return(1); + break; + case SPBCG_MEM_NULL: + return(-1); + break; + case SPBCG_ATIMES_FAIL_UNREC: + IDAProcessError(IDA_mem, SPBCG_ATIMES_FAIL_UNREC, "IDaSPBCG", "IDASpbcgSolve", MSGS_JTIMES_FAILED); + return(-1); + break; + case SPBCG_PSOLVE_FAIL_UNREC: + IDAProcessError(IDA_mem, SPBCG_PSOLVE_FAIL_UNREC, "IDASPBCG", "IDASpbcgSolve", MSGS_PSOLVE_FAILED); + return(-1); + break; + } + + return(0); +} + +/* + * ----------------------------------------------------------------- + * Function : IDASpbcgPerf + * ----------------------------------------------------------------- + * This routine handles performance monitoring specific to the + * IDASPBCG linear solver. When perftask = 0, it saves values of + * various counters. When perftask = 1, it examines difference + * quotients in these counters, and depending on their values, it + * prints up to three warning messages. Messages are printed up to + * a maximum of 10 times. + * ----------------------------------------------------------------- + */ + +static int IDASpbcgPerf(IDAMem IDA_mem, int perftask) +{ + IDASpilsMem idaspils_mem; + realtype avdim, rcfn, rcfl; + long int nstd, nnid; + booleantype lavd, lcfn, lcfl; + + idaspils_mem = (IDASpilsMem) lmem; + + if (perftask == 0) { + nst0 = nst; nni0 = nni; nli0 = nli; + ncfn0 = ncfn; ncfl0 = ncfl; + nwarn = 0; + return(0); + } + + nstd = nst - nst0; nnid = nni - nni0; + if (nstd == 0 || nnid == 0) return(0); + avdim = (realtype) ((nli - nli0)/((realtype) nnid)); + rcfn = (realtype) ((ncfn - ncfn0)/((realtype) nstd)); + rcfl = (realtype) ((ncfl - ncfl0)/((realtype) nnid)); + lavd = (avdim > ((realtype) maxl)); + lcfn = (rcfn > PT9); + lcfl = (rcfl > PT9); + if (!(lavd || lcfn || lcfl)) return(0); + nwarn++; + if (nwarn > 10) return(1); + if (lavd) + IDAProcessError(IDA_mem, IDA_WARNING, "IDASPBCG", "IDASpbcgPerf", MSGS_AVD_WARN, tn, avdim); + if (lcfn) + IDAProcessError(IDA_mem, IDA_WARNING, "IDASPBCG", "IDASpbcgPerf", MSGS_CFN_WARN, tn, rcfn); + if (lcfl) + IDAProcessError(IDA_mem, IDA_WARNING, "IDASPBCG", "IDASpbcgPerf", MSGS_CFL_WARN, tn, rcfl); + + return(0); +} + +static int IDASpbcgFree(IDAMem IDA_mem) +{ + IDASpilsMem idaspils_mem; + SpbcgMem spbcg_mem; + + idaspils_mem = (IDASpilsMem) lmem; + + N_VDestroy(ytemp); + N_VDestroy(xx); + + spbcg_mem = (SpbcgMem)spils_mem; + SpbcgFree(spbcg_mem); + + if (idaspils_mem->s_pfree != NULL) (idaspils_mem->s_pfree)(IDA_mem); + + free(idaspils_mem); idaspils_mem = NULL; + + return(0); +} diff --git a/odemex/Parser/CVode/ida_src/src/ida/ida_spgmr.c b/odemex/Parser/CVode/ida_src/src/ida/ida_spgmr.c new file mode 100644 index 0000000..4d47163 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/ida_spgmr.c @@ -0,0 +1,475 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2007/11/26 16:20:00 $ + * ----------------------------------------------------------------- + * Programmers: Alan C. Hindmarsh, and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California + * Produced at the Lawrence Livermore National Laboratory + * All rights reserved + * For details, see the LICENSE file + * ----------------------------------------------------------------- + * This is the implementation file for the IDA Scaled + * Preconditioned GMRES linear solver module, IDASPGMR. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include "ida_spils_impl.h" +#include "ida_impl.h" + +#include +#include + +/* Constants */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) +#define PT9 RCONST(0.9) +#define PT05 RCONST(0.05) + +/* IDASPGMR linit, lsetup, lsolve, lperf, and lfree routines */ + +static int IDASpgmrInit(IDAMem IDA_mem); + +static int IDASpgmrSetup(IDAMem IDA_mem, + N_Vector yy_p, N_Vector yp_p, N_Vector rr_p, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +static int IDASpgmrSolve(IDAMem IDA_mem, N_Vector bb, N_Vector weight, + N_Vector yy_now, N_Vector yp_now, N_Vector rr_now); + +static int IDASpgmrPerf(IDAMem IDA_mem, int perftask); + +static int IDASpgmrFree(IDAMem IDA_mem); + + +/* Readability Replacements */ + +#define nst (IDA_mem->ida_nst) +#define tn (IDA_mem->ida_tn) +#define cj (IDA_mem->ida_cj) +#define epsNewt (IDA_mem->ida_epsNewt) +#define res (IDA_mem->ida_res) +#define user_data (IDA_mem->ida_user_data) +#define ewt (IDA_mem->ida_ewt) +#define errfp (IDA_mem->ida_errfp) +#define linit (IDA_mem->ida_linit) +#define lsetup (IDA_mem->ida_lsetup) +#define lsolve (IDA_mem->ida_lsolve) +#define lperf (IDA_mem->ida_lperf) +#define lfree (IDA_mem->ida_lfree) +#define lmem (IDA_mem->ida_lmem) +#define nni (IDA_mem->ida_nni) +#define ncfn (IDA_mem->ida_ncfn) +#define setupNonNull (IDA_mem->ida_setupNonNull) +#define vec_tmpl (IDA_mem->ida_tempv1) + +#define sqrtN (idaspils_mem->s_sqrtN) +#define epslin (idaspils_mem->s_epslin) +#define ytemp (idaspils_mem->s_ytemp) +#define yptemp (idaspils_mem->s_yptemp) +#define xx (idaspils_mem->s_xx) +#define ycur (idaspils_mem->s_ycur) +#define ypcur (idaspils_mem->s_ypcur) +#define rcur (idaspils_mem->s_rcur) +#define npe (idaspils_mem->s_npe) +#define nli (idaspils_mem->s_nli) +#define nps (idaspils_mem->s_nps) +#define ncfl (idaspils_mem->s_ncfl) +#define nst0 (idaspils_mem->s_nst0) +#define nni0 (idaspils_mem->s_nni0) +#define nli0 (idaspils_mem->s_nli0) +#define ncfn0 (idaspils_mem->s_ncfn0) +#define ncfl0 (idaspils_mem->s_ncfl0) +#define nwarn (idaspils_mem->s_nwarn) +#define njtimes (idaspils_mem->s_njtimes) +#define nres (idaspils_mem->s_nres) +#define spils_mem (idaspils_mem->s_spils_mem) + +#define jtimesDQ (idaspils_mem->s_jtimesDQ) +#define jtimes (idaspils_mem->s_jtimes) +#define jdata (idaspils_mem->s_jdata) + +#define last_flag (idaspils_mem->s_last_flag) + +/* + * ----------------------------------------------------------------- + * IDASpgmr + * ----------------------------------------------------------------- + * + * This routine initializes the memory record and sets various function + * fields specific to the IDASPGMR linear solver module. + * + * IDASpgmr first calls the existing lfree routine if this is not NULL. + * It then sets the ida_linit, ida_lsetup, ida_lsolve, ida_lperf, and + * ida_lfree fields in (*IDA_mem) to be IDASpgmrInit, IDASpgmrSetup, + * IDASpgmrSolve, IDASpgmrPerf, and IDASpgmrFree, respectively. + * It allocates memory for a structure of type IDASpilsMemRec and sets + * the ida_lmem field in (*IDA_mem) to the address of this structure. + * It sets setupNonNull in (*IDA_mem). It then various fields in the + * IDASpilsMemRec structure. Finally, IDASpgmr allocates memory for + * ytemp, yptemp, and xx, and calls SpgmrMalloc to allocate memory + * for the Spgmr solver. + * + * The return value of IDASpgmr is: + * IDASPILS_SUCCESS = 0 if successful + * IDASPILS_MEM_FAIL = -1 if IDA_mem is NULL or a memory allocation failed + * IDASPILS_ILL_INPUT = -2 if the gstype argument is illegal. + * + * ----------------------------------------------------------------- + */ + +int IDASpgmr(void *ida_mem, int maxl) +{ + IDAMem IDA_mem; + IDASpilsMem idaspils_mem; + SpgmrMem spgmr_mem; + int flag, maxl1; + + /* Return immediately if ida_mem is NULL */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPGMR", "IDASpgmr", MSGS_IDAMEM_NULL); + return(IDASPILS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + /* Check if N_VDotProd is present */ + if(vec_tmpl->ops->nvdotprod == NULL) { + IDAProcessError(NULL, IDASPILS_ILL_INPUT, "IDASPGMR", "IDASpgmr", MSGS_BAD_NVECTOR); + return(IDASPILS_ILL_INPUT); + } + + if (lfree != NULL) flag = lfree((IDAMem) ida_mem); + + /* Set five main function fields in ida_mem */ + linit = IDASpgmrInit; + lsetup = IDASpgmrSetup; + lsolve = IDASpgmrSolve; + lperf = IDASpgmrPerf; + lfree = IDASpgmrFree; + + /* Get memory for IDASpilsMemRec */ + idaspils_mem = NULL; + idaspils_mem = (IDASpilsMem) malloc(sizeof(struct IDASpilsMemRec)); + if (idaspils_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPGMR", "IDASpgmr", MSGS_MEM_FAIL); + return(IDASPILS_MEM_FAIL); + } + + /* Set ILS type */ + idaspils_mem->s_type = SPILS_SPGMR; + + /* Set SPGMR parameters that were passed in call sequence */ + maxl1 = (maxl <= 0) ? IDA_SPILS_MAXL : maxl; + idaspils_mem->s_maxl = maxl1; + + /* Set defaults for Jacobian-related fileds */ + jtimesDQ = TRUE; + jtimes = NULL; + jdata = NULL; + + /* Set defaults for preconditioner-related fields */ + idaspils_mem->s_pset = NULL; + idaspils_mem->s_psolve = NULL; + idaspils_mem->s_pfree = NULL; + idaspils_mem->s_pdata = IDA_mem->ida_user_data; + + /* Set default values for the rest of the Spgmr parameters */ + idaspils_mem->s_gstype = MODIFIED_GS; + idaspils_mem->s_maxrs = IDA_SPILS_MAXRS; + idaspils_mem->s_eplifac = PT05; + idaspils_mem->s_dqincfac = ONE; + + idaspils_mem->s_last_flag = IDASPILS_SUCCESS; + + /* Set setupNonNull to FALSE */ + setupNonNull = FALSE; + + /* Allocate memory for ytemp, yptemp, and xx */ + + ytemp = N_VClone(vec_tmpl); + if (ytemp == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPGMR", "IDASpgmr", MSGS_MEM_FAIL); + free(idaspils_mem); idaspils_mem = NULL; + return(IDASPILS_MEM_FAIL); + } + + yptemp = N_VClone(vec_tmpl); + if (yptemp == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPGMR", "IDASpgmr", MSGS_MEM_FAIL); + N_VDestroy(ytemp); + free(idaspils_mem); idaspils_mem = NULL; + return(IDASPILS_MEM_FAIL); + } + + xx = N_VClone(vec_tmpl); + if (xx == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPGMR", "IDASpgmr", MSGS_MEM_FAIL); + N_VDestroy(ytemp); + N_VDestroy(yptemp); + free(idaspils_mem); idaspils_mem = NULL; + return(IDASPILS_MEM_FAIL); + } + + /* Compute sqrtN from a dot product */ + N_VConst(ONE, ytemp); + sqrtN = RSqrt( N_VDotProd(ytemp, ytemp) ); + + /* Call SpgmrMalloc to allocate workspace for Spgmr */ + spgmr_mem = NULL; + spgmr_mem = SpgmrMalloc(maxl1, vec_tmpl); + if (spgmr_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPGMR", "IDASpgmr", MSGS_MEM_FAIL); + N_VDestroy(ytemp); + N_VDestroy(yptemp); + N_VDestroy(xx); + free(idaspils_mem); idaspils_mem = NULL; + return(IDASPILS_MEM_FAIL); + } + + /* Attach SPGMR memory to spils memory structure */ + spils_mem = (void *)spgmr_mem; + + /* Attach linear solver memory to the integrator memory */ + lmem = idaspils_mem; + + return(IDASPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * IDASPGMR interface routines + * ----------------------------------------------------------------- + */ + +/* Additional readability Replacements */ + +#define gstype (idaspils_mem->s_gstype) +#define maxl (idaspils_mem->s_maxl) +#define maxrs (idaspils_mem->s_maxrs) +#define eplifac (idaspils_mem->s_eplifac) +#define psolve (idaspils_mem->s_psolve) +#define pset (idaspils_mem->s_pset) +#define pdata (idaspils_mem->s_pdata) + +static int IDASpgmrInit(IDAMem IDA_mem) +{ + IDASpilsMem idaspils_mem; + + idaspils_mem = (IDASpilsMem) lmem; + + /* Initialize counters */ + npe = nli = nps = ncfl = 0; + njtimes = nres = 0; + + /* Set setupNonNull to TRUE iff there is preconditioning with setup */ + setupNonNull = (psolve != NULL) && (pset != NULL); + + /* Set Jacobian-related fields, based on jtimesDQ */ + if (jtimesDQ) { + jtimes = IDASpilsDQJtimes; + jdata = IDA_mem; + } else { + jdata = user_data; + } + + last_flag = IDASPILS_SUCCESS; + return(0); +} + +static int IDASpgmrSetup(IDAMem IDA_mem, + N_Vector yy_p, N_Vector yp_p, N_Vector rr_p, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + int retval; + IDASpilsMem idaspils_mem; + + idaspils_mem = (IDASpilsMem) lmem; + + /* Call user setup routine pset and update counter npe. */ + retval = pset(tn, yy_p, yp_p, rr_p, cj, pdata, + tmp1, tmp2, tmp3); + npe++; + + /* Return flag showing success or failure of pset. */ + if (retval < 0) { + IDAProcessError(IDA_mem, SPGMR_PSET_FAIL_UNREC, "IDASPGMR", "IDASpgmrSetup", MSGS_PSET_FAILED); + last_flag = SPGMR_PSET_FAIL_UNREC; + return(-1); + } + if (retval > 0) { + last_flag = SPGMR_PSET_FAIL_REC; + return(+1); + } + + last_flag = SPGMR_SUCCESS; + return(0); +} + + +/* + * The x-scaling and b-scaling arrays are both equal to weight. + * + * We set the initial guess, x = 0, then call SpgmrSolve. + * We copy the solution x into b, and update the counters nli, nps, ncfl. + * If SpgmrSolve returned nli_inc = 0 (hence x = 0), we take the SPGMR + * vtemp vector (= P_inverse F) as the correction vector instead. + * Finally, we set the return value according to the success of SpgmrSolve. + */ + +static int IDASpgmrSolve(IDAMem IDA_mem, N_Vector bb, N_Vector weight, + N_Vector yy_now, N_Vector yp_now, N_Vector rr_now) +{ + IDASpilsMem idaspils_mem; + SpgmrMem spgmr_mem; + int pretype, nli_inc, nps_inc, retval; + realtype res_norm; + + idaspils_mem = (IDASpilsMem) lmem; + + spgmr_mem = (SpgmrMem) spils_mem; + + /* Set SpgmrSolve convergence test constant epslin, in terms of the + Newton convergence test constant epsNewt and safety factors. The factor + sqrt(Neq) assures that the GMRES convergence test is applied to the + WRMS norm of the residual vector, rather than the weighted L2 norm. */ + epslin = sqrtN*eplifac*epsNewt; + + /* Set vectors ycur, ypcur, and rcur for use by the Atimes and Psolve */ + ycur = yy_now; + ypcur = yp_now; + rcur = rr_now; + + /* Set SpgmrSolve inputs pretype and initial guess xx = 0. */ + pretype = (psolve == NULL) ? PREC_NONE : PREC_LEFT; + N_VConst(ZERO, xx); + + /* Call SpgmrSolve and copy xx to bb. */ + retval = SpgmrSolve(spgmr_mem, IDA_mem, xx, bb, pretype, gstype, epslin, + maxrs, IDA_mem, weight, weight, IDASpilsAtimes, + IDASpilsPSolve, &res_norm, &nli_inc, &nps_inc); + + if (nli_inc == 0) N_VScale(ONE, SPGMR_VTEMP(spgmr_mem), bb); + else N_VScale(ONE, xx, bb); + + /* Increment counters nli, nps, and return if successful. */ + nli += nli_inc; + nps += nps_inc; + if (retval != SPGMR_SUCCESS) ncfl++; + + /* Interpret return value from SpgmrSolve */ + + last_flag = retval; + + switch(retval) { + + case SPGMR_SUCCESS: + return(0); + break; + case SPGMR_RES_REDUCED: + return(1); + break; + case SPGMR_CONV_FAIL: + return(1); + break; + case SPGMR_QRFACT_FAIL: + return(1); + break; + case SPGMR_PSOLVE_FAIL_REC: + return(1); + break; + case SPGMR_ATIMES_FAIL_REC: + return(1); + break; + case SPGMR_MEM_NULL: + return(-1); + break; + case SPGMR_ATIMES_FAIL_UNREC: + IDAProcessError(IDA_mem, SPGMR_ATIMES_FAIL_UNREC, "IDASPGMR", "IDASpgmrSolve", MSGS_JTIMES_FAILED); + return(-1); + break; + case SPGMR_PSOLVE_FAIL_UNREC: + IDAProcessError(IDA_mem, SPGMR_PSOLVE_FAIL_UNREC, "IDASPGMR", "IDASpgmrSolve", MSGS_PSOLVE_FAILED); + return(-1); + break; + case SPGMR_GS_FAIL: + return(-1); + break; + case SPGMR_QRSOL_FAIL: + return(-1); + break; + } + + return(0); +} + +/* + * This routine handles performance monitoring specific to the IDASPGMR + * linear solver. When perftask = 0, it saves values of various counters. + * When perftask = 1, it examines difference quotients in these counters, + * and depending on their values, it prints up to three warning messages. + * Messages are printed up to a maximum of 10 times. + */ + +static int IDASpgmrPerf(IDAMem IDA_mem, int perftask) +{ + IDASpilsMem idaspils_mem; + realtype avdim, rcfn, rcfl; + long int nstd, nnid; + booleantype lavd, lcfn, lcfl; + + idaspils_mem = (IDASpilsMem) lmem; + + if (perftask == 0) { + nst0 = nst; nni0 = nni; nli0 = nli; + ncfn0 = ncfn; ncfl0 = ncfl; + nwarn = 0; + return(0); + } + + nstd = nst - nst0; nnid = nni - nni0; + if (nstd == 0 || nnid == 0) return(0); + avdim = (realtype) ((nli - nli0)/((realtype) nnid)); + rcfn = (realtype) ((ncfn - ncfn0)/((realtype) nstd)); + rcfl = (realtype) ((ncfl - ncfl0)/((realtype) nnid)); + lavd = (avdim > ((realtype) maxl )); + lcfn = (rcfn > PT9); + lcfl = (rcfl > PT9); + if (!(lavd || lcfn || lcfl)) return(0); + nwarn++; + if (nwarn > 10) return(1); + if (lavd) + IDAProcessError(IDA_mem, IDA_WARNING, "IDASPGMR", "IDASpgmrPerf", MSGS_AVD_WARN, tn, avdim); + if (lcfn) + IDAProcessError(IDA_mem, IDA_WARNING, "IDASPGMR", "IDASpgmrPerf", MSGS_CFN_WARN, tn, rcfn); + if (lcfl) + IDAProcessError(IDA_mem, IDA_WARNING, "IDASPGMR", "IDASpgmrPerf", MSGS_CFL_WARN, tn, rcfl); + + return(0); +} + +static int IDASpgmrFree(IDAMem IDA_mem) +{ + IDASpilsMem idaspils_mem; + SpgmrMem spgmr_mem; + + idaspils_mem = (IDASpilsMem) lmem; + + N_VDestroy(ytemp); + N_VDestroy(xx); + + spgmr_mem = (SpgmrMem) spils_mem; + SpgmrFree(spgmr_mem); + + if (idaspils_mem->s_pfree != NULL) (idaspils_mem->s_pfree)(IDA_mem); + + free(idaspils_mem); idaspils_mem = NULL; + + return(0); +} + diff --git a/odemex/Parser/CVode/ida_src/src/ida/ida_spils.c b/odemex/Parser/CVode/ida_src/src/ida/ida_spils.c new file mode 100644 index 0000000..dbca511 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/ida_spils.c @@ -0,0 +1,637 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.4 $ + * $Date: 2007/04/30 19:29:00 $ + * ----------------------------------------------------------------- + * Programmers: Alan C. Hindmarsh and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California + * Produced at the Lawrence Livermore National Laboratory + * All rights reserved + * For details, see the LICENSE file + * ----------------------------------------------------------------- + * This is the common implementation file for the IDA Scaled + * Preconditioned Linear Solver modules. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "ida_impl.h" +#include "ida_spils_impl.h" + +/* Private constants */ + +#define ZERO RCONST(0.0) +#define PT25 RCONST(0.25) +#define PT05 RCONST(0.05) +#define ONE RCONST(1.0) + +/* Algorithmic constants */ + +#define MAX_ITERS 3 /* max. number of attempts to recover in DQ J*v */ + +/* Readability Replacements */ + +#define lrw1 (IDA_mem->ida_lrw1) +#define liw1 (IDA_mem->ida_liw1) +#define tn (IDA_mem->ida_tn) +#define cj (IDA_mem->ida_cj) +#define res (IDA_mem->ida_res) +#define user_data (IDA_mem->ida_user_data) +#define ewt (IDA_mem->ida_ewt) +#define lmem (IDA_mem->ida_lmem) + +#define ils_type (idaspils_mem->s_type) +#define sqrtN (idaspils_mem->s_sqrtN) +#define epslin (idaspils_mem->s_epslin) +#define ytemp (idaspils_mem->s_ytemp) +#define yptemp (idaspils_mem->s_yptemp) +#define xx (idaspils_mem->s_xx) +#define ycur (idaspils_mem->s_ycur) +#define ypcur (idaspils_mem->s_ypcur) +#define rcur (idaspils_mem->s_rcur) +#define npe (idaspils_mem->s_npe) +#define nli (idaspils_mem->s_nli) +#define nps (idaspils_mem->s_nps) +#define ncfl (idaspils_mem->s_ncfl) +#define njtimes (idaspils_mem->s_njtimes) +#define nres (idaspils_mem->s_nres) + +#define jtimesDQ (idaspils_mem->s_jtimesDQ) +#define jtimes (idaspils_mem->s_jtimes) +#define jdata (idaspils_mem->s_jdata) + +#define last_flag (idaspils_mem->s_last_flag) + +/* + * ----------------------------------------------------------------- + * OPTIONAL INPUT and OUTPUT + * ----------------------------------------------------------------- + */ + +int IDASpilsSetGSType(void *ida_mem, int gstype) +{ + IDAMem IDA_mem; + IDASpilsMem idaspils_mem; + + /* Return immediately if ida_mem is NULL */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsSetGSType", MSGS_IDAMEM_NULL); + return(IDASPILS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + if (lmem == NULL) { + IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsSetGSType", MSGS_LMEM_NULL); + return(IDASPILS_LMEM_NULL); + } + idaspils_mem = (IDASpilsMem) lmem; + + if (ils_type != SPILS_SPGMR) { + IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASPILS", "IDASpilsSetGSType", MSGS_BAD_LSTYPE); + return(IDASPILS_ILL_INPUT); + } + + /* Check for legal gstype */ + if ((gstype != MODIFIED_GS) && (gstype != CLASSICAL_GS)) { + IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASPILS", "IDASpilsSetGSType", MSGS_BAD_GSTYPE); + return(IDASPILS_ILL_INPUT); + } + + idaspils_mem->s_gstype = gstype; + + return(IDASPILS_SUCCESS); +} + +int IDASpilsSetMaxRestarts(void *ida_mem, int maxrs) +{ + IDAMem IDA_mem; + IDASpilsMem idaspils_mem; + + /* Return immediately if ida_mem is NULL */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsSetMaxRestarts", MSGS_IDAMEM_NULL); + return(IDASPILS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + if (lmem == NULL) { + IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsSetMaxRestarts", MSGS_LMEM_NULL); + return(IDASPILS_LMEM_NULL); + } + idaspils_mem = (IDASpilsMem) lmem; + + if (ils_type != SPILS_SPGMR) { + IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASPILS", "IDASpilsSetMaxRestarts", MSGS_BAD_LSTYPE); + return(IDASPILS_ILL_INPUT); + } + + /* Check for legal maxrs */ + if (maxrs < 0) { + IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASPILS", "IDASpilsSetMaxRestarts", MSGS_NEG_MAXRS); + return(IDASPILS_ILL_INPUT); + } + + idaspils_mem->s_maxrs = maxrs; + + return(IDASPILS_SUCCESS); +} + +int IDASpilsSetMaxl(void *ida_mem, int maxl) +{ + IDAMem IDA_mem; + IDASpilsMem idaspils_mem; + + /* Return immediately if ida_mem is NULL */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsSetMaxl", MSGS_IDAMEM_NULL); + return(IDASPILS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + if (lmem == NULL) { + IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsSetMaxl", MSGS_LMEM_NULL); + return(IDASPILS_LMEM_NULL); + } + idaspils_mem = (IDASpilsMem) lmem; + + if (ils_type == SPILS_SPGMR) { + IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASPILS", "IDASpilsSetMaxl", MSGS_BAD_LSTYPE); + return(IDASPILS_ILL_INPUT); + } + + idaspils_mem->s_maxl = (maxl <= 0) ? IDA_SPILS_MAXL : maxl; + + return(IDASPILS_SUCCESS); +} + +int IDASpilsSetEpsLin(void *ida_mem, realtype eplifac) +{ + IDAMem IDA_mem; + IDASpilsMem idaspils_mem; + + /* Return immediately if ida_mem is NULL */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsSetEpsLin", MSGS_IDAMEM_NULL); + return(IDASPILS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + if (lmem == NULL) { + IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsSetEpsLin", MSGS_LMEM_NULL); + return(IDASPILS_LMEM_NULL); + } + idaspils_mem = (IDASpilsMem) lmem; + + /* Check for legal maxrs */ + if (eplifac < ZERO) { + IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASPILS", "IDASpilsSetEpsLin", MSGS_NEG_EPLIFAC); + return(IDASPILS_ILL_INPUT); + } + + if (eplifac == ZERO) + idaspils_mem->s_eplifac = PT05; + else + idaspils_mem->s_eplifac = eplifac; + + return(IDASPILS_SUCCESS); +} + +int IDASpilsSetIncrementFactor(void *ida_mem, realtype dqincfac) +{ + IDAMem IDA_mem; + IDASpilsMem idaspils_mem; + + /* Return immediately if ida_mem is NULL */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsSetIncrementFactor", MSGS_IDAMEM_NULL); + return(IDASPILS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + if (lmem == NULL) { + IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsSetIncrementFactor", MSGS_LMEM_NULL); + return(IDASPILS_LMEM_NULL); + } + idaspils_mem = (IDASpilsMem) lmem; + + /* Check for legal maxrs */ + if (dqincfac <= ZERO) { + IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASPILS", "IDASpilsSetIncrementFactor", MSGS_NEG_DQINCFAC); + return(IDASPILS_ILL_INPUT); + } + + idaspils_mem->s_dqincfac = dqincfac; + + return(IDASPILS_SUCCESS); +} + +int IDASpilsSetPreconditioner(void *ida_mem, + IDASpilsPrecSetupFn pset, IDASpilsPrecSolveFn psolve) +{ + IDAMem IDA_mem; + IDASpilsMem idaspils_mem; + + /* Return immediately if ida_mem is NULL */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsSetPreconditioner", MSGS_IDAMEM_NULL); + return(IDASPILS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + if (lmem == NULL) { + IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsSetPreconditioner", MSGS_LMEM_NULL); + return(IDASPILS_LMEM_NULL); + } + idaspils_mem = (IDASpilsMem) lmem; + + idaspils_mem->s_pset = pset; + idaspils_mem->s_psolve = psolve; + + return(IDASPILS_SUCCESS); +} + +int IDASpilsSetJacTimesVecFn(void *ida_mem, IDASpilsJacTimesVecFn jtv) +{ + IDAMem IDA_mem; + IDASpilsMem idaspils_mem; + + /* Return immediately if ida_mem is NULL */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsSetJacTimesVecFn", MSGS_IDAMEM_NULL); + return(IDASPILS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + if (lmem == NULL) { + IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsSetJacTimesVecFn", MSGS_LMEM_NULL); + return(IDASPILS_LMEM_NULL); + } + idaspils_mem = (IDASpilsMem) lmem; + + if (jtv != NULL) { + jtimesDQ = FALSE; + jtimes = jtv; + } else { + jtimesDQ = TRUE; + } + + return(IDASPILS_SUCCESS); +} + +int IDASpilsGetWorkSpace(void *ida_mem, long int *lenrwLS, long int *leniwLS) +{ + IDAMem IDA_mem; + IDASpilsMem idaspils_mem; + int maxl; + + /* Return immediately if ida_mem is NULL */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsGetWorkSpace", MSGS_IDAMEM_NULL); + return(IDASPILS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + if (lmem == NULL) { + IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsGetWorkSpace", MSGS_LMEM_NULL); + return(IDASPILS_LMEM_NULL); + } + idaspils_mem = (IDASpilsMem) lmem; + + switch(ils_type) { + case SPILS_SPGMR: + maxl = idaspils_mem->s_maxl; + *lenrwLS = lrw1*(maxl + 6) + maxl*(maxl + 4) + 1; + *leniwLS = liw1*(maxl + 6); + break; + case SPILS_SPBCG: + *lenrwLS = lrw1 * 10; + *leniwLS = liw1 * 10; + break; + case SPILS_SPTFQMR: + *lenrwLS = lrw1*13; + *leniwLS = liw1*13; + break; + } + + return(IDASPILS_SUCCESS); +} + +int IDASpilsGetNumPrecEvals(void *ida_mem, long int *npevals) +{ + IDAMem IDA_mem; + IDASpilsMem idaspils_mem; + + /* Return immediately if ida_mem is NULL */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsGetNumPrecEvals", MSGS_IDAMEM_NULL); + return(IDASPILS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + if (lmem == NULL) { + IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsGetNumPrecEvals", MSGS_LMEM_NULL); + return(IDASPILS_LMEM_NULL); + } + idaspils_mem = (IDASpilsMem) lmem; + + *npevals = npe; + + return(IDASPILS_SUCCESS); +} + +int IDASpilsGetNumPrecSolves(void *ida_mem, long int *npsolves) +{ + IDAMem IDA_mem; + IDASpilsMem idaspils_mem; + + /* Return immediately if ida_mem is NULL */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsGetNumPrecSolves", MSGS_IDAMEM_NULL); + return(IDASPILS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + if (lmem == NULL) { + IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsGetNumPrecSolves", MSGS_LMEM_NULL); + return(IDASPILS_LMEM_NULL); + } + idaspils_mem = (IDASpilsMem) lmem; + + *npsolves = nps; + + return(IDASPILS_SUCCESS); +} + +int IDASpilsGetNumLinIters(void *ida_mem, long int *nliters) +{ + IDAMem IDA_mem; + IDASpilsMem idaspils_mem; + + /* Return immediately if ida_mem is NULL */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsGetNumLinIters", MSGS_IDAMEM_NULL); + return(IDASPILS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + if (lmem == NULL) { + IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsGetNumLinIters", MSGS_LMEM_NULL); + return(IDASPILS_LMEM_NULL); + } + idaspils_mem = (IDASpilsMem) lmem; + + *nliters = nli; + + return(IDASPILS_SUCCESS); +} + +int IDASpilsGetNumConvFails(void *ida_mem, long int *nlcfails) +{ + IDAMem IDA_mem; + IDASpilsMem idaspils_mem; + + /* Return immediately if ida_mem is NULL */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsGetNumConvFails", MSGS_IDAMEM_NULL); + return(IDASPILS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + if (lmem == NULL) { + IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsGetNumConvFails", MSGS_LMEM_NULL); + return(IDASPILS_LMEM_NULL); + } + idaspils_mem = (IDASpilsMem) lmem; + + *nlcfails = ncfl; + + return(IDASPILS_SUCCESS); +} + +int IDASpilsGetNumJtimesEvals(void *ida_mem, long int *njvevals) +{ + IDAMem IDA_mem; + IDASpilsMem idaspils_mem; + + /* Return immediately if ida_mem is NULL */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsGetNumJtimesEvals", MSGS_IDAMEM_NULL); + return(IDASPILS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + if (lmem == NULL) { + IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsGetNumJtimesEvals", MSGS_LMEM_NULL); + return(IDASPILS_LMEM_NULL); + } + idaspils_mem = (IDASpilsMem) lmem; + + *njvevals = njtimes; + + return(IDASPILS_SUCCESS); +} + +int IDASpilsGetNumResEvals(void *ida_mem, long int *nrevalsLS) +{ + IDAMem IDA_mem; + IDASpilsMem idaspils_mem; + + /* Return immediately if ida_mem is NULL */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsGetNumResEvals", MSGS_IDAMEM_NULL); + return(IDASPILS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + if (lmem == NULL) { + IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsGetNumResEvals", MSGS_LMEM_NULL); + return(IDASPILS_LMEM_NULL); + } + idaspils_mem = (IDASpilsMem) lmem; + + *nrevalsLS = nres; + + return(IDASPILS_SUCCESS); +} + +int IDASpilsGetLastFlag(void *ida_mem, int *flag) +{ + IDAMem IDA_mem; + IDASpilsMem idaspils_mem; + + /* Return immediately if ida_mem is NULL */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsGetLastFlag", MSGS_IDAMEM_NULL); + return(IDASPILS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + if (lmem == NULL) { + IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsGetLastFlag", MSGS_LMEM_NULL); + return(IDASPILS_LMEM_NULL); + } + idaspils_mem = (IDASpilsMem) lmem; + + *flag = last_flag; + + return(IDASPILS_SUCCESS); +} + +char *IDASpilsGetReturnFlagName(int flag) +{ + char *name; + + name = (char *)malloc(30*sizeof(char)); + + switch(flag) { + case IDASPILS_SUCCESS: + sprintf(name,"IDASPILS_SUCCESS"); + break; + case IDASPILS_MEM_NULL: + sprintf(name,"IDASPILS_MEM_NULL"); + break; + case IDASPILS_LMEM_NULL: + sprintf(name,"IDASPILS_LMEM_NULL"); + break; + case IDASPILS_ILL_INPUT: + sprintf(name,"IDASPILS_ILL_INPUT"); + break; + case IDASPILS_MEM_FAIL: + sprintf(name,"IDASPILS_MEM_FAIL"); + break; + case IDASPILS_PMEM_NULL: + sprintf(name,"IDASPILS_PMEM_NULL"); + break; + default: + sprintf(name,"NONE"); + } + + return(name); +} + +/* + * ----------------------------------------------------------------- + * IDASPILS private functions + * ----------------------------------------------------------------- + */ + +#define psolve (idaspils_mem->s_psolve) +#define pdata (idaspils_mem->s_pdata) +#define dqincfac (idaspils_mem->s_dqincfac) + +/* + * This routine generates the matrix-vector product z = Jv, where + * J is the system Jacobian, by calling either the user provided + * routine or the internal DQ routine. + */ + +int IDASpilsAtimes(void *ida_mem, N_Vector v, N_Vector z) +{ + IDAMem IDA_mem; + IDASpilsMem idaspils_mem; + int jtflag; + + IDA_mem = (IDAMem) ida_mem; + idaspils_mem = (IDASpilsMem) lmem; + + jtflag = jtimes(tn, ycur, ypcur, rcur, v, z, cj, jdata, ytemp, yptemp); + njtimes++; + + return(jtflag); +} + +/* + * This routine interfaces between the generic Solve routine and + * the user's psolve routine. It passes to psolve all required state + * information from ida_mem. Its return value is the same as that + * returned by psolve. Note that the generic solver guarantees + * that IDASilsPSolve will not be called in the case psolve = NULL. + */ + +int IDASpilsPSolve(void *ida_mem, N_Vector r, N_Vector z, int lr) +{ + IDAMem IDA_mem; + IDASpilsMem idaspils_mem; + int retval; + + IDA_mem = (IDAMem) ida_mem; + idaspils_mem = (IDASpilsMem) lmem; + + retval = psolve(tn, ycur, ypcur, rcur, r, z, cj, epslin, pdata, ytemp); + + /* This call is counted in nps within the IDASp**Solve routine */ + + return(retval); + +} + +/* + * This routine generates the matrix-vector product z = Jv, where + * J is the system Jacobian, by using a difference quotient approximation. + * The approximation is + * Jv = [F(t,y1,yp1) - F(t,y,yp)]/sigma, where + * y1 = y + sigma*v, yp1 = yp + cj*sigma*v, + * sigma = sqrt(Neq)*dqincfac. + * The return value from the call to res is saved in order to set the + * return flag from IDASp**Solve. + */ + +int IDASpilsDQJtimes(realtype tt, + N_Vector yy, N_Vector yp, N_Vector rr, + N_Vector v, N_Vector Jv, + realtype c_j, void *data, + N_Vector work1, N_Vector work2) +{ + IDAMem IDA_mem; + IDASpilsMem idaspils_mem; + N_Vector y_tmp, yp_tmp; + realtype sig, siginv; + int iter, retval; + + /* data is ida_mem */ + IDA_mem = (IDAMem) data; + idaspils_mem = (IDASpilsMem) lmem; + + switch(ils_type) { + case SPILS_SPGMR: + sig = sqrtN*dqincfac; + break; + case SPILS_SPBCG: + sig = dqincfac/N_VWrmsNorm(v, ewt); + break; + case SPILS_SPTFQMR: + sig = dqincfac/N_VWrmsNorm(v, ewt); + break; + } + + /* Rename work1 and work2 for readibility */ + y_tmp = work1; + yp_tmp = work2; + + for (iter=0; iter 0) return(+1); + + /* Set Jv to [Jv - rr]/sig and return. */ + siginv = ONE/sig; + N_VLinearSum(siginv, Jv, -siginv, rr, Jv); + + return(0); + +} diff --git a/odemex/Parser/CVode/ida_src/src/ida/ida_spils_impl.h b/odemex/Parser/CVode/ida_src/src/ida/ida_spils_impl.h new file mode 100644 index 0000000..e64dc0a --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/ida_spils_impl.h @@ -0,0 +1,188 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.4 $ + * $Date: 2007/04/30 19:29:00 $ + * ----------------------------------------------------------------- + * Programmers: Alan C. Hindmarsh and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the common header file (private version) for the Scaled + * Preconditioned Iterative Linear Solver modules. + * ----------------------------------------------------------------- + */ + +#ifndef _IDASPILS_IMPL_H +#define _IDASPILS_IMPL_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include "ida_impl.h" + +/* Types of iterative linear solvers */ + +#define SPILS_SPGMR 1 +#define SPILS_SPBCG 2 +#define SPILS_SPTFQMR 3 + +/* Constants */ + +#define IDA_SPILS_MAXL 5 +#define IDA_SPILS_MAXRS 5 + +/* + * ----------------------------------------------------------------- + * Types : IDASpilsMemRec, IDASpilsMem + * ----------------------------------------------------------------- + */ + +typedef struct IDASpilsMemRec { + + int s_type; /* type of scaled preconditioned iterative LS */ + + int s_gstype; /* type of Gram-Schmidt orthogonalization */ + realtype s_sqrtN; /* sqrt(N) */ + int s_maxl; /* maxl = maximum dimension of the Krylov space */ + int s_maxrs; /* maxrs = max. number of GMRES restarts */ + realtype s_eplifac; /* eplifac = linear convergence factor */ + realtype s_dqincfac; /* dqincfac = optional increment factor in Jv */ + realtype s_epslin; /* SpgrmSolve tolerance parameter */ + + long int s_npe; /* npe = total number of precond calls */ + long int s_nli; /* nli = total number of linear iterations */ + long int s_nps; /* nps = total number of psolve calls */ + long int s_ncfl; /* ncfl = total number of convergence failures */ + long int s_nres; /* nres = total number of calls to res */ + long int s_njtimes; /* njtimes = total number of calls to jtimes */ + + long int s_nst0; /* nst0 = saved nst (for performance monitor) */ + long int s_nni0; /* nni0 = saved nni (for performance monitor) */ + long int s_nli0; /* nli0 = saved nli (for performance monitor) */ + long int s_ncfn0; /* ncfn0 = saved ncfn (for performance monitor) */ + long int s_ncfl0; /* ncfl0 = saved ncfl (for performance monitor) */ + long int s_nwarn; /* nwarn = no. of warnings (for perf. monitor) */ + + N_Vector s_ytemp; /* temp vector used by IDAAtimesDQ */ + N_Vector s_yptemp; /* temp vector used by IDAAtimesDQ */ + N_Vector s_xx; /* temp vector used by the solve function */ + N_Vector s_ycur; /* current y vector in Newton iteration */ + N_Vector s_ypcur; /* current yp vector in Newton iteration */ + N_Vector s_rcur; /* rcur = F(tn, ycur, ypcur) */ + + void *s_spils_mem; /* memory used by the generic solver */ + + int s_last_flag; /* last error return flag */ + + /* Preconditioner computation + * (a) user-provided: + * - pdata == user_data + * - pfree == NULL (the user dealocates memory for f_data) + * (b) internal preconditioner module + * - pdata == ida_mem + * - pfree == set by the prec. module and called in IDASpilsFree + */ + + IDASpilsPrecSetupFn s_pset; + IDASpilsPrecSolveFn s_psolve; + void (*s_pfree)(IDAMem IDA_mem); + void *s_pdata; + + /* Jacobian times vector compuation + * (a) jtimes function provided by the user: + * - jdata == user_data + * - jtimesDQ == FALSE + * (b) internal jtimes + * - jdata == ida_mem + * - jtimesDQ == TRUE + */ + + booleantype s_jtimesDQ; + IDASpilsJacTimesVecFn s_jtimes; + void *s_jdata; + +} *IDASpilsMem; + + +/* + * ----------------------------------------------------------------- + * Prototypes of internal functions + * ----------------------------------------------------------------- + */ + +/* Atimes and PSolve routines called by generic solver */ + +int IDASpilsAtimes(void *ida_mem, N_Vector v, N_Vector z); + +int IDASpilsPSolve(void *ida_mem, N_Vector r, N_Vector z, int lr); + +/* Difference quotient approximation for Jac times vector */ + +int IDASpilsDQJtimes(realtype tt, + N_Vector yy, N_Vector yp, N_Vector rr, + N_Vector v, N_Vector Jv, + realtype c_j, void *data, + N_Vector work1, N_Vector work2); + + + +/* + * ----------------------------------------------------------------- + * Error and Warning Messages + * ----------------------------------------------------------------- + */ + +#if defined(SUNDIALS_EXTENDED_PRECISION) + +#define MSGS_TIME "at t = %Lg, " +#define MSGS_FRMT "%Le." + +#elif defined(SUNDIALS_DOUBLE_PRECISION) + +#define MSGS_TIME "at t = %lg, " +#define MSGS_FRMT "%le." + +#else + +#define MSGS_TIME "at t = %g, " +#define MSGS_FRMT "%e." + +#endif + + +/* Error Messages */ + +#define MSGS_IDAMEM_NULL "Integrator memory is NULL." +#define MSGS_MEM_FAIL "A memory request failed." +#define MSGS_BAD_NVECTOR "A required vector operation is not implemented." +#define MSGS_BAD_LSTYPE "Incompatible linear solver type." +#define MSGS_LMEM_NULL "Linear solver memory is NULL." +#define MSGS_BAD_GSTYPE "gstype has an illegal value." +#define MSGS_NEG_MAXRS "maxrs < 0 illegal." +#define MSGS_NEG_EPLIFAC "eplifac < 0.0 illegal." +#define MSGS_NEG_DQINCFAC "dqincfac < 0.0 illegal." + +#define MSGS_PSET_FAILED "The preconditioner setup routine failed in an unrecoverable manner." +#define MSGS_PSOLVE_FAILED "The preconditioner solve routine failed in an unrecoverable manner." +#define MSGS_JTIMES_FAILED "The Jacobian x vector routine failed in an unrecoverable manner." + +/* Warning Messages */ + +#define MSGS_WARN "Warning: " MSGS_TIME "poor iterative algorithm performance. " + +#define MSGS_AVD_WARN MSGS_WARN "Average number of linear iterations is " MSGS_FRMT +#define MSGS_CFN_WARN MSGS_WARN "Nonlinear convergence failure rate is " MSGS_FRMT +#define MSGS_CFL_WARN MSGS_WARN "Linear convergence failure rate is " MSGS_FRMT + + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/src/ida/ida_sptfqmr.c b/odemex/Parser/CVode/ida_src/src/ida/ida_sptfqmr.c new file mode 100644 index 0000000..65bd102 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/ida/ida_sptfqmr.c @@ -0,0 +1,477 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2007/11/26 16:20:00 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the IDA scaled preconditioned + * TFQMR linear solver module, IDASPTFQMR. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include "ida_spils_impl.h" +#include "ida_impl.h" + +#include +#include + +/* Constants */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) +#define PT9 RCONST(0.9) +#define PT05 RCONST(0.05) + +/* IDASPTFQMR linit, lsetup, lsolve, lperf, and lfree routines */ + +static int IDASptfqmrInit(IDAMem IDA_mem); + +static int IDASptfqmrSetup(IDAMem IDA_mem, + N_Vector yy_p, N_Vector yp_p, N_Vector rr_p, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +static int IDASptfqmrSolve(IDAMem IDA_mem, N_Vector bb, N_Vector weight, + N_Vector yy_now, N_Vector yp_now, N_Vector rr_now); + +static int IDASptfqmrPerf(IDAMem IDA_mem, int perftask); + +static int IDASptfqmrFree(IDAMem IDA_mem); + +/* Readability Replacements */ + +#define nst (IDA_mem->ida_nst) +#define tn (IDA_mem->ida_tn) +#define cj (IDA_mem->ida_cj) +#define epsNewt (IDA_mem->ida_epsNewt) +#define res (IDA_mem->ida_res) +#define user_data (IDA_mem->ida_user_data) +#define ewt (IDA_mem->ida_ewt) +#define errfp (IDA_mem->ida_errfp) +#define linit (IDA_mem->ida_linit) +#define lsetup (IDA_mem->ida_lsetup) +#define lsolve (IDA_mem->ida_lsolve) +#define lperf (IDA_mem->ida_lperf) +#define lfree (IDA_mem->ida_lfree) +#define lmem (IDA_mem->ida_lmem) +#define nni (IDA_mem->ida_nni) +#define ncfn (IDA_mem->ida_ncfn) +#define setupNonNull (IDA_mem->ida_setupNonNull) +#define vec_tmpl (IDA_mem->ida_tempv1) + +#define sqrtN (idaspils_mem->s_sqrtN) +#define epslin (idaspils_mem->s_epslin) +#define ytemp (idaspils_mem->s_ytemp) +#define yptemp (idaspils_mem->s_yptemp) +#define xx (idaspils_mem->s_xx) +#define ycur (idaspils_mem->s_ycur) +#define ypcur (idaspils_mem->s_ypcur) +#define rcur (idaspils_mem->s_rcur) +#define npe (idaspils_mem->s_npe) +#define nli (idaspils_mem->s_nli) +#define nps (idaspils_mem->s_nps) +#define ncfl (idaspils_mem->s_ncfl) +#define nst0 (idaspils_mem->s_nst0) +#define nni0 (idaspils_mem->s_nni0) +#define nli0 (idaspils_mem->s_nli0) +#define ncfn0 (idaspils_mem->s_ncfn0) +#define ncfl0 (idaspils_mem->s_ncfl0) +#define nwarn (idaspils_mem->s_nwarn) +#define njtimes (idaspils_mem->s_njtimes) +#define nres (idaspils_mem->s_nres) +#define spils_mem (idaspils_mem->s_spils_mem) + +#define jtimesDQ (idaspils_mem->s_jtimesDQ) +#define jtimes (idaspils_mem->s_jtimes) +#define jdata (idaspils_mem->s_jdata) + +#define last_flag (idaspils_mem->s_last_flag) + +/* + * ----------------------------------------------------------------- + * Function : IDASptfqmr + * ----------------------------------------------------------------- + * This routine initializes the memory record and sets various function + * fields specific to the IDASPTFQMR linear solver module. + * + * IDASptfqmr first calls the existing lfree routine if this is not NULL. + * It then sets the ida_linit, ida_lsetup, ida_lsolve, ida_lperf, and + * ida_lfree fields in (*IDA_mem) to be IDASptfqmrInit, IDASptfqmrSetup, + * IDASptfqmrSolve, IDASptfqmrPerf, and IDASptfqmrFree, respectively. + * It allocates memory for a structure of type IDASpilsMemRec and sets + * the ida_lmem field in (*IDA_mem) to the address of this structure. + * It sets setupNonNull in (*IDA_mem). It then sets various fields + * in the IDASpilsMemRec structure. Finally, IDASptfqmr allocates + * memory for ytemp, yptemp, and xx, and calls SptfqmrMalloc to + * allocate memory for the Sptfqmr solver. + * + * The return value of IDASptfqmr is: + * IDASPILS_SUCCESS = 0 if successful + * IDASPILS_MEM_FAIL = -1 if IDA_mem is NULL or a memory + * allocation failed + * IDASPILS_ILL_INPUT = -2 if a required vector operation is not + * implemented. + * ----------------------------------------------------------------- + */ + +int IDASptfqmr(void *ida_mem, int maxl) +{ + IDAMem IDA_mem; + IDASpilsMem idaspils_mem; + SptfqmrMem sptfqmr_mem; + int flag, maxl1; + + /* Return immediately if ida_mem is NULL */ + if (ida_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPTFQMR", "IDASptfqmr", MSGS_IDAMEM_NULL); + return(IDASPILS_MEM_NULL); + } + IDA_mem = (IDAMem) ida_mem; + + /* Check if N_VDotProd is present */ + if (vec_tmpl->ops->nvdotprod == NULL) { + IDAProcessError(NULL, IDASPILS_ILL_INPUT, "IDASPTFQMR", "IDASptfqmr", MSGS_BAD_NVECTOR); + return(IDASPILS_ILL_INPUT); + } + + if (lfree != NULL) flag = lfree((IDAMem) ida_mem); + + /* Set five main function fields in ida_mem */ + linit = IDASptfqmrInit; + lsetup = IDASptfqmrSetup; + lsolve = IDASptfqmrSolve; + lperf = IDASptfqmrPerf; + lfree = IDASptfqmrFree; + + /* Get memory for IDASpilsMemRec */ + idaspils_mem = NULL; + idaspils_mem = (IDASpilsMem) malloc(sizeof(struct IDASpilsMemRec)); + if (idaspils_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPTFQMR", "IDASptfqmr", MSGS_MEM_FAIL); + return(IDASPILS_MEM_FAIL); + } + + /* Set ILS type */ + idaspils_mem->s_type = SPILS_SPTFQMR; + + /* Set SPTFQMR parameters that were passed in call sequence */ + maxl1 = (maxl <= 0) ? IDA_SPILS_MAXL : maxl; + idaspils_mem->s_maxl = maxl1; + + /* Set defaults for Jacobian-related fileds */ + jtimesDQ = TRUE; + jtimes = NULL; + jdata = NULL; + + /* Set defaults for preconditioner-related fields */ + idaspils_mem->s_pset = NULL; + idaspils_mem->s_psolve = NULL; + idaspils_mem->s_pfree = NULL; + idaspils_mem->s_pdata = IDA_mem->ida_user_data; + + /* Set default values for the rest of the Sptfqmr parameters */ + idaspils_mem->s_eplifac = PT05; + idaspils_mem->s_dqincfac = ONE; + + idaspils_mem->s_last_flag = IDASPILS_SUCCESS; + + /* Set setupNonNull to FALSE */ + setupNonNull = FALSE; + + /* Allocate memory for ytemp, yptemp, and xx */ + + ytemp = N_VClone(vec_tmpl); + if (ytemp == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPTFQMR", "IDASptfqmr", MSGS_MEM_FAIL); + free(idaspils_mem); idaspils_mem = NULL; + return(IDASPILS_MEM_FAIL); + } + + yptemp = N_VClone(vec_tmpl); + if (yptemp == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPTFQMR", "IDASptfqmr", MSGS_MEM_FAIL); + N_VDestroy(ytemp); + free(idaspils_mem); idaspils_mem = NULL; + return(IDASPILS_MEM_FAIL); + } + + xx = N_VClone(vec_tmpl); + if (xx == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPTFQMR", "IDASptfqmr", MSGS_MEM_FAIL); + N_VDestroy(ytemp); + N_VDestroy(yptemp); + free(idaspils_mem); idaspils_mem = NULL; + return(IDASPILS_MEM_FAIL); + } + + /* Compute sqrtN from a dot product */ + N_VConst(ONE, ytemp); + sqrtN = RSqrt(N_VDotProd(ytemp, ytemp)); + + /* Call SptfqmrMalloc to allocate workspace for Sptfqmr */ + sptfqmr_mem = NULL; + sptfqmr_mem = SptfqmrMalloc(maxl1, vec_tmpl); + if (sptfqmr_mem == NULL) { + IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPTFQMR", "IDASptfqmr", MSGS_MEM_FAIL); + N_VDestroy(ytemp); + N_VDestroy(yptemp); + N_VDestroy(xx); + free(idaspils_mem); idaspils_mem = NULL; + return(IDASPILS_MEM_FAIL); + } + + /* Attach SPTFQMR memory to spils memory structure */ + spils_mem = (void *)sptfqmr_mem; + + /* Attach linear solver memory to the integrator memory */ + lmem = idaspils_mem; + + return(IDASPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * IDASPTFQMR interface routines + * ----------------------------------------------------------------- + */ + +/* Additional readability Replacements */ + +#define maxl (idaspils_mem->s_maxl) +#define eplifac (idaspils_mem->s_eplifac) +#define psolve (idaspils_mem->s_psolve) +#define pset (idaspils_mem->s_pset) +#define pdata (idaspils_mem->s_pdata) + +static int IDASptfqmrInit(IDAMem IDA_mem) +{ + IDASpilsMem idaspils_mem; + SptfqmrMem sptfqmr_mem; + + idaspils_mem = (IDASpilsMem) lmem; + sptfqmr_mem = (SptfqmrMem) spils_mem; + + /* Initialize counters */ + npe = nli = nps = ncfl = 0; + njtimes = nres = 0; + + /* Set setupNonNull to TRUE iff there is preconditioning with setup */ + setupNonNull = (psolve != NULL) && (pset != NULL); + + /* Set Jacobian-related fields, based on jtimesDQ */ + if (jtimesDQ) { + jtimes = IDASpilsDQJtimes; + jdata = IDA_mem; + } else { + jdata = user_data; + } + + /* Set maxl in the SPTFQMR memory in case it was changed by the user */ + sptfqmr_mem->l_max = maxl; + + last_flag = IDASPILS_SUCCESS; + + return(0); +} + +static int IDASptfqmrSetup(IDAMem IDA_mem, + N_Vector yy_p, N_Vector yp_p, N_Vector rr_p, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + int retval; + IDASpilsMem idaspils_mem; + + idaspils_mem = (IDASpilsMem) lmem; + + /* Call user setup routine pset and update counter npe */ + retval = pset(tn, yy_p, yp_p, rr_p, cj, pdata, + tmp1, tmp2, tmp3); + npe++; + + if (retval < 0) { + IDAProcessError(IDA_mem, SPTFQMR_PSET_FAIL_UNREC, "IDASPTFQMR", "IDASptfqmrSetup", MSGS_PSET_FAILED); + last_flag = SPTFQMR_PSET_FAIL_UNREC; + return(-1); + } + if (retval > 0) { + last_flag = SPTFQMR_PSET_FAIL_REC; + return(+1); + } + + last_flag = SPTFQMR_SUCCESS; + + return(0); +} + +/* + * ----------------------------------------------------------------- + * Function : IDASptfqmrSolve + * ----------------------------------------------------------------- + * Note: The x-scaling and b-scaling arrays are both equal to weight. + * + * We set the initial guess, x = 0, then call SptfqmrSolve. + * We copy the solution x into b, and update the counters nli, nps, + * and ncfl. If SptfqmrSolve returned nli_inc = 0 (hence x = 0), we + * take the SPTFQMR vtemp vector (= P_inverse F) as the correction + * vector instead. Finally, we set the return value according to the + * success of SptfqmrSolve. + * ----------------------------------------------------------------- + */ + +static int IDASptfqmrSolve(IDAMem IDA_mem, N_Vector bb, N_Vector weight, + N_Vector yy_now, N_Vector yp_now, N_Vector rr_now) +{ + IDASpilsMem idaspils_mem; + SptfqmrMem sptfqmr_mem; + int pretype, nli_inc, nps_inc, retval; + realtype res_norm; + + idaspils_mem = (IDASpilsMem) lmem; + + sptfqmr_mem = (SptfqmrMem)spils_mem; + + /* Set SptfqmrSolve convergence test constant epslin, in terms of the + Newton convergence test constant epsNewt and safety factors. The factor + sqrt(Neq) assures that the TFQMR convergence test is applied to the + WRMS norm of the residual vector, rather than the weighted L2 norm. */ + epslin = sqrtN*eplifac*epsNewt; + + /* Set vectors ycur, ypcur, and rcur for use by the Atimes and Psolve */ + ycur = yy_now; + ypcur = yp_now; + rcur = rr_now; + + /* Set SptfqmrSolve inputs pretype and initial guess xx = 0 */ + pretype = (psolve == NULL) ? PREC_NONE : PREC_LEFT; + N_VConst(ZERO, xx); + + /* Call SptfqmrSolve and copy xx to bb */ + retval = SptfqmrSolve(sptfqmr_mem, IDA_mem, xx, bb, pretype, epslin, + IDA_mem, weight, weight, IDASpilsAtimes, + IDASpilsPSolve, &res_norm, &nli_inc, &nps_inc); + + if (nli_inc == 0) N_VScale(ONE, SPTFQMR_VTEMP(sptfqmr_mem), bb); + else N_VScale(ONE, xx, bb); + + /* Increment counters nli, nps, and return if successful */ + nli += nli_inc; + nps += nps_inc; + if (retval != SPTFQMR_SUCCESS) ncfl++; + + /* Interpret return value from SpgmrSolve */ + + last_flag = retval; + + switch(retval) { + + case SPTFQMR_SUCCESS: + return(0); + break; + case SPTFQMR_RES_REDUCED: + return(1); + break; + case SPTFQMR_CONV_FAIL: + return(1); + break; + case SPTFQMR_PSOLVE_FAIL_REC: + return(1); + break; + case SPTFQMR_ATIMES_FAIL_REC: + return(1); + break; + case SPTFQMR_MEM_NULL: + return(-1); + break; + case SPTFQMR_ATIMES_FAIL_UNREC: + IDAProcessError(IDA_mem, SPTFQMR_ATIMES_FAIL_UNREC, "IDASPTFQMR", "IDASptfqmrSolve", MSGS_JTIMES_FAILED); + return(-1); + break; + case SPTFQMR_PSOLVE_FAIL_UNREC: + IDAProcessError(IDA_mem, SPTFQMR_PSOLVE_FAIL_UNREC, "IDASPTFQMR", "IDASptfqmrSolve", MSGS_PSOLVE_FAILED); + return(-1); + break; + } + + return(0); +} + +/* + * ----------------------------------------------------------------- + * Function : IDASptfqmrPerf + * ----------------------------------------------------------------- + * This routine handles performance monitoring specific to the + * IDASPTFQMR linear solver. When perftask = 0, it saves values of + * various counters. When perftask = 1, it examines difference + * quotients in these counters, and depending on their values, it + * prints up to three warning messages. Messages are printed up to + * a maximum of 10 times. + * ----------------------------------------------------------------- + */ + +static int IDASptfqmrPerf(IDAMem IDA_mem, int perftask) +{ + IDASpilsMem idaspils_mem; + realtype avdim, rcfn, rcfl; + long int nstd, nnid; + booleantype lavd, lcfn, lcfl; + + idaspils_mem = (IDASpilsMem) lmem; + + if (perftask == 0) { + nst0 = nst; nni0 = nni; nli0 = nli; + ncfn0 = ncfn; ncfl0 = ncfl; + nwarn = 0; + return(0); + } + + nstd = nst - nst0; nnid = nni - nni0; + if (nstd == 0 || nnid == 0) return(0); + avdim = (realtype) ((nli - nli0)/((realtype) nnid)); + rcfn = (realtype) ((ncfn - ncfn0)/((realtype) nstd)); + rcfl = (realtype) ((ncfl - ncfl0)/((realtype) nnid)); + lavd = (avdim > ((realtype) maxl)); + lcfn = (rcfn > PT9); + lcfl = (rcfl > PT9); + if (!(lavd || lcfn || lcfl)) return(0); + nwarn++; + if (nwarn > 10) return(1); + if (lavd) + IDAProcessError(IDA_mem, IDA_WARNING, "IDASPTFQMR", "IDASptfqmrPerf", MSGS_AVD_WARN, tn, avdim); + if (lcfn) + IDAProcessError(IDA_mem, IDA_WARNING, "IDASPTFQMR", "IDASptfqmrPerf", MSGS_CFN_WARN, tn, rcfn); + if (lcfl) + IDAProcessError(IDA_mem, IDA_WARNING, "IDASPTFQMR", "IDASptfqmrPerf", MSGS_CFL_WARN, tn, rcfl); + + return(0); +} + +static int IDASptfqmrFree(IDAMem IDA_mem) +{ + IDASpilsMem idaspils_mem; + SptfqmrMem sptfqmr_mem; + + idaspils_mem = (IDASpilsMem) lmem; + + N_VDestroy(ytemp); + N_VDestroy(yptemp); + N_VDestroy(xx); + + sptfqmr_mem = (SptfqmrMem)spils_mem; + SptfqmrFree(sptfqmr_mem); + + if (idaspils_mem->s_pfree != NULL) (idaspils_mem->s_pfree)(IDA_mem); + + free(idaspils_mem); idaspils_mem = NULL; + + return(0); +} + diff --git a/odemex/Parser/CVode/ida_src/src/nvec_par/CMakeLists.txt b/odemex/Parser/CVode/ida_src/src/nvec_par/CMakeLists.txt new file mode 100644 index 0000000..f5e359f --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/nvec_par/CMakeLists.txt @@ -0,0 +1,89 @@ +# --------------------------------------------------------------- +# $Revision: 1.3 $ +# $Date: 2009/02/17 02:58:48 $ +# --------------------------------------------------------------- +# Programmer: Radu Serban @ LLNL +# --------------------------------------------------------------- +# Copyright (c) 2007, The Regents of the University of California. +# Produced at the Lawrence Livermore National Laboratory. +# All rights reserved. +# For details, see the LICENSE file. +# --------------------------------------------------------------- +# CMakeLists.txt file for the parallel NVECTOR library + +INSTALL(CODE "MESSAGE(\"\nInstall NVECTOR_PARALLEL\n\")") + +IF(MPI_MPICC) + # use MPI_MPICC as the compiler + SET(CMAKE_C_COMPILER ${MPI_MPICC}) +ELSE(MPI_MPICC) + # add MPI_INCLUDE_PATH to include directories + INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH}) +ENDIF(MPI_MPICC) + +# Add variable nvecparallel_SOURCES with the sources for the NVECPARALLEL lib +SET(nvecparallel_SOURCES nvector_parallel.c) + +# Add variable shared_SOURCES with the common SUNDIALS sources which will +# also be included in the NVECPARALLEL library +SET(shared_SOURCES sundials_math.c) +ADD_PREFIX(${sundials_SOURCE_DIR}/src/sundials/ shared_SOURCES) + +# Add variable nvecparallel_HEADERS with the exported NVECPARALLEL header files +SET(nvecparallel_HEADERS nvector_parallel.h) +ADD_PREFIX(${sundials_SOURCE_DIR}/include/nvector/ nvecparallel_HEADERS) + +# Add source directory to include directories +INCLUDE_DIRECTORIES(.) + +# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY +ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY) + +# Rules for building and installing the static library: +# - Add the build target for the NVECPARALLEL library +# - Set the library name and make sure it is not deleted +# - Install the NVECSERIAL library +IF(BUILD_STATIC_LIBS) + ADD_LIBRARY(sundials_nvecparallel_static STATIC ${nvecparallel_SOURCES} ${shared_SOURCES}) + SET_TARGET_PROPERTIES(sundials_nvecparallel_static + PROPERTIES OUTPUT_NAME sundials_nvecparallel CLEAN_DIRECT_OUTPUT 1) + INSTALL(TARGETS sundials_nvecparallel_static DESTINATION lib) +ENDIF(BUILD_STATIC_LIBS) + +# Rules for building and installing the shared library: +# - Add the build target for the NVECPARALLEL library +# - Set the library name and make sure it is not deleted +# - Set VERSION and SOVERSION for shared libraries +# - Install the NVECSERIAL library +IF(BUILD_SHARED_LIBS) + ADD_LIBRARY(sundials_nvecparallel_shared SHARED ${nvecparallel_SOURCES} ${shared_SOURCES}) + SET_TARGET_PROPERTIES(sundials_nvecparallel_shared + PROPERTIES OUTPUT_NAME sundials_nvecparallel CLEAN_DIRECT_OUTPUT 1) + SET_TARGET_PROPERTIES(sundials_nvecparallel_shared + PROPERTIES VERSION ${nveclib_VERSION} SOVERSION ${nveclib_SOVERSION}) + INSTALL(TARGETS sundials_nvecparallel_shared DESTINATION lib) +ENDIF(BUILD_SHARED_LIBS) + +# Install the NVECPARALLEL header files +INSTALL(FILES ${nvecparallel_HEADERS} DESTINATION include/nvector) + +# If FCMIX is enabled and MPI-F77 works, build and install the FNVECPARALLEL library +IF(FCMIX_ENABLE AND MPIF_FOUND) + SET(fnvecparallel_SOURCES fnvector_parallel.c) + IF(BUILD_STATIC_LIBS) + ADD_LIBRARY(sundials_fnvecparallel_static STATIC ${fnvecparallel_SOURCES}) + SET_TARGET_PROPERTIES(sundials_fnvecparallel_static + PROPERTIES OUTPUT_NAME sundials_fnvecparallel CLEAN_DIRECT_OUTPUT 1) + INSTALL(TARGETS sundials_fnvecparallel_static DESTINATION lib) + ENDIF(BUILD_STATIC_LIBS) + IF(BUILD_SHARED_LIBS) + ADD_LIBRARY(sundials_fnvecparallel_shared SHARED ${fnvecparallel_SOURCES}) + SET_TARGET_PROPERTIES(sundials_fnvecparallel_shared + PROPERTIES OUTPUT_NAME sundials_fnvecparallel CLEAN_DIRECT_OUTPUT 1) + SET_TARGET_PROPERTIES(sundials_fnvecparallel_shared + PROPERTIES VERSION ${nveclib_VERSION} SOVERSION ${nveclib_SOVERSION}) + INSTALL(TARGETS sundials_fnvecparallel_shared DESTINATION lib) + ENDIF(BUILD_SHARED_LIBS) +ENDIF(FCMIX_ENABLE AND MPIF_FOUND) +# +MESSAGE(STATUS "Added NVECTOR_PARALLEL module") diff --git a/odemex/Parser/CVode/ida_src/src/nvec_par/Makefile.in b/odemex/Parser/CVode/ida_src/src/nvec_par/Makefile.in new file mode 100644 index 0000000..bd7ea4f --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/nvec_par/Makefile.in @@ -0,0 +1,128 @@ +# ----------------------------------------------------------------- +# $Revision: 1.8 $ +# $Date: 2007/01/29 17:36:28 $ +# ----------------------------------------------------------------- +# Programmer(s): Radu Serban and Aaron Collier @ LLNL +# ----------------------------------------------------------------- +# Copyright (c) 2002, The Regents of the University of California. +# Produced at the Lawrence Livermore National Laboratory. +# All rights reserved. +# For details, see the LICENSE file. +# ----------------------------------------------------------------- +# Makefile for parallel NVECTOR module +# +# @configure_input@ +# ----------------------------------------------------------------- + +SHELL = @SHELL@ + +@SET_MAKE@ + +srcdir = @srcdir@ +builddir = @builddir@ +abs_builddir = @abs_builddir@ +top_builddir = @top_builddir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +includedir = @includedir@ +libdir = @libdir@ + +INSTALL = @INSTALL@ +INSTALL_LIB = @INSTALL_PROGRAM@ +INSTALL_HEADER = @INSTALL_DATA@ + +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ + +MPICC = @MPICC@ +MPI_INC_DIR = @MPI_INC_DIR@ +MPI_LIB_DIR = @MPI_LIB_DIR@ +MPI_LIBS = @MPI_LIBS@ +MPI_FLAGS = @MPI_FLAGS@ +CPPFLAGS = @CPPFLAGS@ +CFLAGS = @CFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ + +FCMIX_ENABLED = @FCMIX_ENABLED@ + +top_srcdir = $(srcdir)/../.. + +INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(MPI_INC_DIR) + +LIB_REVISION = 0:2:0 + +NVECPAR_LIB = libsundials_nvecparallel.la +NVECPAR_LIB_FILES = nvector_parallel.lo + +FNVECPAR_LIB = libsundials_fnvecparallel.la +FNVECPAR_LIB_FILES = fnvector_parallel.lo + +SHARED_LIB_FILES = $(top_builddir)/src/sundials/sundials_math.lo + +mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs +rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs + +all: $(NVECPAR_LIB) $(FNVECPAR_LIB) + +$(NVECPAR_LIB): shared $(NVECPAR_LIB_FILES) + $(LIBTOOL) --mode=link $(MPICC) $(CFLAGS) $(MPI_FLAGS) -o $(NVECPAR_LIB) $(NVECPAR_LIB_FILES) $(SHARED_LIB_FILES) $(LDFLAGS) -L$(MPI_LIB_DIR) $(MPI_LIBS) $(LIBS) -rpath $(libdir) -version-info $(LIB_REVISION) + +$(FNVECPAR_LIB): $(FNVECPAR_LIB_FILES) + @if test "X${FCMIX_ENABLED}" = "Xyes"; then \ + echo "${LIBTOOL} --mode=link ${MPICC} ${CFLAGS} ${MPI_FLAGS} -o ${FNVECPAR_LIB} ${FNVECPAR_LIB_FILES} ${SHARED_LIB_FILES} ${LDFLAGS} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LIBS} -rpath ${libdir} -version-info ${LIB_REVISION}" ; \ + ${LIBTOOL} --mode=link ${MPICC} ${CFLAGS} ${MPI_FLAGS} -o ${FNVECPAR_LIB} ${FNVECPAR_LIB_FILES} ${SHARED_LIB_FILES} ${LDFLAGS} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LIBS} -rpath ${libdir} -version-info ${LIB_REVISION} ; \ + fi + +install: $(NVECPAR_LIB) $(FNVECPAR_LIB) + $(mkinstalldirs) $(includedir)/nvector + $(mkinstalldirs) $(libdir) + $(LIBTOOL) --mode=install $(INSTALL_LIB) $(NVECPAR_LIB) $(libdir) + $(INSTALL_HEADER) $(top_srcdir)/include/nvector/nvector_parallel.h $(includedir)/nvector/ + @if test "X${FCMIX_ENABLED}" = "Xyes"; then \ + echo "${LIBTOOL} --mode=install ${INSTALL_LIB} ${FNVECPAR_LIB} ${libdir}" ; \ + ${LIBTOOL} --mode=install ${INSTALL_LIB} ${FNVECPAR_LIB} ${libdir} ; \ + fi + +uninstall: + $(LIBTOOL) --mode=uninstall rm -f $(libdir)/$(NVECPAR_LIB) + @if test "X${FCMIX_ENABLED}" = "Xyes"; then \ + echo "${LIBTOOL} --mode=uninstall rm -f ${libdir}/${FNVECPAR_LIB}" ; \ + ${LIBTOOL} --mode=uninstall rm -f ${libdir}/${FNVECPAR_LIB} ; \ + fi + rm -f $(includedir)/nvector/nvector_parallel.h + $(rminstalldirs) ${includedir}/nvector + +shared: + @cd ${top_builddir}/src/sundials ; \ + ${MAKE} ; \ + cd ${abs_builddir} + +clean: + $(LIBTOOL) --mode=clean rm -f $(NVECPAR_LIB) + rm -f $(NVECPAR_LIB_FILES) + rm -f nvector_parallel.o + @if test "X${FCMIX_ENABLED}" = "Xyes"; then \ + echo "${LIBTOOL} --mode=clean rm -f ${FNVECPAR_LIB}" ; \ + ${LIBTOOL} --mode=clean rm -f ${FNVECPAR_LIB} ; \ + echo "rm -f ${FNVECPAR_LIB_FILES}" ; \ + rm -f ${FNVECPAR_LIB_FILES} ; \ + echo "rm -f fnvector_parallel.o" ; \ + rm -f fnvector_parallel.o ; \ + fi + +distclean: clean + rm -f Makefile + +nvector_parallel.lo: $(srcdir)/nvector_parallel.c + $(LIBTOOL) --mode=compile $(MPICC) $(CPPFLAGS) $(MPI_FLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/nvector_parallel.c +fnvector_parallel.lo: $(srcdir)/fnvector_parallel.c + @if test "X${FCMIX_ENABLED}" = "Xyes"; then \ + echo "${LIBTOOL} --mode=compile ${MPICC} ${CPPFLAGS} ${MPI_FLAGS} $(INCLUDES) ${CFLAGS} -c ${srcdir}/fnvector_parallel.c" ; \ + ${LIBTOOL} --mode=compile ${MPICC} ${CPPFLAGS} ${MPI_FLAGS} $(INCLUDES) ${CFLAGS} -c ${srcdir}/fnvector_parallel.c ; \ + fi + +libtool: $(top_builddir)/$(LIBTOOL_DEPS) + @cd ${top_builddir} ; \ + ${SHELL} ./config.status --recheck ; \ + cd ${abs_builddir} diff --git a/odemex/Parser/CVode/ida_src/src/nvec_par/README b/odemex/Parser/CVode/ida_src/src/nvec_par/README new file mode 100644 index 0000000..726603e --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/nvec_par/README @@ -0,0 +1,135 @@ + NVECTOR_PARALLEL + Release 2.4.0, January 2008 + +MPI parallel implementation of the NVECTOR module for SUNDIALS. + +NVECTOR_PARALLEL defines the content field of N_Vector to be a structure +containing the global and local lengths of the vector, a pointer to the +beginning of a contiguous local data array, an MPI communicator, and a +boolean flag indicating ownership of the data array. + +NVECTOR_PARALLEL defines seven macros to provide access to the content of +a parallel N_Vector, several constructors for variables of type N_Vector, +a constructor for an array of variables of type N_Vector, and destructors +for N_Vector and N_Vector array. + +NVECTOR_PARALLEL provides implementations for all vector operations defined +by the generic NVECTOR module in the table of operations. + + +A. Documentation +---------------- + +The MPI parallel NVECTOR implementation is fully described in the user documentation +for any of the SUNDIALS solvers [1-5]. A PDF file for the user guide for a particular +solver is available in the solver's subdirectory under doc/. + + +B. Installation +--------------- + +For basic installation instructions see /sundials/INSTALL_NOTES. +For complete installation instructions see any of the user guides. + + +C. References +------------- + +[1] A. C. Hindmarsh and R. Serban, "User Documentation for CVODE v2.4.0," + LLLNL technical report UCRL-MA-208108, November 2004. + +[2] A. C. Hindmarsh and R. Serban, "User Documentation for CVODES v2.4.0," + LLNL technical report UCRL-MA-208111, November 2004. + +[3] A. C. Hindmarsh and R. Serban, "User Documentation for IDA v2.4.0," + LLNL technical report UCRL-MA-208112, November 2004. + +[4] R. Serban and C. Petra, "User Documentation for IDAS v1.0.0," + LLNL technical report UCRL-SM-234051, August 2007. + +[5] A. M. Collier, A. C. Hindmarsh, R. Serban,and C. S. Woodward, "User + Documentation for KINSOL v2.4.0," LLNL technical report UCRL-MA-208116, + November 2004. + + +D. Releases +----------- + +v. 2.4.0 - Jan. 2008 +v. 2.3.0 - Nov. 2006 +v. 2.2.0 - Mar. 2006 +v. 2.1.1 - May. 2005 +v. 2.1.0 - Apr. 2005 +v. 2.0.2 - Mar. 2005 +v. 2.0.1 - Jan. 2005 +v. 2.0 - Dec. 2004 +v. 1.0 - Jul. 2002 (first SUNDIALS release) + + +E. Revision History +------------------- + +v. 2.3.0 (Nov. 2006) ---> v. 2.4.0 (Jan. 2008) +--------------------------------------------------------- + +- none + +v. 2.2.0 (Mar. 2006) ---> v. 2.3.0 (Nov. 2006) +---------------------------------------------- + +- Changes related to the build system + - reorganized source tree. Header files in ${srcdir}/include/nvector; + sources in ${srcdir}/src/nvec_par + - exported header files in ${includedir}/sundials + +v. 2.1.1 (May. 2005) ---> v. 2.2.0 (Mar. 2006) +---------------------------------------------- + +- none + +v. 2.1.0 (Apr. 2005) ---> v. 2.1.1 (May. 2005) +---------------------------------------------- + +- Changes to user interface + - added argument to initialization routines to allow user to specify a + different MPI communicator + +- Changes to data structures + - added N_VCloneEmpty to global vector operations table + +v. 2.0.2 (Mar. 2005) ---> v. 2.1.0 (Apr. 2005) +---------------------------------------------- + +- none + +v. 2.0.1 (Jan. 2005) ---> v. 2.0.2 (Mar. 2005) +---------------------------------------------- + +- Changes related to the build system + - fixed autoconf-related bug to allow configuration with the PGI Fortran compiler + - modified to use customized detection of the Fortran name mangling scheme + (autoconf's AC_F77_WRAPPERS routine is problematic on some platforms) + - added --with-mpi-flags as a configure option to allow user to specify + MPI-specific flags + - updated Makefiles for Fortran examples to avoid C++ compiler errors (now use + CC and MPICC to link) + +v. 2.0 (Dec. 2004) ---> v. 2.0.1 (Jan. 2005) +-------------------------------------------- + +- Changes related to the build system + - changed order of compiler directives in header files to avoid compilation + errors when using a C++ compiler. + +v. 1.0 (Jul. 2002) ---> v. 2.0 (Dec. 2004) +------------------------------------------ + +- Revised to correspond to new generic NVECTOR module + (see sundials/shared/README). +- Extended the list of user-callable functions provided by NVECTOR_PARALLEL + outside the table of vector operations. +- Revised parallel N_VMin and N_VMinQuotient to use BIG_REAL if + local N is 0 or no quotients found. +- Revised the F/C interface to use underscore flags for name mapping + and to use precision flag from configure. +- Revised F/C routine NVECTOR names for uniformity. diff --git a/odemex/Parser/CVode/ida_src/src/nvec_par/fnvector_parallel.c b/odemex/Parser/CVode/ida_src/src/nvec_par/fnvector_parallel.c new file mode 100644 index 0000000..6ece6b9 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/nvec_par/fnvector_parallel.c @@ -0,0 +1,182 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.1 $ + * $Date: 2006/07/05 15:32:37 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This file (companion of nvector_parallel.h) contains the + * implementation needed for the Fortran initialization of parallel + * vector operations. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "fnvector_parallel.h" + +/* Define global vector variables */ + +N_Vector F2C_CVODE_vec; +N_Vector F2C_CVODE_vecQ; +N_Vector *F2C_CVODE_vecS; +N_Vector F2C_CVODE_vecB; +N_Vector F2C_CVODE_vecQB; + +N_Vector F2C_IDA_vec; +N_Vector F2C_IDA_vecQ; +N_Vector *F2C_IDA_vecS; +N_Vector F2C_IDA_vecB; +N_Vector F2C_IDA_vecQB; + +N_Vector F2C_KINSOL_vec; + +#ifndef SUNDIALS_MPI_COMM_F2C +#define MPI_Fint int +#endif + +/* Fortran callable interfaces */ + +void FNV_INITP(MPI_Fint *comm, int *code, long int *L, long int *N, int *ier) +{ + MPI_Comm F2C_comm; + +#ifdef SUNDIALS_MPI_COMM_F2C + F2C_comm = MPI_Comm_f2c(*comm); +#else + F2C_comm = MPI_COMM_WORLD; +#endif + + *ier = 0; + + switch(*code) { + case FCMIX_CVODE: + F2C_CVODE_vec = NULL; + F2C_CVODE_vec = N_VNewEmpty_Parallel(F2C_comm, *L, *N); + if (F2C_CVODE_vec == NULL) *ier = -1; + break; + case FCMIX_IDA: + F2C_IDA_vec = NULL; + F2C_IDA_vec = N_VNewEmpty_Parallel(F2C_comm, *L, *N); + if (F2C_IDA_vec == NULL) *ier = -1; + break; + case FCMIX_KINSOL: + F2C_KINSOL_vec = NULL; + F2C_KINSOL_vec = N_VNewEmpty_Parallel(F2C_comm, *L, *N); + if (F2C_KINSOL_vec == NULL) *ier = -1; + break; + default: + *ier = -1; + } +} + +void FNV_INITP_Q(MPI_Fint *comm, int *code, long int *Lq, long int *Nq, int *ier) +{ + MPI_Comm F2C_comm; + +#ifdef SUNDIALS_MPI_COMM_F2C + F2C_comm = MPI_Comm_f2c(*comm); +#else + F2C_comm = MPI_COMM_WORLD; +#endif + + *ier = 0; + + switch(*code) { + case FCMIX_CVODE: + F2C_CVODE_vecQ = NULL; + F2C_CVODE_vecQ = N_VNewEmpty_Parallel(F2C_comm, *Lq, *Nq); + if (F2C_CVODE_vecQ == NULL) *ier = -1; + break; + case FCMIX_IDA: + F2C_IDA_vecQ = NULL; + F2C_IDA_vecQ = N_VNewEmpty_Parallel(F2C_comm, *Lq, *Nq); + if (F2C_IDA_vecQ == NULL) *ier = -1; + break; + default: + *ier = -1; + } +} + +void FNV_INITP_B(MPI_Fint *comm, int *code, long int *LB, long int *NB, int *ier) +{ + MPI_Comm F2C_comm; + +#ifdef SUNDIALS_MPI_COMM_F2C + F2C_comm = MPI_Comm_f2c(*comm); +#else + F2C_comm = MPI_COMM_WORLD; +#endif + + *ier = 0; + + switch(*code) { + case FCMIX_CVODE: + F2C_CVODE_vecB = NULL; + F2C_CVODE_vecB = N_VNewEmpty_Parallel(F2C_comm, *LB, *NB); + if (F2C_CVODE_vecB == NULL) *ier = -1; + break; + case FCMIX_IDA: + F2C_IDA_vecB = NULL; + F2C_IDA_vecB = N_VNewEmpty_Parallel(F2C_comm, *LB, *NB); + if (F2C_IDA_vecB == NULL) *ier = -1; + break; + default: + *ier = -1; + } +} + +void FNV_INITP_QB(MPI_Fint *comm, int *code, long int *LqB, long int *NqB, int *ier) +{ + MPI_Comm F2C_comm; + +#ifdef SUNDIALS_MPI_COMM_F2C + F2C_comm = MPI_Comm_f2c(*comm); +#else + F2C_comm = MPI_COMM_WORLD; +#endif + + + *ier = 0; + + switch(*code) { + case FCMIX_CVODE: + F2C_CVODE_vecQB = NULL; + F2C_CVODE_vecQB = N_VNewEmpty_Parallel(F2C_comm, *LqB, *NqB); + if (F2C_CVODE_vecQB == NULL) *ier = -1; + break; + case FCMIX_IDA: + F2C_IDA_vecQB = NULL; + F2C_IDA_vecQB = N_VNewEmpty_Parallel(F2C_comm, *LqB, *NqB); + if (F2C_IDA_vecQB == NULL) *ier = -1; + break; + default: + *ier = -1; + } +} + +void FNV_INITP_S(int *code, int *Ns, int *ier) +{ + *ier = 0; + + switch(*code) { + case FCMIX_CVODE: + F2C_CVODE_vecS = NULL; + F2C_CVODE_vecS = (N_Vector *) N_VCloneVectorArrayEmpty_Parallel(*Ns, F2C_CVODE_vec); + if (F2C_CVODE_vecS == NULL) *ier = -1; + break; + case FCMIX_IDA: + F2C_IDA_vecS = NULL; + F2C_IDA_vecS = (N_Vector *) N_VCloneVectorArrayEmpty_Parallel(*Ns, F2C_IDA_vec); + if (F2C_IDA_vecS == NULL) *ier = -1; + break; + default: + *ier = -1; + } +} diff --git a/odemex/Parser/CVode/ida_src/src/nvec_par/fnvector_parallel.h b/odemex/Parser/CVode/ida_src/src/nvec_par/fnvector_parallel.h new file mode 100644 index 0000000..79837bb --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/nvec_par/fnvector_parallel.h @@ -0,0 +1,88 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.3 $ + * $Date: 2006/11/29 00:05:09 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This file (companion of nvector_parallel.c) contains the + * definitions needed for the initialization of parallel + * vector operations in Fortran. + * ----------------------------------------------------------------- + */ + +#ifndef _FNVECTOR_PARALLEL_H +#define _FNVECTOR_PARALLEL_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +#if defined(F77_FUNC) + +#define FNV_INITP F77_FUNC(fnvinitp, FNVINITP) +#define FNV_INITP_Q F77_FUNC_(fnvinitp_q, FNVINITP_Q) +#define FNV_INITP_S F77_FUNC_(fnvinitp_s, FNVINITP_S) +#define FNV_INITP_B F77_FUNC_(fnvinitp_b, FNVINITP_B) +#define FNV_INITP_QB F77_FUNC_(fnvinitp_qb, FNVINITP_QB) + +#else + +#define FNV_INITP fnvinitp_ +#define FNV_INITP_Q fnvinitp_q_ +#define FNV_INITP_S fnvinitp_s_ +#define FNV_INITP_B fnvinitp_b_ +#define FNV_INITP_QB fnvinitp_qb_ + +#endif + +/* Declarations of global variables */ + +extern N_Vector F2C_CVODE_vec; +extern N_Vector F2C_CVODE_vecQ; +extern N_Vector *F2C_CVODE_vecS; +extern N_Vector F2C_CVODE_vecB; +extern N_Vector F2C_CVODE_vecQB; + +extern N_Vector F2C_IDA_vec; +extern N_Vector F2C_IDA_vecQ; +extern N_Vector *F2C_IDA_vecS; +extern N_Vector F2C_IDA_vecB; +extern N_Vector F2C_IDA_vecQB; + +extern N_Vector F2C_KINSOL_vec; + +/* + * Prototypes of exported functions + * + * FNV_INITP - initializes parallel vector operations for main problem + * FNV_INITP_Q - initializes parallel vector operations for quadratures + * FNV_INITP_S - initializes parallel vector operations for sensitivities + * FNV_INITP_B - initializes parallel vector operations for adjoint problem + * FNV_INITP_QB - initializes parallel vector operations for adjoint quadratures + * + */ + +#ifndef SUNDIALS_MPI_COMM_F2C +#define MPI_Fint int +#endif + +void FNV_INITP(MPI_Fint *comm, int *code, long int *L, long int *N, int *ier); +void FNV_INITP_Q(MPI_Fint *comm, int *code, long int *Lq, long int *Nq, int *ier); +void FNV_INITP_B(MPI_Fint *comm, int *code, long int *LB, long int *NB, int *ier); +void FNV_INITP_QB(MPI_Fint *comm, int *code, long int *LqB, long int *NqB, int *ier); +void FNV_INITP_S(int *code, int *Ns, int *ier); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/src/nvec_par/nvector_parallel.c b/odemex/Parser/CVode/ida_src/src/nvec_par/nvector_parallel.c new file mode 100644 index 0000000..8a53fab --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/nvec_par/nvector_parallel.c @@ -0,0 +1,1152 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.1 $ + * $Date: 2006/07/05 15:32:37 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban, + * and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for a parallel MPI implementation + * of the NVECTOR package. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include + +#define ZERO RCONST(0.0) +#define HALF RCONST(0.5) +#define ONE RCONST(1.0) +#define ONEPT5 RCONST(1.5) + +/* Error Message */ + +#define BAD_N1 "N_VNew_Parallel -- Sum of local vector lengths differs from " +#define BAD_N2 "input global length. \n\n" +#define BAD_N BAD_N1 BAD_N2 + +/* Private function prototypes */ + +/* Reduction operations add/max/min over the processor group */ +static realtype VAllReduce_Parallel(realtype d, int op, MPI_Comm comm); +/* z=x */ +static void VCopy_Parallel(N_Vector x, N_Vector z); +/* z=x+y */ +static void VSum_Parallel(N_Vector x, N_Vector y, N_Vector z); +/* z=x-y */ +static void VDiff_Parallel(N_Vector x, N_Vector y, N_Vector z); +/* z=-x */ +static void VNeg_Parallel(N_Vector x, N_Vector z); +/* z=c(x+y) */ +static void VScaleSum_Parallel(realtype c, N_Vector x, N_Vector y, N_Vector z); +/* z=c(x-y) */ +static void VScaleDiff_Parallel(realtype c, N_Vector x, N_Vector y, N_Vector z); +/* z=ax+y */ +static void VLin1_Parallel(realtype a, N_Vector x, N_Vector y, N_Vector z); +/* z=ax-y */ +static void VLin2_Parallel(realtype a, N_Vector x, N_Vector y, N_Vector z); +/* y <- ax+y */ +static void Vaxpy_Parallel(realtype a, N_Vector x, N_Vector y); +/* x <- ax */ +static void VScaleBy_Parallel(realtype a, N_Vector x); + +/* + * ----------------------------------------------------------------- + * exported functions + * ----------------------------------------------------------------- + */ + +/* ---------------------------------------------------------------- + * Function to create a new parallel vector with empty data array + */ + +N_Vector N_VNewEmpty_Parallel(MPI_Comm comm, + long int local_length, + long int global_length) +{ + N_Vector v; + N_Vector_Ops ops; + N_VectorContent_Parallel content; + long int n, Nsum; + + /* Compute global length as sum of local lengths */ + n = local_length; + MPI_Allreduce(&n, &Nsum, 1, PVEC_INTEGER_MPI_TYPE, MPI_SUM, comm); + if (Nsum != global_length) { + printf(BAD_N); + return(NULL); + } + + /* Create vector */ + v = NULL; + v = (N_Vector) malloc(sizeof *v); + if (v == NULL) return(NULL); + + /* Create vector operation structure */ + ops = NULL; + ops = (N_Vector_Ops) malloc(sizeof(struct _generic_N_Vector_Ops)); + if (ops == NULL) { free(v); return(NULL); } + + ops->nvclone = N_VClone_Parallel; + ops->nvcloneempty = N_VCloneEmpty_Parallel; + ops->nvdestroy = N_VDestroy_Parallel; + ops->nvspace = N_VSpace_Parallel; + ops->nvgetarraypointer = N_VGetArrayPointer_Parallel; + ops->nvsetarraypointer = N_VSetArrayPointer_Parallel; + ops->nvlinearsum = N_VLinearSum_Parallel; + ops->nvconst = N_VConst_Parallel; + ops->nvprod = N_VProd_Parallel; + ops->nvdiv = N_VDiv_Parallel; + ops->nvscale = N_VScale_Parallel; + ops->nvabs = N_VAbs_Parallel; + ops->nvinv = N_VInv_Parallel; + ops->nvaddconst = N_VAddConst_Parallel; + ops->nvdotprod = N_VDotProd_Parallel; + ops->nvmaxnorm = N_VMaxNorm_Parallel; + ops->nvwrmsnormmask = N_VWrmsNormMask_Parallel; + ops->nvwrmsnorm = N_VWrmsNorm_Parallel; + ops->nvmin = N_VMin_Parallel; + ops->nvwl2norm = N_VWL2Norm_Parallel; + ops->nvl1norm = N_VL1Norm_Parallel; + ops->nvcompare = N_VCompare_Parallel; + ops->nvinvtest = N_VInvTest_Parallel; + ops->nvconstrmask = N_VConstrMask_Parallel; + ops->nvminquotient = N_VMinQuotient_Parallel; + + /* Create content */ + content = NULL; + content = (N_VectorContent_Parallel) malloc(sizeof(struct _N_VectorContent_Parallel)); + if (content == NULL) { free(ops); free(v); return(NULL); } + + /* Attach lengths and communicator */ + content->local_length = local_length; + content->global_length = global_length; + content->comm = comm; + content->own_data = FALSE; + content->data = NULL; + + /* Attach content and ops */ + v->content = content; + v->ops = ops; + + return(v); +} + +/* ---------------------------------------------------------------- + * Function to create a new parallel vector + */ + +N_Vector N_VNew_Parallel(MPI_Comm comm, + long int local_length, + long int global_length) +{ + N_Vector v; + realtype *data; + + v = NULL; + v = N_VNewEmpty_Parallel(comm, local_length, global_length); + if (v == NULL) return(NULL); + + /* Create data */ + if(local_length > 0) { + + /* Allocate memory */ + data = NULL; + data = (realtype *) malloc(local_length * sizeof(realtype)); + if(data == NULL) { N_VDestroy_Parallel(v); return(NULL); } + + /* Attach data */ + NV_OWN_DATA_P(v) = TRUE; + NV_DATA_P(v) = data; + + } + + return(v); +} + +/* ---------------------------------------------------------------- + * Function to create a parallel N_Vector with user data component + */ + +N_Vector N_VMake_Parallel(MPI_Comm comm, + long int local_length, + long int global_length, + realtype *v_data) +{ + N_Vector v; + + v = NULL; + v = N_VNewEmpty_Parallel(comm, local_length, global_length); + if (v == NULL) return(NULL); + + if (local_length > 0) { + /* Attach data */ + NV_OWN_DATA_P(v) = FALSE; + NV_DATA_P(v) = v_data; + } + + return(v); +} + +/* ---------------------------------------------------------------- + * Function to create an array of new parallel vectors. + */ + +N_Vector *N_VCloneVectorArray_Parallel(int count, N_Vector w) +{ + N_Vector *vs; + int j; + + if (count <= 0) return(NULL); + + vs = NULL; + vs = (N_Vector *) malloc(count * sizeof(N_Vector)); + if(vs == NULL) return(NULL); + + for (j = 0; j < count; j++) { + vs[j] = NULL; + vs[j] = N_VClone_Parallel(w); + if (vs[j] == NULL) { + N_VDestroyVectorArray_Parallel(vs, j-1); + return(NULL); + } + } + + return(vs); +} + +/* ---------------------------------------------------------------- + * Function to create an array of new parallel vectors with empty + * (NULL) data array. + */ + +N_Vector *N_VCloneVectorArrayEmpty_Parallel(int count, N_Vector w) +{ + N_Vector *vs; + int j; + + if (count <= 0) return(NULL); + + vs = NULL; + vs = (N_Vector *) malloc(count * sizeof(N_Vector)); + if(vs == NULL) return(NULL); + + for (j = 0; j < count; j++) { + vs[j] = NULL; + vs[j] = N_VCloneEmpty_Parallel(w); + if (vs[j] == NULL) { + N_VDestroyVectorArray_Parallel(vs, j-1); + return(NULL); + } + } + + return(vs); +} + +/* ---------------------------------------------------------------- + * Function to free an array created with N_VCloneVectorArray_Parallel + */ + +void N_VDestroyVectorArray_Parallel(N_Vector *vs, int count) +{ + int j; + + for (j = 0; j < count; j++) N_VDestroy_Parallel(vs[j]); + + free(vs); vs = NULL; + + return; +} + +/* ---------------------------------------------------------------- + * Function to print a parallel vector + */ + +void N_VPrint_Parallel(N_Vector x) +{ + long int i, N; + realtype *xd; + + xd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + + for (i = 0; i < N; i++) { +#if defined(SUNDIALS_EXTENDED_PRECISION) + printf("%Lg\n", xd[i]); +#elif defined(SUNDIALS_DOUBLE_PRECISION) + printf("%lg\n", xd[i]); +#else + printf("%g\n", xd[i]); +#endif + } + printf("\n"); + + return; +} + +/* + * ----------------------------------------------------------------- + * implementation of vector operations + * ----------------------------------------------------------------- + */ + +N_Vector N_VCloneEmpty_Parallel(N_Vector w) +{ + N_Vector v; + N_Vector_Ops ops; + N_VectorContent_Parallel content; + + if (w == NULL) return(NULL); + + /* Create vector */ + v = NULL; + v = (N_Vector) malloc(sizeof *v); + if (v == NULL) return(NULL); + + /* Create vector operation structure */ + ops = NULL; + ops = (N_Vector_Ops) malloc(sizeof(struct _generic_N_Vector_Ops)); + if (ops == NULL) { free(v); return(NULL); } + + ops->nvclone = w->ops->nvclone; + ops->nvcloneempty = w->ops->nvcloneempty; + ops->nvdestroy = w->ops->nvdestroy; + ops->nvspace = w->ops->nvspace; + ops->nvgetarraypointer = w->ops->nvgetarraypointer; + ops->nvsetarraypointer = w->ops->nvsetarraypointer; + ops->nvlinearsum = w->ops->nvlinearsum; + ops->nvconst = w->ops->nvconst; + ops->nvprod = w->ops->nvprod; + ops->nvdiv = w->ops->nvdiv; + ops->nvscale = w->ops->nvscale; + ops->nvabs = w->ops->nvabs; + ops->nvinv = w->ops->nvinv; + ops->nvaddconst = w->ops->nvaddconst; + ops->nvdotprod = w->ops->nvdotprod; + ops->nvmaxnorm = w->ops->nvmaxnorm; + ops->nvwrmsnormmask = w->ops->nvwrmsnormmask; + ops->nvwrmsnorm = w->ops->nvwrmsnorm; + ops->nvmin = w->ops->nvmin; + ops->nvwl2norm = w->ops->nvwl2norm; + ops->nvl1norm = w->ops->nvl1norm; + ops->nvcompare = w->ops->nvcompare; + ops->nvinvtest = w->ops->nvinvtest; + ops->nvconstrmask = w->ops->nvconstrmask; + ops->nvminquotient = w->ops->nvminquotient; + + /* Create content */ + content = NULL; + content = (N_VectorContent_Parallel) malloc(sizeof(struct _N_VectorContent_Parallel)); + if (content == NULL) { free(ops); free(v); return(NULL); } + + /* Attach lengths and communicator */ + content->local_length = NV_LOCLENGTH_P(w); + content->global_length = NV_GLOBLENGTH_P(w); + content->comm = NV_COMM_P(w); + content->own_data = FALSE; + content->data = NULL; + + /* Attach content and ops */ + v->content = content; + v->ops = ops; + + return(v); +} + +N_Vector N_VClone_Parallel(N_Vector w) +{ + N_Vector v; + realtype *data; + long int local_length; + + v = NULL; + v = N_VCloneEmpty_Parallel(w); + if (v == NULL) return(NULL); + + local_length = NV_LOCLENGTH_P(w); + + /* Create data */ + if(local_length > 0) { + + /* Allocate memory */ + data = NULL; + data = (realtype *) malloc(local_length * sizeof(realtype)); + if(data == NULL) { N_VDestroy_Parallel(v); return(NULL); } + + /* Attach data */ + NV_OWN_DATA_P(v) = TRUE; + NV_DATA_P(v) = data; + } + + return(v); +} + +void N_VDestroy_Parallel(N_Vector v) +{ + if ((NV_OWN_DATA_P(v) == TRUE) && (NV_DATA_P(v) != NULL)) { + free(NV_DATA_P(v)); + NV_DATA_P(v) = NULL; + } + free(v->content); v->content = NULL; + free(v->ops); v->ops = NULL; + free(v); v = NULL; + + return; +} + +void N_VSpace_Parallel(N_Vector v, long int *lrw, long int *liw) +{ + MPI_Comm comm; + int npes; + + comm = NV_COMM_P(v); + MPI_Comm_size(comm, &npes); + + *lrw = NV_GLOBLENGTH_P(v); + *liw = 2*npes; + + return; +} + +realtype *N_VGetArrayPointer_Parallel(N_Vector v) +{ + return((realtype *) NV_DATA_P(v)); +} + +void N_VSetArrayPointer_Parallel(realtype *v_data, N_Vector v) +{ + if (NV_LOCLENGTH_P(v) > 0) NV_DATA_P(v) = v_data; + + return; +} + +void N_VLinearSum_Parallel(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z) +{ + long int i, N; + realtype c, *xd, *yd, *zd; + N_Vector v1, v2; + booleantype test; + + xd = yd = zd = NULL; + + if ((b == ONE) && (z == y)) { /* BLAS usage: axpy y <- ax+y */ + Vaxpy_Parallel(a, x, y); + return; + } + + if ((a == ONE) && (z == x)) { /* BLAS usage: axpy x <- by+x */ + Vaxpy_Parallel(b, y, x); + return; + } + + /* Case: a == b == 1.0 */ + + if ((a == ONE) && (b == ONE)) { + VSum_Parallel(x, y, z); + return; + } + + /* Cases: (1) a == 1.0, b = -1.0, (2) a == -1.0, b == 1.0 */ + + if ((test = ((a == ONE) && (b == -ONE))) || ((a == -ONE) && (b == ONE))) { + v1 = test ? y : x; + v2 = test ? x : y; + VDiff_Parallel(v2, v1, z); + return; + } + + /* Cases: (1) a == 1.0, b == other or 0.0, (2) a == other or 0.0, b == 1.0 */ + /* if a or b is 0.0, then user should have called N_VScale */ + + if ((test = (a == ONE)) || (b == ONE)) { + c = test ? b : a; + v1 = test ? y : x; + v2 = test ? x : y; + VLin1_Parallel(c, v1, v2, z); + return; + } + + /* Cases: (1) a == -1.0, b != 1.0, (2) a != 1.0, b == -1.0 */ + + if ((test = (a == -ONE)) || (b == -ONE)) { + c = test ? b : a; + v1 = test ? y : x; + v2 = test ? x : y; + VLin2_Parallel(c, v1, v2, z); + return; + } + + /* Case: a == b */ + /* catches case both a and b are 0.0 - user should have called N_VConst */ + + if (a == b) { + VScaleSum_Parallel(a, x, y, z); + return; + } + + /* Case: a == -b */ + + if (a == -b) { + VScaleDiff_Parallel(a, x, y, z); + return; + } + + /* Do all cases not handled above: + (1) a == other, b == 0.0 - user should have called N_VScale + (2) a == 0.0, b == other - user should have called N_VScale + (3) a,b == other, a !=b, a != -b */ + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + yd = NV_DATA_P(y); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) + zd[i] = (a*xd[i])+(b*yd[i]); + + return; +} + +void N_VConst_Parallel(realtype c, N_Vector z) +{ + long int i, N; + realtype *zd; + + zd = NULL; + + N = NV_LOCLENGTH_P(z); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) zd[i] = c; + + return; +} + +void N_VProd_Parallel(N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + yd = NV_DATA_P(y); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]*yd[i]; + + return; +} + +void N_VDiv_Parallel(N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + yd = NV_DATA_P(y); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]/yd[i]; + + return; +} + +void N_VScale_Parallel(realtype c, N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + if (z == x) { /* BLAS usage: scale x <- cx */ + VScaleBy_Parallel(c, x); + return; + } + + if (c == ONE) { + VCopy_Parallel(x, z); + } else if (c == -ONE) { + VNeg_Parallel(x, z); + } else { + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + zd = NV_DATA_P(z); + for (i = 0; i < N; i++) + zd[i] = c*xd[i]; + } + + return; +} + +void N_VAbs_Parallel(N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) + zd[i] = ABS(xd[i]); + + return; +} + +void N_VInv_Parallel(N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) + zd[i] = ONE/xd[i]; + + return; +} + +void N_VAddConst_Parallel(N_Vector x, realtype b, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) zd[i] = xd[i]+b; + + return; +} + +realtype N_VDotProd_Parallel(N_Vector x, N_Vector y) +{ + long int i, N; + realtype sum, *xd, *yd, gsum; + MPI_Comm comm; + + sum = ZERO; + xd = yd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + yd = NV_DATA_P(y); + comm = NV_COMM_P(x); + + for (i = 0; i < N; i++) sum += xd[i]*yd[i]; + + gsum = VAllReduce_Parallel(sum, 1, comm); + + return(gsum); +} + +realtype N_VMaxNorm_Parallel(N_Vector x) +{ + long int i, N; + realtype max, *xd, gmax; + MPI_Comm comm; + + xd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + comm = NV_COMM_P(x); + + max = ZERO; + + for (i = 0; i < N; i++) { + if (ABS(xd[i]) > max) max = ABS(xd[i]); + } + + gmax = VAllReduce_Parallel(max, 2, comm); + + return(gmax); +} + +realtype N_VWrmsNorm_Parallel(N_Vector x, N_Vector w) +{ + long int i, N, N_global; + realtype sum, prodi, *xd, *wd, gsum; + MPI_Comm comm; + + sum = ZERO; + xd = wd = NULL; + + N = NV_LOCLENGTH_P(x); + N_global = NV_GLOBLENGTH_P(x); + xd = NV_DATA_P(x); + wd = NV_DATA_P(w); + comm = NV_COMM_P(x); + + for (i = 0; i < N; i++) { + prodi = xd[i]*wd[i]; + sum += SQR(prodi); + } + + gsum = VAllReduce_Parallel(sum, 1, comm); + + return(RSqrt(gsum/N_global)); +} + +realtype N_VWrmsNormMask_Parallel(N_Vector x, N_Vector w, N_Vector id) +{ + long int i, N, N_global; + realtype sum, prodi, *xd, *wd, *idd, gsum; + MPI_Comm comm; + + sum = ZERO; + xd = wd = idd = NULL; + + N = NV_LOCLENGTH_P(x); + N_global = NV_GLOBLENGTH_P(x); + xd = NV_DATA_P(x); + wd = NV_DATA_P(w); + idd = NV_DATA_P(id); + comm = NV_COMM_P(x); + + for (i = 0; i < N; i++) { + if (idd[i] > ZERO) { + prodi = xd[i]*wd[i]; + sum += SQR(prodi); + } + } + + gsum = VAllReduce_Parallel(sum, 1, comm); + + return(RSqrt(gsum/N_global)); +} + +realtype N_VMin_Parallel(N_Vector x) +{ + long int i, N; + realtype min, *xd, gmin; + MPI_Comm comm; + + xd = NULL; + + N = NV_LOCLENGTH_P(x); + comm = NV_COMM_P(x); + + min = BIG_REAL; + + if (N > 0) { + + xd = NV_DATA_P(x); + + min = xd[0]; + + for (i = 1; i < N; i++) { + if (xd[i] < min) min = xd[i]; + } + + } + + gmin = VAllReduce_Parallel(min, 3, comm); + + return(gmin); +} + +realtype N_VWL2Norm_Parallel(N_Vector x, N_Vector w) +{ + long int i, N; + realtype sum, prodi, *xd, *wd, gsum; + MPI_Comm comm; + + sum = ZERO; + xd = wd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + wd = NV_DATA_P(w); + comm = NV_COMM_P(x); + + for (i = 0; i < N; i++) { + prodi = xd[i]*wd[i]; + sum += SQR(prodi); + } + + gsum = VAllReduce_Parallel(sum, 1, comm); + + return(RSqrt(gsum)); +} + +realtype N_VL1Norm_Parallel(N_Vector x) +{ + long int i, N; + realtype sum, gsum, *xd; + MPI_Comm comm; + + sum = ZERO; + xd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + comm = NV_COMM_P(x); + + for (i = 0; i= c) ? ONE : ZERO; + } + + return; +} + +booleantype N_VInvTest_Parallel(N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd, val, gval; + MPI_Comm comm; + + xd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + zd = NV_DATA_P(z); + comm = NV_COMM_P(x); + + val = ONE; + for (i = 0; i < N; i++) { + if (xd[i] == ZERO) + val = ZERO; + else + zd[i] = ONE/xd[i]; + } + + gval = VAllReduce_Parallel(val, 3, comm); + + if (gval == ZERO) + return(FALSE); + else + return(TRUE); +} + +booleantype N_VConstrMask_Parallel(N_Vector c, N_Vector x, N_Vector m) +{ + long int i, N; + realtype temp; + realtype *cd, *xd, *md; + MPI_Comm comm; + + cd = xd = md = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + cd = NV_DATA_P(c); + md = NV_DATA_P(m); + comm = NV_COMM_P(x); + + temp = ONE; + + for (i = 0; i < N; i++) { + md[i] = ZERO; + if (cd[i] == ZERO) continue; + if (cd[i] > ONEPT5 || cd[i] < -ONEPT5) { + if (xd[i]*cd[i] <= ZERO) { temp = ZERO; md[i] = ONE; } + continue; + } + if (cd[i] > HALF || cd[i] < -HALF) { + if (xd[i]*cd[i] < ZERO ) { temp = ZERO; md[i] = ONE; } + } + } + + temp = VAllReduce_Parallel(temp, 3, comm); + + if (temp == ONE) return(TRUE); + else return(FALSE); +} + +realtype N_VMinQuotient_Parallel(N_Vector num, N_Vector denom) +{ + booleantype notEvenOnce; + long int i, N; + realtype *nd, *dd, min; + MPI_Comm comm; + + nd = dd = NULL; + + N = NV_LOCLENGTH_P(num); + nd = NV_DATA_P(num); + dd = NV_DATA_P(denom); + comm = NV_COMM_P(num); + + notEvenOnce = TRUE; + min = BIG_REAL; + + for (i = 0; i < N; i++) { + if (dd[i] == ZERO) continue; + else { + if (!notEvenOnce) min = MIN(min, nd[i]/dd[i]); + else { + min = nd[i]/dd[i]; + notEvenOnce = FALSE; + } + } + } + + return(VAllReduce_Parallel(min, 3, comm)); +} + +/* + * ----------------------------------------------------------------- + * private functions + * ----------------------------------------------------------------- + */ + +static realtype VAllReduce_Parallel(realtype d, int op, MPI_Comm comm) +{ + /* + * This function does a global reduction. The operation is + * sum if op = 1, + * max if op = 2, + * min if op = 3. + * The operation is over all processors in the communicator + */ + + realtype out; + + switch (op) { + case 1: MPI_Allreduce(&d, &out, 1, PVEC_REAL_MPI_TYPE, MPI_SUM, comm); + break; + + case 2: MPI_Allreduce(&d, &out, 1, PVEC_REAL_MPI_TYPE, MPI_MAX, comm); + break; + + case 3: MPI_Allreduce(&d, &out, 1, PVEC_REAL_MPI_TYPE, MPI_MIN, comm); + break; + + default: break; + } + + return(out); +} + +static void VCopy_Parallel(N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]; + + return; +} + +static void VSum_Parallel(N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + yd = NV_DATA_P(y); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]+yd[i]; + + return; +} + +static void VDiff_Parallel(N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + yd = NV_DATA_P(y); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]-yd[i]; + + return; +} + +static void VNeg_Parallel(N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) + zd[i] = -xd[i]; + + return; +} + +static void VScaleSum_Parallel(realtype c, N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + yd = NV_DATA_P(y); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) + zd[i] = c*(xd[i]+yd[i]); + + return; +} + +static void VScaleDiff_Parallel(realtype c, N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + yd = NV_DATA_P(y); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) + zd[i] = c*(xd[i]-yd[i]); + + return; +} + +static void VLin1_Parallel(realtype a, N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + yd = NV_DATA_P(y); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) + zd[i] = (a*xd[i])+yd[i]; + + return; +} + +static void VLin2_Parallel(realtype a, N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + yd = NV_DATA_P(y); + zd = NV_DATA_P(z); + + for (i = 0; i < N; i++) + zd[i] = (a*xd[i])-yd[i]; + + return; +} + +static void Vaxpy_Parallel(realtype a, N_Vector x, N_Vector y) +{ + long int i, N; + realtype *xd, *yd; + + xd = yd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + yd = NV_DATA_P(y); + + if (a == ONE) { + for (i = 0; i < N; i++) + yd[i] += xd[i]; + return; + } + + if (a == -ONE) { + for (i = 0; i < N; i++) + yd[i] -= xd[i]; + return; + } + + for (i = 0; i < N; i++) + yd[i] += a*xd[i]; + + return; +} + +static void VScaleBy_Parallel(realtype a, N_Vector x) +{ + long int i, N; + realtype *xd; + + xd = NULL; + + N = NV_LOCLENGTH_P(x); + xd = NV_DATA_P(x); + + for (i = 0; i < N; i++) + xd[i] *= a; + + return; +} diff --git a/odemex/Parser/CVode/ida_src/src/nvec_ser/CMakeLists.txt b/odemex/Parser/CVode/ida_src/src/nvec_ser/CMakeLists.txt new file mode 100644 index 0000000..9c97be5 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/nvec_ser/CMakeLists.txt @@ -0,0 +1,82 @@ +# --------------------------------------------------------------- +# $Revision: 1.3 $ +# $Date: 2009/02/17 02:58:48 $ +# --------------------------------------------------------------- +# Programmer: Radu Serban @ LLNL +# --------------------------------------------------------------- +# Copyright (c) 2007, The Regents of the University of California. +# Produced at the Lawrence Livermore National Laboratory. +# All rights reserved. +# For details, see the LICENSE file. +# --------------------------------------------------------------- +# CMakeLists.txt file for the serial NVECTOR library + +INSTALL(CODE "MESSAGE(\"\nInstall NVECTOR_SERIAL\n\")") + +# Add variable nvecserial_SOURCES with the sources for the NVECSERIAL lib +SET(nvecserial_SOURCES nvector_serial.c) + +# Add variable shared_SOURCES with the common SUNDIALS sources which will +# also be included in the NVECSERIAL library +SET(shared_SOURCES sundials_math.c) +ADD_PREFIX(${sundials_SOURCE_DIR}/src/sundials/ shared_SOURCES) + +# Add variable nvecserial_HEADERS with the exported NVECSERIAL header files +SET(nvecserial_HEADERS nvector_serial.h) +ADD_PREFIX(${sundials_SOURCE_DIR}/include/nvector/ nvecserial_HEADERS) + +# Add source directory to include directories +INCLUDE_DIRECTORIES(.) + +# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY +ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY) + +# Rules for building and installing the static library: +# - Add the build target for the NVECSERIAL library +# - Set the library name and make sure it is not deleted +# - Install the NVECSERIAL library +IF(BUILD_STATIC_LIBS) + ADD_LIBRARY(sundials_nvecserial_static STATIC ${nvecserial_SOURCES} ${shared_SOURCES}) + SET_TARGET_PROPERTIES(sundials_nvecserial_static + PROPERTIES OUTPUT_NAME sundials_nvecserial CLEAN_DIRECT_OUTPUT 1) + INSTALL(TARGETS sundials_nvecserial_static DESTINATION lib) +ENDIF(BUILD_STATIC_LIBS) + +# Rules for building and installing the shared library: +# - Add the build target for the NVECSERIAL library +# - Set the library name and make sure it is not deleted +# - Set VERSION and SOVERSION for shared libraries +# - Install the NVECSERIAL library +IF(BUILD_SHARED_LIBS) + ADD_LIBRARY(sundials_nvecserial_shared SHARED ${nvecserial_SOURCES} ${shared_SOURCES}) + SET_TARGET_PROPERTIES(sundials_nvecserial_shared + PROPERTIES OUTPUT_NAME sundials_nvecserial CLEAN_DIRECT_OUTPUT 1) + SET_TARGET_PROPERTIES(sundials_nvecserial_shared + PROPERTIES VERSION ${nveclib_VERSION} SOVERSION ${nveclib_SOVERSION}) + INSTALL(TARGETS sundials_nvecserial_shared DESTINATION lib) +ENDIF(BUILD_SHARED_LIBS) + +# Install the NVECSERIAL header files +INSTALL(FILES ${nvecserial_HEADERS} DESTINATION include/nvector) + +# If FCMIX is enabled, build and install the FNVECSERIAL library +IF(FCMIX_ENABLE AND F77_FOUND) + SET(fnvecserial_SOURCES fnvector_serial.c) + IF(BUILD_STATIC_LIBS) + ADD_LIBRARY(sundials_fnvecserial_static STATIC ${fnvecserial_SOURCES}) + SET_TARGET_PROPERTIES(sundials_fnvecserial_static + PROPERTIES OUTPUT_NAME sundials_fnvecserial CLEAN_DIRECT_OUTPUT 1) + INSTALL(TARGETS sundials_fnvecserial_static DESTINATION lib) + ENDIF(BUILD_STATIC_LIBS) + IF(BUILD_SHARED_LIBS) + ADD_LIBRARY(sundials_fnvecserial_shared ${fnvecserial_SOURCES}) + SET_TARGET_PROPERTIES(sundials_fnvecserial_shared + PROPERTIES OUTPUT_NAME sundials_fnvecserial CLEAN_DIRECT_OUTPUT 1) + SET_TARGET_PROPERTIES(sundials_fnvecserial_shared + PROPERTIES VERSION ${nveclib_VERSION} SOVERSION ${nveclib_SOVERSION}) + INSTALL(TARGETS sundials_fnvecserial_shared DESTINATION lib) + ENDIF(BUILD_SHARED_LIBS) +ENDIF(FCMIX_ENABLE AND F77_FOUND) + +# +MESSAGE(STATUS "Added NVECTOR_SERIAL module") diff --git a/odemex/Parser/CVode/ida_src/src/nvec_ser/Makefile.in b/odemex/Parser/CVode/ida_src/src/nvec_ser/Makefile.in new file mode 100644 index 0000000..fe8a6dc --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/nvec_ser/Makefile.in @@ -0,0 +1,125 @@ +# ----------------------------------------------------------------- +# $Revision: 1.8 $ +# $Date: 2007/01/29 17:36:28 $ +# ----------------------------------------------------------------- +# Programmer(s): Radu Serban and Aaron Collier @ LLNL +# ----------------------------------------------------------------- +# Copyright (c) 2002, The Regents of the University of California. +# Produced at the Lawrence Livermore National Laboratory. +# All rights reserved. +# For details, see the LICENSE file. +# ----------------------------------------------------------------- +# Makefile for serial NVECTOR module +# +# @configure_input@ +# ----------------------------------------------------------------- + +SHELL = @SHELL@ + +@SET_MAKE@ + +srcdir = @srcdir@ +builddir = @builddir@ +abs_builddir = @abs_builddir@ +top_builddir = @top_builddir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +includedir = @includedir@ +libdir = @libdir@ + +INSTALL = @INSTALL@ +INSTALL_LIB = @INSTALL_PROGRAM@ +INSTALL_HEADER = @INSTALL_DATA@ + +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ + +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CC = @CC@ +CFLAGS = @CFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ + +FCMIX_ENABLED = @FCMIX_ENABLED@ + +top_srcdir = $(srcdir)/../.. + +INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include + +LIB_REVISION = 0:2:0 + +NVECSER_LIB = libsundials_nvecserial.la +NVECSER_LIB_FILES = nvector_serial.lo + +FNVECSER_LIB = libsundials_fnvecserial.la +FNVECSER_LIB_FILES = fnvector_serial.lo + +SHARED_LIB_FILES = $(top_builddir)/src/sundials/sundials_math.lo + +mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs +rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs + +all: $(NVECSER_LIB) $(FNVECSER_LIB) + +$(NVECSER_LIB): shared $(NVECSER_LIB_FILES) + $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(NVECSER_LIB) $(NVECSER_LIB_FILES) $(SHARED_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -version-info $(LIB_REVISION) + +$(FNVECSER_LIB): $(FNVECSER_LIB_FILES) + @if test "X${FCMIX_ENABLED}" = "Xyes"; then \ + echo "${LIBTOOL} --mode=link ${CC} ${CFLAGS} -o ${FNVECSER_LIB} ${FNVECSER_LIB_FILES} ${SHARED_LIB_FILES} -rpath ${libdir} $(LDFLAGS) ${LIBS} -version-info ${LIB_REVISION}" ; \ + ${LIBTOOL} --mode=link ${CC} ${CFLAGS} -o ${FNVECSER_LIB} ${FNVECSER_LIB_FILES} ${SHARED_LIB_FILES} -rpath ${libdir} $(LDFLAGS) ${LIBS} -version-info ${LIB_REVISION} ; \ + fi + +install: $(NVECSER_LIB) $(FNVECSER_LIB) + $(mkinstalldirs) $(includedir)/nvector + $(mkinstalldirs) $(libdir) + $(LIBTOOL) --mode=install $(INSTALL_LIB) $(NVECSER_LIB) $(libdir) + $(INSTALL_HEADER) $(top_srcdir)/include/nvector/nvector_serial.h $(includedir)/nvector/ + @if test "X${FCMIX_ENABLED}" = "Xyes"; then \ + echo "${LIBTOOL} --mode=install ${INSTALL_LIB} ${FNVECSER_LIB} ${libdir}" ; \ + ${LIBTOOL} --mode=install ${INSTALL_LIB} ${FNVECSER_LIB} ${libdir} ; \ + fi + +uninstall: + $(LIBTOOL) --mode=uninstall rm -f $(libdir)/$(NVECSER_LIB) + @if test "X${FCMIX_ENABLED}" = "Xyes"; then \ + echo "${LIBTOOL} --mode=uninstall rm -f ${libdir}/${FNVECSER_LIB}" ; \ + ${LIBTOOL} --mode=uninstall rm -f ${libdir}/${FNVECSER_LIB} ; \ + fi + rm -f $(includedir)/nvector/nvector_serial.h + $(rminstalldirs) ${includedir}/nvector + +shared: + @cd ${top_builddir}/src/sundials ; \ + ${MAKE} ; \ + cd ${abs_builddir} + +clean: + $(LIBTOOL) --mode=clean rm -f $(NVECSER_LIB) + rm -f $(NVECSER_LIB_FILES) + rm -f nvector_serial.o + @if test "X${FCMIX_ENABLED}" = "Xyes"; then \ + echo "${LIBTOOL} --mode=clean rm -f ${FNVECSER_LIB}" ; \ + ${LIBTOOL} --mode=clean rm -f ${FNVECSER_LIB} ; \ + echo "rm -f ${FNVECSER_LIB_FILES}" ; \ + rm -f ${FNVECSER_LIB_FILES} ; \ + echo "rm -f fnvector_serial.o" ; \ + rm -f fnvector_serial.o ; \ + fi + +distclean: clean + rm -f Makefile + +nvector_serial.lo: $(srcdir)/nvector_serial.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/nvector_serial.c +fnvector_serial.lo: $(srcdir)/fnvector_serial.c + @if test "X${FCMIX_ENABLED}" = "Xyes"; then \ + echo "${LIBTOOL} --mode=compile ${CC} ${CPPFLAGS} $(INCLUDES) ${CFLAGS} -c ${srcdir}/fnvector_serial.c" ; \ + ${LIBTOOL} --mode=compile ${CC} ${CPPFLAGS} $(INCLUDES) ${CFLAGS} -c ${srcdir}/fnvector_serial.c ; \ + fi + +libtool: $(top_builddir)/$(LIBTOOL_DEPS) + @cd ${top_builddir} ; \ + ${SHELL} ./config.status --recheck ; \ + cd ${abs_builddir} diff --git a/odemex/Parser/CVode/ida_src/src/nvec_ser/README b/odemex/Parser/CVode/ida_src/src/nvec_ser/README new file mode 100644 index 0000000..03b7ee5 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/nvec_ser/README @@ -0,0 +1,131 @@ + NVECTOR_SERIAL + Release 2.4.0, January 2008 + +Serial implementation of the NVECTOR module for SUNDIALS. + +NVECTOR_SERIAL defines the content field of N_Vector to be a structure +containing the length of the vector, a pointer to the beginning of a +contiguous data array, and a boolean flag indicating ownership of the +data array. + +NVECTOR_SERIAL defines five macros to provide access to the content of +a serial N_Vector, several constructors for variables of type N_Vector, +a constructor for an array of variables of type N_Vector, and destructors +for N_Vector and N_Vector array. + +NVECTOR_SERIAL provides implementations for all vector operations defined +by the generic NVECTOR module in the table of operations. + + +A. Documentation +---------------- + +The serial NVECTOR implementation is fully described in the user documentation +for any of the SUNDIALS solvers [1-5]. A PDF file for the user guide for a +particular solver is available in the solver's subdirectory under doc/. + + +B. Installation +--------------- + +For basic installation instructions see /sundials/INSTALL_NOTES. +For complete installation instructions see any of the user guides. + + +C. References +------------- + +[1] A. C. Hindmarsh and R. Serban, "User Documentation for CVODE v2.4.0," + LLLNL technical report UCRL-MA-208108, November 2004. + +[2] A. C. Hindmarsh and R. Serban, "User Documentation for CVODES v2.4.0," + LLNL technical report UCRL-MA-208111, November 2004. + +[3] A. C. Hindmarsh and R. Serban, "User Documentation for IDA v2.4.0," + LLNL technical report UCRL-MA-208112, November 2004. + +[4] R. Serban and C. Petra, "User Documentation for IDAS v1.0.0," + LLNL technical report UCRL-SM-234051, August 2007. + +[5] A. M. Collier, A. C. Hindmarsh, R. Serban,and C. S. Woodward, "User + Documentation for KINSOL v2.4.0," LLNL technical report UCRL-MA-208116, + November 2004. + + +D. Releases +----------- + +v. 2.4.0 - Jan. 2008 +v. 2.3.0 - Nov. 2006 +v. 2.2.0 - Mar. 2006 +v. 2.1.1 - May. 2005 +v. 2.1.0 - Apr. 2005 +v. 2.0.2 - Mar. 2005 +v. 2.0.1 - Jan. 2005 +v. 2.0 - Dec. 2004 +v. 1.0 - Jul. 2002 (first SUNDIALS release) + + +E. Revision History +------------------- + +v. 2.3.0 (Nov. 2006) ---> v. 2.4.0 (Jan. 2008) +--------------------------------------------------------- + +- none + + +v. 2.2.0 (Mar. 2006) ---> v. 2.3.0 (Nov. 2006) +---------------------------------------------- + +- Changes related to the build system + - reorganized source tree. Header files in ${srcdir}/include/nvector; + sources in ${srcdir}/src/nvec_ser + - exported header files in ${includedir}/sundials + + +v. 2.1.1 (May. 2005) ---> v. 2.2.0 (Mar. 2006) +---------------------------------------------- + +- none + +v. 2.1.0 (Apr. 2005) ---> v. 2.1.1 (May. 2005) +---------------------------------------------- + +- Changes to data structures + - added N_VCloneEmpty to global vector operations table + +v. 2.0.2 (Mar. 2005) ---> v. 2.1.0 (Apr. 2005) +---------------------------------------------- + +- none + +v. 2.0.1 (Jan. 2005) ---> v. 2.0.2 (Mar. 2005) +---------------------------------------------- + +- Changes related to the build system + - fixed autoconf-related bug to allow configuration with the PGI Fortran compiler + - modified to use customized detection of the Fortran name mangling scheme + (autoconf's AC_F77_WRAPPERS routine is problematic on some platforms) + - added --with-mpi-flags as a configure option to allow user to specify + MPI-specific flags + - updated Makefiles for Fortran examples to avoid C++ compiler errors (now use + CC and MPICC to link) + +v. 2.0 (Dec. 2004) ---> v. 2.0.1 (Jan. 2005) +-------------------------------------------- + +- Changes related to the build system + - changed order of compiler directives in header files to avoid compilation + errors when using a C++ compiler. + +v. 1.0 (Jul. 2002) ---> v. 2.0 (Dec. 2004) +------------------------------------------ + +- Revised to correspond to new generic NVECTOR module + (see sundials/shared/README). +- Extended the list of user-callable functions provided by NVECTOR_SERIAL + outside the table of vector operations. +- Revised the F/C interface to use underscore flags for name mapping + and to use precision flag from configure. +- Revised F/C routine NVECTOR names for uniformity. diff --git a/odemex/Parser/CVode/ida_src/src/nvec_ser/fnvector_serial.c b/odemex/Parser/CVode/ida_src/src/nvec_ser/fnvector_serial.c new file mode 100644 index 0000000..8f83c80 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/nvec_ser/fnvector_serial.c @@ -0,0 +1,147 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.1 $ + * $Date: 2006/07/05 15:32:37 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This file (companion of nvector_serial.h) contains the + * implementation needed for the Fortran initialization of serial + * vector operations. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "fnvector_serial.h" + +/* Define global vector variables */ + +N_Vector F2C_CVODE_vec; +N_Vector F2C_CVODE_vecQ; +N_Vector *F2C_CVODE_vecS; +N_Vector F2C_CVODE_vecB; +N_Vector F2C_CVODE_vecQB; + +N_Vector F2C_IDA_vec; +N_Vector F2C_IDA_vecQ; +N_Vector *F2C_IDA_vecS; +N_Vector F2C_IDA_vecB; +N_Vector F2C_IDA_vecQB; + +N_Vector F2C_KINSOL_vec; + +/* Fortran callable interfaces */ + +void FNV_INITS(int *code, long int *N, int *ier) +{ + *ier = 0; + + switch(*code) { + case FCMIX_CVODE: + F2C_CVODE_vec = NULL; + F2C_CVODE_vec = N_VNewEmpty_Serial(*N); + if (F2C_CVODE_vec == NULL) *ier = -1; + break; + case FCMIX_IDA: + F2C_IDA_vec = NULL; + F2C_IDA_vec = N_VNewEmpty_Serial(*N); + if (F2C_IDA_vec == NULL) *ier = -1; + break; + case FCMIX_KINSOL: + F2C_KINSOL_vec = NULL; + F2C_KINSOL_vec = N_VNewEmpty_Serial(*N); + if (F2C_KINSOL_vec == NULL) *ier = -1; + break; + default: + *ier = -1; + } +} + +void FNV_INITS_Q(int *code, long int *Nq, int *ier) +{ + *ier = 0; + + switch(*code) { + case FCMIX_CVODE: + F2C_CVODE_vecQ = NULL; + F2C_CVODE_vecQ = N_VNewEmpty_Serial(*Nq); + if (F2C_CVODE_vecQ == NULL) *ier = -1; + break; + case FCMIX_IDA: + F2C_IDA_vecQ = NULL; + F2C_IDA_vecQ = N_VNewEmpty_Serial(*Nq); + if (F2C_IDA_vecQ == NULL) *ier = -1; + break; + default: + *ier = -1; + } +} + +void FNV_INITS_B(int *code, long int *NB, int *ier) +{ + *ier = 0; + + switch(*code) { + case FCMIX_CVODE: + F2C_CVODE_vecB = NULL; + F2C_CVODE_vecB = N_VNewEmpty_Serial(*NB); + if (F2C_CVODE_vecB == NULL) *ier = -1; + break; + case FCMIX_IDA: + F2C_IDA_vecB = NULL; + F2C_IDA_vecB = N_VNewEmpty_Serial(*NB); + if (F2C_IDA_vecB == NULL) *ier = -1; + break; + default: + *ier = -1; + } +} + +void FNV_INITS_QB(int *code, long int *NqB, int *ier) +{ + *ier = 0; + + switch(*code) { + case FCMIX_CVODE: + F2C_CVODE_vecQB = NULL; + F2C_CVODE_vecQB = N_VNewEmpty_Serial(*NqB); + if (F2C_CVODE_vecQB == NULL) *ier = -1; + break; + case FCMIX_IDA: + F2C_IDA_vecQB = NULL; + F2C_IDA_vecQB = N_VNewEmpty_Serial(*NqB); + if (F2C_IDA_vecQB == NULL) *ier = -1; + break; + default: + *ier = -1; + } +} + +void FNV_INITS_S(int *code, int *Ns, int *ier) +{ + *ier = 0; + + switch(*code) { + case FCMIX_CVODE: + F2C_CVODE_vecS = NULL; + F2C_CVODE_vecS = (N_Vector *) N_VCloneVectorArrayEmpty_Serial(*Ns, F2C_CVODE_vec); + if (F2C_CVODE_vecS == NULL) *ier = -1; + break; + case FCMIX_IDA: + F2C_IDA_vecS = NULL; + F2C_IDA_vecS = (N_Vector *) N_VCloneVectorArrayEmpty_Serial(*Ns, F2C_IDA_vec); + if (F2C_IDA_vecS == NULL) *ier = -1; + break; + default: + *ier = -1; + } +} + + diff --git a/odemex/Parser/CVode/ida_src/src/nvec_ser/fnvector_serial.h b/odemex/Parser/CVode/ida_src/src/nvec_ser/fnvector_serial.h new file mode 100644 index 0000000..2642337 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/nvec_ser/fnvector_serial.h @@ -0,0 +1,84 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.3 $ + * $Date: 2006/11/29 00:05:09 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This file (companion of nvector_serial.h) contains the + * definitions needed for the initialization of serial + * vector operations in Fortran. + * ----------------------------------------------------------------- + */ + +#ifndef _FNVECTOR_SERIAL_H +#define _FNVECTOR_SERIAL_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +#if defined(F77_FUNC) + +#define FNV_INITS F77_FUNC(fnvinits, FNVINITS) +#define FNV_INITS_Q F77_FUNC_(fnvinits_q, FNVINITS_Q) +#define FNV_INITS_S F77_FUNC_(fnvinits_s, FNVINITS_S) +#define FNV_INITS_B F77_FUNC_(fnvinits_b, FNVINITS_B) +#define FNV_INITS_QB F77_FUNC_(fnvinits_qb, FNVINITS_QB) + +#else + +#define FNV_INITS fnvinits_ +#define FNV_INITS_Q fnvinits_q_ +#define FNV_INITS_S fnvinits_s_ +#define FNV_INITS_B fnvinits_b_ +#define FNV_INITS_QB fnvinits_qb_ + +#endif + +/* Declarations of global variables */ + +extern N_Vector F2C_CVODE_vec; +extern N_Vector F2C_CVODE_vecQ; +extern N_Vector *F2C_CVODE_vecS; +extern N_Vector F2C_CVODE_vecB; +extern N_Vector F2C_CVODE_vecQB; + +extern N_Vector F2C_IDA_vec; +extern N_Vector F2C_IDA_vecQ; +extern N_Vector *F2C_IDA_vecS; +extern N_Vector F2C_IDA_vecB; +extern N_Vector F2C_IDA_vecQB; + +extern N_Vector F2C_KINSOL_vec; + +/* + * Prototypes of exported functions + * + * FNV_INITS - initializes serial vector operations for main problem + * FNV_INITS_Q - initializes serial vector operations for quadratures + * FNV_INITS_S - initializes serial vector operations for sensitivities + * FNV_INITS_B - initializes serial vector operations for adjoint problem + * FNV_INITS_QB - initializes serial vector operations for adjoint quadratures + * + */ + +void FNV_INITS(int *code, long int *neq, int *ier); +void FNV_INITS_Q(int *code, long int *Nq, int *ier); +void FNV_INITS_S(int *code, int *Ns, int *ier); +void FNV_INITS_B(int *code, long int *NB, int *ier); +void FNV_INITS_QB(int *code, long int *NqB, int *ier); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/odemex/Parser/CVode/ida_src/src/nvec_ser/nvector_serial.c b/odemex/Parser/CVode/ida_src/src/nvec_ser/nvector_serial.c new file mode 100644 index 0000000..c890253 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/nvec_ser/nvector_serial.c @@ -0,0 +1,1034 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.1 $ + * $Date: 2006/07/05 15:32:37 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban, + * and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for a serial implementation + * of the NVECTOR package. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include + +#define ZERO RCONST(0.0) +#define HALF RCONST(0.5) +#define ONE RCONST(1.0) +#define ONEPT5 RCONST(1.5) + +/* Private function prototypes */ +/* z=x */ +static void VCopy_Serial(N_Vector x, N_Vector z); +/* z=x+y */ +static void VSum_Serial(N_Vector x, N_Vector y, N_Vector z); +/* z=x-y */ +static void VDiff_Serial(N_Vector x, N_Vector y, N_Vector z); +/* z=-x */ +static void VNeg_Serial(N_Vector x, N_Vector z); +/* z=c(x+y) */ +static void VScaleSum_Serial(realtype c, N_Vector x, N_Vector y, N_Vector z); +/* z=c(x-y) */ +static void VScaleDiff_Serial(realtype c, N_Vector x, N_Vector y, N_Vector z); +/* z=ax+y */ +static void VLin1_Serial(realtype a, N_Vector x, N_Vector y, N_Vector z); +/* z=ax-y */ +static void VLin2_Serial(realtype a, N_Vector x, N_Vector y, N_Vector z); +/* y <- ax+y */ +static void Vaxpy_Serial(realtype a, N_Vector x, N_Vector y); +/* x <- ax */ +static void VScaleBy_Serial(realtype a, N_Vector x); + +/* + * ----------------------------------------------------------------- + * exported functions + * ----------------------------------------------------------------- + */ + +/* ---------------------------------------------------------------------------- + * Function to create a new empty serial vector + */ + +N_Vector N_VNewEmpty_Serial(long int length) +{ + N_Vector v; + N_Vector_Ops ops; + N_VectorContent_Serial content; + + /* Create vector */ + v = NULL; + v = (N_Vector) malloc(sizeof *v); + if (v == NULL) return(NULL); + + /* Create vector operation structure */ + ops = NULL; + ops = (N_Vector_Ops) malloc(sizeof(struct _generic_N_Vector_Ops)); + if (ops == NULL) { free(v); return(NULL); } + + ops->nvclone = N_VClone_Serial; + ops->nvcloneempty = N_VCloneEmpty_Serial; + ops->nvdestroy = N_VDestroy_Serial; + ops->nvspace = N_VSpace_Serial; + ops->nvgetarraypointer = N_VGetArrayPointer_Serial; + ops->nvsetarraypointer = N_VSetArrayPointer_Serial; + ops->nvlinearsum = N_VLinearSum_Serial; + ops->nvconst = N_VConst_Serial; + ops->nvprod = N_VProd_Serial; + ops->nvdiv = N_VDiv_Serial; + ops->nvscale = N_VScale_Serial; + ops->nvabs = N_VAbs_Serial; + ops->nvinv = N_VInv_Serial; + ops->nvaddconst = N_VAddConst_Serial; + ops->nvdotprod = N_VDotProd_Serial; + ops->nvmaxnorm = N_VMaxNorm_Serial; + ops->nvwrmsnormmask = N_VWrmsNormMask_Serial; + ops->nvwrmsnorm = N_VWrmsNorm_Serial; + ops->nvmin = N_VMin_Serial; + ops->nvwl2norm = N_VWL2Norm_Serial; + ops->nvl1norm = N_VL1Norm_Serial; + ops->nvcompare = N_VCompare_Serial; + ops->nvinvtest = N_VInvTest_Serial; + ops->nvconstrmask = N_VConstrMask_Serial; + ops->nvminquotient = N_VMinQuotient_Serial; + + /* Create content */ + content = NULL; + content = (N_VectorContent_Serial) malloc(sizeof(struct _N_VectorContent_Serial)); + if (content == NULL) { free(ops); free(v); return(NULL); } + + content->length = length; + content->own_data = FALSE; + content->data = NULL; + + /* Attach content and ops */ + v->content = content; + v->ops = ops; + + return(v); +} + +/* ---------------------------------------------------------------------------- + * Function to create a new serial vector + */ + +N_Vector N_VNew_Serial(long int length) +{ + N_Vector v; + realtype *data; + + v = NULL; + v = N_VNewEmpty_Serial(length); + if (v == NULL) return(NULL); + + /* Create data */ + if (length > 0) { + + /* Allocate memory */ + data = NULL; + data = (realtype *) malloc(length * sizeof(realtype)); + if(data == NULL) { N_VDestroy_Serial(v); return(NULL); } + + /* Attach data */ + NV_OWN_DATA_S(v) = TRUE; + NV_DATA_S(v) = data; + + } + + return(v); +} + +/* ---------------------------------------------------------------------------- + * Function to create a serial N_Vector with user data component + */ + +N_Vector N_VMake_Serial(long int length, realtype *v_data) +{ + N_Vector v; + + v = NULL; + v = N_VNewEmpty_Serial(length); + if (v == NULL) return(NULL); + + if (length > 0) { + /* Attach data */ + NV_OWN_DATA_S(v) = FALSE; + NV_DATA_S(v) = v_data; + } + + return(v); +} + +/* ---------------------------------------------------------------------------- + * Function to create an array of new serial vectors. + */ + +N_Vector *N_VCloneVectorArray_Serial(int count, N_Vector w) +{ + N_Vector *vs; + int j; + + if (count <= 0) return(NULL); + + vs = NULL; + vs = (N_Vector *) malloc(count * sizeof(N_Vector)); + if(vs == NULL) return(NULL); + + for (j = 0; j < count; j++) { + vs[j] = NULL; + vs[j] = N_VClone_Serial(w); + if (vs[j] == NULL) { + N_VDestroyVectorArray_Serial(vs, j-1); + return(NULL); + } + } + + return(vs); +} + +/* ---------------------------------------------------------------------------- + * Function to create an array of new serial vectors with NULL data array. + */ + +N_Vector *N_VCloneVectorArrayEmpty_Serial(int count, N_Vector w) +{ + N_Vector *vs; + int j; + + if (count <= 0) return(NULL); + + vs = NULL; + vs = (N_Vector *) malloc(count * sizeof(N_Vector)); + if(vs == NULL) return(NULL); + + for (j = 0; j < count; j++) { + vs[j] = NULL; + vs[j] = N_VCloneEmpty_Serial(w); + if (vs[j] == NULL) { + N_VDestroyVectorArray_Serial(vs, j-1); + return(NULL); + } + } + + return(vs); +} + +/* ---------------------------------------------------------------------------- + * Function to free an array created with N_VCloneVectorArray_Serial + */ + +void N_VDestroyVectorArray_Serial(N_Vector *vs, int count) +{ + int j; + + for (j = 0; j < count; j++) N_VDestroy_Serial(vs[j]); + + free(vs); vs = NULL; + + return; +} + +/* ---------------------------------------------------------------------------- + * Function to print the a serial vector + */ + +void N_VPrint_Serial(N_Vector x) +{ + long int i, N; + realtype *xd; + + xd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + + for (i = 0; i < N; i++) { +#if defined(SUNDIALS_EXTENDED_PRECISION) + printf("%11.8Lg\n", xd[i]); +#elif defined(SUNDIALS_DOUBLE_PRECISION) + printf("%11.8lg\n", xd[i]); +#else + printf("%11.8g\n", xd[i]); +#endif + } + printf("\n"); + + return; +} + +/* + * ----------------------------------------------------------------- + * implementation of vector operations + * ----------------------------------------------------------------- + */ + +N_Vector N_VCloneEmpty_Serial(N_Vector w) +{ + N_Vector v; + N_Vector_Ops ops; + N_VectorContent_Serial content; + + if (w == NULL) return(NULL); + + /* Create vector */ + v = NULL; + v = (N_Vector) malloc(sizeof *v); + if (v == NULL) return(NULL); + + /* Create vector operation structure */ + ops = NULL; + ops = (N_Vector_Ops) malloc(sizeof(struct _generic_N_Vector_Ops)); + if (ops == NULL) { free(v); return(NULL); } + + ops->nvclone = w->ops->nvclone; + ops->nvcloneempty = w->ops->nvcloneempty; + ops->nvdestroy = w->ops->nvdestroy; + ops->nvspace = w->ops->nvspace; + ops->nvgetarraypointer = w->ops->nvgetarraypointer; + ops->nvsetarraypointer = w->ops->nvsetarraypointer; + ops->nvlinearsum = w->ops->nvlinearsum; + ops->nvconst = w->ops->nvconst; + ops->nvprod = w->ops->nvprod; + ops->nvdiv = w->ops->nvdiv; + ops->nvscale = w->ops->nvscale; + ops->nvabs = w->ops->nvabs; + ops->nvinv = w->ops->nvinv; + ops->nvaddconst = w->ops->nvaddconst; + ops->nvdotprod = w->ops->nvdotprod; + ops->nvmaxnorm = w->ops->nvmaxnorm; + ops->nvwrmsnormmask = w->ops->nvwrmsnormmask; + ops->nvwrmsnorm = w->ops->nvwrmsnorm; + ops->nvmin = w->ops->nvmin; + ops->nvwl2norm = w->ops->nvwl2norm; + ops->nvl1norm = w->ops->nvl1norm; + ops->nvcompare = w->ops->nvcompare; + ops->nvinvtest = w->ops->nvinvtest; + ops->nvconstrmask = w->ops->nvconstrmask; + ops->nvminquotient = w->ops->nvminquotient; + + /* Create content */ + content = NULL; + content = (N_VectorContent_Serial) malloc(sizeof(struct _N_VectorContent_Serial)); + if (content == NULL) { free(ops); free(v); return(NULL); } + + content->length = NV_LENGTH_S(w); + content->own_data = FALSE; + content->data = NULL; + + /* Attach content and ops */ + v->content = content; + v->ops = ops; + + return(v); +} + +N_Vector N_VClone_Serial(N_Vector w) +{ + N_Vector v; + realtype *data; + long int length; + + v = NULL; + v = N_VCloneEmpty_Serial(w); + if (v == NULL) return(NULL); + + length = NV_LENGTH_S(w); + + /* Create data */ + if (length > 0) { + + /* Allocate memory */ + data = NULL; + data = (realtype *) malloc(length * sizeof(realtype)); + if(data == NULL) { N_VDestroy_Serial(v); return(NULL); } + + /* Attach data */ + NV_OWN_DATA_S(v) = TRUE; + NV_DATA_S(v) = data; + + } + + return(v); +} + +void N_VDestroy_Serial(N_Vector v) +{ + if (NV_OWN_DATA_S(v) == TRUE) { + free(NV_DATA_S(v)); + NV_DATA_S(v) = NULL; + } + free(v->content); v->content = NULL; + free(v->ops); v->ops = NULL; + free(v); v = NULL; + + return; +} + +void N_VSpace_Serial(N_Vector v, long int *lrw, long int *liw) +{ + *lrw = NV_LENGTH_S(v); + *liw = 1; + + return; +} + +realtype *N_VGetArrayPointer_Serial(N_Vector v) +{ + return((realtype *) NV_DATA_S(v)); +} + +void N_VSetArrayPointer_Serial(realtype *v_data, N_Vector v) +{ + if (NV_LENGTH_S(v) > 0) NV_DATA_S(v) = v_data; + + return; +} + +void N_VLinearSum_Serial(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z) +{ + long int i, N; + realtype c, *xd, *yd, *zd; + N_Vector v1, v2; + booleantype test; + + xd = yd = zd = NULL; + + if ((b == ONE) && (z == y)) { /* BLAS usage: axpy y <- ax+y */ + Vaxpy_Serial(a,x,y); + return; + } + + if ((a == ONE) && (z == x)) { /* BLAS usage: axpy x <- by+x */ + Vaxpy_Serial(b,y,x); + return; + } + + /* Case: a == b == 1.0 */ + + if ((a == ONE) && (b == ONE)) { + VSum_Serial(x, y, z); + return; + } + + /* Cases: (1) a == 1.0, b = -1.0, (2) a == -1.0, b == 1.0 */ + + if ((test = ((a == ONE) && (b == -ONE))) || ((a == -ONE) && (b == ONE))) { + v1 = test ? y : x; + v2 = test ? x : y; + VDiff_Serial(v2, v1, z); + return; + } + + /* Cases: (1) a == 1.0, b == other or 0.0, (2) a == other or 0.0, b == 1.0 */ + /* if a or b is 0.0, then user should have called N_VScale */ + + if ((test = (a == ONE)) || (b == ONE)) { + c = test ? b : a; + v1 = test ? y : x; + v2 = test ? x : y; + VLin1_Serial(c, v1, v2, z); + return; + } + + /* Cases: (1) a == -1.0, b != 1.0, (2) a != 1.0, b == -1.0 */ + + if ((test = (a == -ONE)) || (b == -ONE)) { + c = test ? b : a; + v1 = test ? y : x; + v2 = test ? x : y; + VLin2_Serial(c, v1, v2, z); + return; + } + + /* Case: a == b */ + /* catches case both a and b are 0.0 - user should have called N_VConst */ + + if (a == b) { + VScaleSum_Serial(a, x, y, z); + return; + } + + /* Case: a == -b */ + + if (a == -b) { + VScaleDiff_Serial(a, x, y, z); + return; + } + + /* Do all cases not handled above: + (1) a == other, b == 0.0 - user should have called N_VScale + (2) a == 0.0, b == other - user should have called N_VScale + (3) a,b == other, a !=b, a != -b */ + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = (a*xd[i])+(b*yd[i]); + + return; +} + +void N_VConst_Serial(realtype c, N_Vector z) +{ + long int i, N; + realtype *zd; + + zd = NULL; + + N = NV_LENGTH_S(z); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) zd[i] = c; + + return; +} + +void N_VProd_Serial(N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]*yd[i]; + + return; +} + +void N_VDiv_Serial(N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]/yd[i]; + + return; +} + +void N_VScale_Serial(realtype c, N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + if (z == x) { /* BLAS usage: scale x <- cx */ + VScaleBy_Serial(c, x); + return; + } + + if (c == ONE) { + VCopy_Serial(x, z); + } else if (c == -ONE) { + VNeg_Serial(x, z); + } else { + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + zd = NV_DATA_S(z); + for (i = 0; i < N; i++) + zd[i] = c*xd[i]; + } + + return; +} + +void N_VAbs_Serial(N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = ABS(xd[i]); + + return; +} + +void N_VInv_Serial(N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = ONE/xd[i]; + + return; +} + +void N_VAddConst_Serial(N_Vector x, realtype b, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]+b; + + return; +} + +realtype N_VDotProd_Serial(N_Vector x, N_Vector y) +{ + long int i, N; + realtype sum, *xd, *yd; + + sum = ZERO; + xd = yd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + + for (i = 0; i < N; i++) + sum += xd[i]*yd[i]; + + return(sum); +} + +realtype N_VMaxNorm_Serial(N_Vector x) +{ + long int i, N; + realtype max, *xd; + + max = ZERO; + xd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + + for (i = 0; i < N; i++) { + if (ABS(xd[i]) > max) max = ABS(xd[i]); + } + + return(max); +} + +realtype N_VWrmsNorm_Serial(N_Vector x, N_Vector w) +{ + long int i, N; + realtype sum, prodi, *xd, *wd; + + sum = ZERO; + xd = wd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + wd = NV_DATA_S(w); + + for (i = 0; i < N; i++) { + prodi = xd[i]*wd[i]; + sum += SQR(prodi); + } + + return(RSqrt(sum/N)); +} + +realtype N_VWrmsNormMask_Serial(N_Vector x, N_Vector w, N_Vector id) +{ + long int i, N; + realtype sum, prodi, *xd, *wd, *idd; + + sum = ZERO; + xd = wd = idd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + wd = NV_DATA_S(w); + idd = NV_DATA_S(id); + + for (i = 0; i < N; i++) { + if (idd[i] > ZERO) { + prodi = xd[i]*wd[i]; + sum += SQR(prodi); + } + } + + return(RSqrt(sum / N)); +} + +realtype N_VMin_Serial(N_Vector x) +{ + long int i, N; + realtype min, *xd; + + xd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + + min = xd[0]; + + for (i = 1; i < N; i++) { + if (xd[i] < min) min = xd[i]; + } + + return(min); +} + +realtype N_VWL2Norm_Serial(N_Vector x, N_Vector w) +{ + long int i, N; + realtype sum, prodi, *xd, *wd; + + sum = ZERO; + xd = wd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + wd = NV_DATA_S(w); + + for (i = 0; i < N; i++) { + prodi = xd[i]*wd[i]; + sum += SQR(prodi); + } + + return(RSqrt(sum)); +} + +realtype N_VL1Norm_Serial(N_Vector x) +{ + long int i, N; + realtype sum, *xd; + + sum = ZERO; + xd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + + for (i = 0; i= c) ? ONE : ZERO; + } + + return; +} + +booleantype N_VInvTest_Serial(N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) { + if (xd[i] == ZERO) return(FALSE); + zd[i] = ONE/xd[i]; + } + + return(TRUE); +} + +booleantype N_VConstrMask_Serial(N_Vector c, N_Vector x, N_Vector m) +{ + long int i, N; + booleantype test; + realtype *cd, *xd, *md; + + cd = xd = md = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + cd = NV_DATA_S(c); + md = NV_DATA_S(m); + + test = TRUE; + + for (i = 0; i < N; i++) { + md[i] = ZERO; + if (cd[i] == ZERO) continue; + if (cd[i] > ONEPT5 || cd[i] < -ONEPT5) { + if ( xd[i]*cd[i] <= ZERO) { test = FALSE; md[i] = ONE; } + continue; + } + if ( cd[i] > HALF || cd[i] < -HALF) { + if (xd[i]*cd[i] < ZERO ) { test = FALSE; md[i] = ONE; } + } + } + + return(test); +} + +realtype N_VMinQuotient_Serial(N_Vector num, N_Vector denom) +{ + booleantype notEvenOnce; + long int i, N; + realtype *nd, *dd, min; + + nd = dd = NULL; + + N = NV_LENGTH_S(num); + nd = NV_DATA_S(num); + dd = NV_DATA_S(denom); + + notEvenOnce = TRUE; + min = BIG_REAL; + + for (i = 0; i < N; i++) { + if (dd[i] == ZERO) continue; + else { + if (!notEvenOnce) min = MIN(min, nd[i]/dd[i]); + else { + min = nd[i]/dd[i]; + notEvenOnce = FALSE; + } + } + } + + return(min); +} + +/* + * ----------------------------------------------------------------- + * private functions + * ----------------------------------------------------------------- + */ + +static void VCopy_Serial(N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]; + + return; +} + +static void VSum_Serial(N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]+yd[i]; + + return; +} + +static void VDiff_Serial(N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]-yd[i]; + + return; +} + +static void VNeg_Serial(N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = -xd[i]; + + return; +} + +static void VScaleSum_Serial(realtype c, N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = c*(xd[i]+yd[i]); + + return; +} + +static void VScaleDiff_Serial(realtype c, N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = c*(xd[i]-yd[i]); + + return; +} + +static void VLin1_Serial(realtype a, N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = (a*xd[i])+yd[i]; + + return; +} + +static void VLin2_Serial(realtype a, N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = (a*xd[i])-yd[i]; + + return; +} + +static void Vaxpy_Serial(realtype a, N_Vector x, N_Vector y) +{ + long int i, N; + realtype *xd, *yd; + + xd = yd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + + if (a == ONE) { + for (i = 0; i < N; i++) + yd[i] += xd[i]; + return; + } + + if (a == -ONE) { + for (i = 0; i < N; i++) + yd[i] -= xd[i]; + return; + } + + for (i = 0; i < N; i++) + yd[i] += a*xd[i]; + + return; +} + +static void VScaleBy_Serial(realtype a, N_Vector x) +{ + long int i, N; + realtype *xd; + + xd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + + for (i = 0; i < N; i++) + xd[i] *= a; + + return; +} diff --git a/odemex/Parser/CVode/ida_src/src/sundials/CMakeLists.txt b/odemex/Parser/CVode/ida_src/src/sundials/CMakeLists.txt new file mode 100644 index 0000000..459dcdf --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/sundials/CMakeLists.txt @@ -0,0 +1,45 @@ +# --------------------------------------------------------------- +# $Revision: 1.4 $ +# $Date: 2009/02/17 02:52:53 $ +# --------------------------------------------------------------- +# Programmer: Radu Serban @ LLNL +# --------------------------------------------------------------- +# Copyright (c) 2007, The Regents of the University of California. +# Produced at the Lawrence Livermore National Laboratory. +# All rights reserved. +# For details, see the LICENSE file. +# --------------------------------------------------------------- +# CMakeLists.txt file for the generic SUNDIALS modules + +# From here we only install the generic SUNDIALS headers. +# The implementations themselves are incorporated in the individual SUNDIALS solver libraries. + +INSTALL(CODE "MESSAGE(\"\nInstall shared components\n\")") + +# Add variable sundials_HEADERS with the exported SUNDIALS header files +SET(sundials_HEADERS + sundials_band.h + sundials_dense.h + sundials_direct.h + sundials_iterative.h + sundials_math.h + sundials_nvector.h + sundials_fnvector.h + sundials_spbcgs.h + sundials_spgmr.h + sundials_sptfqmr.h + sundials_types.h + ) + +# Add prefix with complete path to the SUNDIALS header files +ADD_PREFIX(${sundials_SOURCE_DIR}/include/sundials/ sundials_HEADERS) + +# Install the SUNDIALS header files +INSTALL(FILES ${sundials_HEADERS} DESTINATION include/sundials) + +# If Blas/Lapack support was enabled, install the Lapack interface headers +IF(LAPACK_FOUND) + SET(sundials_BL_HEADERS sundials_lapack.h) + ADD_PREFIX(${sundials_SOURCE_DIR}/include/sundials/ sundials_BL_HEADERS) + INSTALL(FILES ${sundials_BL_HEADERS} DESTINATION include/sundials) +ENDIF(LAPACK_FOUND) diff --git a/odemex/Parser/CVode/ida_src/src/sundials/Makefile.in b/odemex/Parser/CVode/ida_src/src/sundials/Makefile.in new file mode 100644 index 0000000..f750ba1 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/sundials/Makefile.in @@ -0,0 +1,137 @@ +# ----------------------------------------------------------------- +# $Revision: 1.12 $ +# $Date: 2009/02/17 02:52:53 $ +# ----------------------------------------------------------------- +# Programmer(s): Radu Serban and Aaron Collier @ LLNL +# ----------------------------------------------------------------- +# Copyright (c) 2002, The Regents of the University of California. +# Produced at the Lawrence Livermore National Laboratory. +# All rights reserved. +# For details, see the LICENSE file. +# ----------------------------------------------------------------- +# Makefile for SHARED module +# +# @configure_input@ +# ----------------------------------------------------------------- + +SHELL = @SHELL@ + +srcdir = @srcdir@ +builddir = @builddir@ +abs_builddir = @abs_builddir@ +top_builddir = @top_builddir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +includedir = @includedir@ +libdir = @libdir@ +bindir = @bindir@ + +INSTALL = @INSTALL@ +INSTALL_PROG = @INSTALL_PROGRAM@ +INSTALL_HEADER = @INSTALL_DATA@ + +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ + +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CC = @CC@ +CFLAGS = @CFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ + +LAPACK_ENABLED = @LAPACK_ENABLED@ + +top_srcdir = $(srcdir)/../.. + +INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include + +SHARED_SRC_FILES = sundials_direct.c sundials_band.c sundials_dense.c sundials_iterative.c sundials_math.c sundials_nvector.c sundials_spgmr.c sundials_spbcgs.c sundials_sptfqmr.c + +SHARED_OBJ_FILES = $(SHARED_SRC_FILES:.c=.o) + +SHARED_LIB_FILES = $(SHARED_SRC_FILES:.c=.lo) + +mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs +rminstalldirs = $(SHELL) $(top_srcdir)/config/rminstalldirs + +# ---------------------------------------------------------------------------------------------------------------------- + + +all: + @if test "X${LAPACK_ENABLED}" = "Xyes"; then \ + make lib_with_bl; \ + else \ + make lib_without_bl; \ + fi + +lib_without_bl: $(SHARED_LIB_FILES) + +lib_with_bl: $(SHARED_LIB_FILES) + +install: + $(mkinstalldirs) $(includedir)/sundials + $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_direct.h $(includedir)/sundials/ + $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_band.h $(includedir)/sundials/ + $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_dense.h $(includedir)/sundials/ + $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_iterative.h $(includedir)/sundials/ + $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_spgmr.h $(includedir)/sundials/ + $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_spbcgs.h $(includedir)/sundials/ + $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_sptfqmr.h $(includedir)/sundials/ + $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_math.h $(includedir)/sundials/ + $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_types.h $(includedir)/sundials/ + $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_nvector.h $(includedir)/sundials/ + $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_fnvector.h $(includedir)/sundials/ + $(INSTALL_HEADER) $(top_builddir)/include/sundials/sundials_config.h $(includedir)/sundials/ + @if test "X${LAPACK_ENABLED}" = "Xyes"; then \ + $(INSTALL_HEADER) $(top_srcdir)/include/sundials/sundials_lapack.h $(includedir)/sundials/ ; \ + fi + +uninstall: + rm -f $(includedir)/sundials/sundials_direct.h + rm -f $(includedir)/sundials/sundials_band.h + rm -f $(includedir)/sundials/sundials_dense.h + rm -f $(includedir)/sundials/sundials_lapack.h + rm -f $(includedir)/sundials/sundials_iterative.h + rm -f $(includedir)/sundials/sundials_spgmr.h + rm -f $(includedir)/sundials/sundials_spbcgs.h + rm -f $(includedir)/sundials/sundials_sptfqmr.h + rm -f $(includedir)/sundials/sundials_math.h + rm -f $(includedir)/sundials/sundials_types.h + rm -f $(includedir)/sundials/sundials_nvector.h + rm -f $(includedir)/sundials/sundials_fnvector.h + rm -f $(includedir)/sundials/sundials_config.h + $(rminstalldirs) $(includedir)/sundials + +clean: + rm -f $(SHARED_LIB_FILES) + rm -f $(SHARED_OBJ_FILES) + rm -rf .libs + +distclean: clean + rm -f $(top_builddir)/include/sundials/sundials_config.h + rm -f Makefile + +sundials_direct.lo: $(srcdir)/sundials_direct.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/sundials_direct.c +sundials_band.lo: $(srcdir)/sundials_band.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/sundials_band.c +sundials_dense.lo: $(srcdir)/sundials_dense.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/sundials_dense.c +sundials_iterative.lo: $(srcdir)/sundials_iterative.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/sundials_iterative.c +sundials_spgmr.lo: $(srcdir)/sundials_spgmr.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/sundials_spgmr.c +sundials_spbcgs.lo: $(srcdir)/sundials_spbcgs.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/sundials_spbcgs.c +sundials_sptfqmr.lo: $(srcdir)/sundials_sptfqmr.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/sundials_sptfqmr.c +sundials_math.lo: $(srcdir)/sundials_math.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/sundials_math.c +sundials_nvector.lo: $(srcdir)/sundials_nvector.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/sundials_nvector.c + +libtool: $(top_builddir)/$(LIBTOOL_DEPS) + @cd ${top_builddir} ; \ + ${SHELL} ./config.status --recheck ; \ + cd ${abs_builddir} diff --git a/odemex/Parser/CVode/ida_src/src/sundials/README b/odemex/Parser/CVode/ida_src/src/sundials/README new file mode 100644 index 0000000..d73e577 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/sundials/README @@ -0,0 +1,201 @@ + SUNDIALS + Shared Module + Release 2.4.0, January 2008 + + +The family of solvers referred to as SUNDIALS consists of solvers +CVODE (ODE), CVODES (ODE with sensitivity analysis capabilities), +IDA (DAE), IDAS (DAE with sensitivity analysis capabilities), and +KINSOL (for nonlinear algebraic systems). + +The various solvers of this family share many subordinate modules contained +in this module: +- generic NVECTOR module +- generic linear solver modules (band, dense, lapack, spgmr, bcg, tfqmr) +- definitions of SUNDIALS types (realtype, booleantype) +- common math functions (RpowerI, RPowerR, RSqrt, RAbs,...) + + +A. Documentation +---------------- +All shared submodules are fully described in the user documentation for any of +the SUNDIALS solvers [1-5]. A PDF file for the user guide for a particular solver +is available in the solver's subdirectory under doc/. + + +B. Installation +--------------- + +For basic installation instructions see the file /sundials/INSTALL_NOTES. +For complete installation instructions see any of the user guides. + + +C. References +------------- + +[1] A. C. Hindmarsh and R. Serban, "User Documentation for CVODE v2.4.0," + LLLNL technical report UCRL-MA-208108, November 2004. + +[2] A. C. Hindmarsh and R. Serban, "User Documentation for CVODES v2.4.0," + LLNL technical report UCRL-MA-208111, November 2004. + +[3] A. C. Hindmarsh and R. Serban, "User Documentation for IDA v2.4.0," + LLNL technical report UCRL-MA-208112, November 2004. + +[4] R. Serban and C. Petra, "User Documentation for IDAS v1.0.0," + LLNL technical report UCRL-SM-234051, August 2007. + +[5] A. M. Collier, A. C. Hindmarsh, R. Serban,and C. S. Woodward, "User + Documentation for KINSOL v2.4.0," LLNL technical report UCRL-MA-208116, + November 2004. + + +D. Releases +----------- + +v. 2.4.0 - Jan. 2008 +v. 2.3.0 - Nov. 2006 +v. 2.2.0 - Mar. 2006 +v. 2.1.1 - May. 2005 +v. 2.1.0 - Apr. 2005 +v. 2.0.2 - Mar. 2005 +v. 2.0.1 - Jan. 2005 +v. 2.0 - Dec. 2004 +v. 1.0 - Jul. 2002 (first SUNDIALS release) +v. 0.0 - Mar. 2002 + + +E. Revision History +------------------- + +v. 2.3.0 (Nov. 2006) ---> v. 2.4.0 (Jan. 2008) +--------------------------------------------------------- + +- New features + - added a new generic linear solver module based on Blas + Lapack + for both dense and banded matrices. + +- Changes to user interface + - common functionality for all direct linear solvers (dense, band, and + the new Lapack solver) has been collected into the DLS (Direct Linear + Solver) module, implemented in the files sundials_direct.h and + sundials_direct.c (similar to the SPILS module for the iterative linear + solvers). + - in order to include the new Lapack-based linear solver, all dimensions + for the above linear solvers (problem sizes, bandwidths,... including + the underlying matrix data types) are now of type 'int' (and not 'long int'). + + +v. 2.2.0 (Mar. 2006) ---> v. 2.3.0 (Nov. 2006) +---------------------------------------------- + +- Changes to the user interface + - modified sundials_dense and sundials_smalldense to work with + rectangular m by n matrices (m <= n). + +- Changes related to the build system + - reorganized source tree + - exported header files are installed in solver-specific subdirectories + of ${includedir} + - sundialsTB is distributed only as part of the SUNDIALS tarball + +v. 2.1.1 (May 2005) ---> v. 2.2.0 (Mar. 2006) +---------------------------------------------- + +- New features + - added SPBCG (scaled preconditioned Bi-CGStab) linear solver module + - added SPTFQMR (scaled preconditioned TFQMR) linear solver module + +- Changes related to the build system + - updated configure script and Makefiles for Fortran examples to avoid C++ + compiler errors (now use CC and MPICC to link only if necessary) + - SUNDIALS shared header files are installed under a 'sundials' subdirectory + of the install include directory + - the shared object files are now linked into each SUNDIALS library rather + than into a separate libsundials_shared library + +- Changes to the user interface + - added prefix 'sundials_' to all shared header files + +v. 2.1.0 (Apr. 2005) ---> v. 2.1.1 (May.2005) +---------------------------------------------- + +- Changes to data structures + - added N_VCloneEmpty to global vector operations table + +v. 2.0.2 (Mar. 2005) ---> v. 2.1.0 (Apr. 2005) +---------------------------------------------- + +- none + +v. 2.0.1 (Jan. 2005) ---> v. 2.0.2 (Mar. 2005) +---------------------------------------------- + +- Changes related to the build system + - fixed autoconf-related bug to allow configuration with the PGI Fortran compiler + - modified to use customized detection of the Fortran name mangling scheme + (autoconf's AC_F77_WRAPPERS routine is problematic on some platforms) + - added --with-mpi-flags as a configure option to allow user to specify + MPI-specific flags + - updated Makefiles for Fortran examples to avoid C++ compiler errors (now use + CC and MPICC to link) + +v. 2.0 (Dec. 2004) ---> v. 2.0.1 (Jan. 2005) +-------------------------------------------- + +- Changes related to the build system + - changed order of compiler directives in header files to avoid compilation + errors when using a C++ compiler. + +v. 1.0 (Jul. 2002) ---> v. 2.0 (Dec. 2004) +------------------------------------------ + +- Changes to the generic NVECTOR module + - removed machEnv, redefined table of vector operations (now contained + in the N_Vector structure itself). + - all SUNDIALS functions create new N_Vector variables through cloning, using + an N_Vector passed by the user as a template. + - a particular NVECTOR implementation is supposed to provide user-callable + constructor and destructor functions. + - removed from structure of vector operations the following functions: + N_VNew, N_VNew_S, N_VFree, N_VFree_S, N_VMake, N_VDispose, N_VGetData, + N_VSetData, N_VConstrProdPos, and N_VOneMask. + - added in structure of vector operations the following functions: + N_VClone, N_VDestroy, N_VSpace, N_VGetArrayPointer, N_VSetArrayPointer, + and N_VWrmsNormMask. + - Note that nvec_ser and nvec_par are now separate modules outside the + shared SUNDIALS module. + +- Changes to the generic linear solvers + - in SPGMR, added a dummy N_Vector argument to be used as a template + for cloning. + - in SPGMR, removed N (problem dimension) from argument list of SpgmrMalloc. + - iterative.{c,h} replace iterativ.{c,h} + - modified constant names in iterative.h (preconditioner types are prefixed + with 'PREC_'). + - changed numerical values for MODIFIED_GS (from 0 to 1) and CLASSICAL_GS + (from 1 to 2). + +- Changes to sundialsmath submodule + - replaced internal routine for estimation of unit roundoff with definition + of unit roundoff from float.h + - modified functions to call appropriate math routines given the precision + level specified by the user. + +- Changes to sundialstypes submodule + - removed type 'integertype'. + - added definitions for 'BIG_REAL', 'SMALL_REAL', and 'UNIT_ROUNDOFF' using + values from float.h based on the precision. + - changed definition of macro RCONST to depend on precision. + +v 0.0 (Mar. 2002) ---> v. 1.0 (Jul. 2002) +----------------------------------------- + +20020321 Defined and implemented generic NVECTOR module, and separate serial/ + parallel NVECTOR modules, including serial/parallel F/C interfaces. + Modified dense and band backsolve routines to take real* type for + RHS and solution vector. +20020329 Named the DenseMat, BandMat, and SpgmrMemRec structures. +20020626 Changed type names to realtype, integertype, booleantype. + Renamed llnltypes and llnlmath files. + diff --git a/odemex/Parser/CVode/ida_src/src/sundials/sundials_band.c b/odemex/Parser/CVode/ida_src/src/sundials/sundials_band.c new file mode 100644 index 0000000..fa4eea7 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/sundials/sundials_band.c @@ -0,0 +1,235 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2009/02/17 02:42:29 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for a generic BAND linear + * solver package. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +#define ROW(i,j,smu) (i-j+smu) + +/* + * ----------------------------------------------------- + * Functions working on DlsMat + * ----------------------------------------------------- + */ + +int BandGBTRF(DlsMat A, int *p) +{ + return(bandGBTRF(A->cols, A->M, A->mu, A->ml, A->s_mu, p)); +} + +void BandGBTRS(DlsMat A, int *p, realtype *b) +{ + bandGBTRS(A->cols, A->M, A->s_mu, A->ml, p, b); +} + +void BandCopy(DlsMat A, DlsMat B, int copymu, int copyml) +{ + bandCopy(A->cols, B->cols, A->M, A->s_mu, B->s_mu, copymu, copyml); +} + +void BandScale(realtype c, DlsMat A) +{ + bandScale(c, A->cols, A->M, A->mu, A->ml, A->s_mu); +} + +/* + * ----------------------------------------------------- + * Functions working on realtype** + * ----------------------------------------------------- + */ + +int bandGBTRF(realtype **a, int n, int mu, int ml, int smu, int *p) +{ + int c, r, num_rows; + int i, j, k, l, storage_l, storage_k, last_col_k, last_row_k; + realtype *a_c, *col_k, *diag_k, *sub_diag_k, *col_j, *kptr, *jptr; + realtype max, temp, mult, a_kj; + booleantype swap; + + /* zero out the first smu - mu rows of the rectangular array a */ + + num_rows = smu - mu; + if (num_rows > 0) { + for (c=0; c < n; c++) { + a_c = a[c]; + for (r=0; r < num_rows; r++) { + a_c[r] = ZERO; + } + } + } + + /* k = elimination step number */ + + for (k=0; k < n-1; k++, p++) { + + col_k = a[k]; + diag_k = col_k + smu; + sub_diag_k = diag_k + 1; + last_row_k = MIN(n-1,k+ml); + + /* find l = pivot row number */ + + l=k; + max = ABS(*diag_k); + for (i=k+1, kptr=sub_diag_k; i <= last_row_k; i++, kptr++) { + if (ABS(*kptr) > max) { + l=i; + max = ABS(*kptr); + } + } + storage_l = ROW(l, k, smu); + *p = l; + + /* check for zero pivot element */ + + if (col_k[storage_l] == ZERO) return(k+1); + + /* swap a(l,k) and a(k,k) if necessary */ + + if ( (swap = (l != k) )) { + temp = col_k[storage_l]; + col_k[storage_l] = *diag_k; + *diag_k = temp; + } + + /* Scale the elements below the diagonal in */ + /* column k by -1.0 / a(k,k). After the above swap, */ + /* a(k,k) holds the pivot element. This scaling */ + /* stores the pivot row multipliers -a(i,k)/a(k,k) */ + /* in a(i,k), i=k+1, ..., MIN(n-1,k+ml). */ + + mult = -ONE / (*diag_k); + for (i=k+1, kptr = sub_diag_k; i <= last_row_k; i++, kptr++) + (*kptr) *= mult; + + /* row_i = row_i - [a(i,k)/a(k,k)] row_k, i=k+1, ..., MIN(n-1,k+ml) */ + /* row k is the pivot row after swapping with row l. */ + /* The computation is done one column at a time, */ + /* column j=k+1, ..., MIN(k+smu,n-1). */ + + last_col_k = MIN(k+smu,n-1); + for (j=k+1; j <= last_col_k; j++) { + + col_j = a[j]; + storage_l = ROW(l,j,smu); + storage_k = ROW(k,j,smu); + a_kj = col_j[storage_l]; + + /* Swap the elements a(k,j) and a(k,l) if l!=k. */ + + if (swap) { + col_j[storage_l] = col_j[storage_k]; + col_j[storage_k] = a_kj; + } + + /* a(i,j) = a(i,j) - [a(i,k)/a(k,k)]*a(k,j) */ + /* a_kj = a(k,j), *kptr = - a(i,k)/a(k,k), *jptr = a(i,j) */ + + if (a_kj != ZERO) { + for (i=k+1, kptr=sub_diag_k, jptr=col_j+ROW(k+1,j,smu); + i <= last_row_k; + i++, kptr++, jptr++) + (*jptr) += a_kj * (*kptr); + } + } + } + + /* set the last pivot row to be n-1 and check for a zero pivot */ + + *p = n-1; + if (a[n-1][smu] == ZERO) return(n); + + /* return 0 to indicate success */ + + return(0); +} + +void bandGBTRS(realtype **a, int n, int smu, int ml, int *p, realtype *b) +{ + int k, l, i, first_row_k, last_row_k; + realtype mult, *diag_k; + + /* Solve Ly = Pb, store solution y in b */ + + for (k=0; k < n-1; k++) { + l = p[k]; + mult = b[l]; + if (l != k) { + b[l] = b[k]; + b[k] = mult; + } + diag_k = a[k]+smu; + last_row_k = MIN(n-1,k+ml); + for (i=k+1; i <= last_row_k; i++) + b[i] += mult * diag_k[i-k]; + } + + /* Solve Ux = y, store solution x in b */ + + for (k=n-1; k >= 0; k--) { + diag_k = a[k]+smu; + first_row_k = MAX(0,k-smu); + b[k] /= (*diag_k); + mult = -b[k]; + for (i=first_row_k; i <= k-1; i++) + b[i] += mult*diag_k[i-k]; + } +} + +void bandCopy(realtype **a, realtype **b, int n, int a_smu, int b_smu, + int copymu, int copyml) +{ + int i, j, copySize; + realtype *a_col_j, *b_col_j; + + copySize = copymu + copyml + 1; + + for (j=0; j < n; j++) { + a_col_j = a[j]+a_smu-copymu; + b_col_j = b[j]+b_smu-copymu; + for (i=0; i < copySize; i++) + b_col_j[i] = a_col_j[i]; + } +} + +void bandScale(realtype c, realtype **a, int n, int mu, int ml, int smu) +{ + int i, j, colSize; + realtype *col_j; + + colSize = mu + ml + 1; + + for(j=0; j < n; j++) { + col_j = a[j]+smu-mu; + for (i=0; i < colSize; i++) + col_j[i] *= c; + } +} + +void bandAddIdentity(realtype **a, int n, int smu) +{ + int j; + + for(j=0; j < n; j++) + a[j][smu] += ONE; +} diff --git a/odemex/Parser/CVode/ida_src/src/sundials/sundials_dense.c b/odemex/Parser/CVode/ida_src/src/sundials/sundials_dense.c new file mode 100644 index 0000000..104e070 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/sundials/sundials_dense.c @@ -0,0 +1,373 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2009/02/17 02:42:29 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for a generic package of dense + * matrix operations. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) +#define TWO RCONST(2.0) + +/* + * ----------------------------------------------------- + * Functions working on DlsMat + * ----------------------------------------------------- + */ + +int DenseGETRF(DlsMat A, int *p) +{ + return(denseGETRF(A->cols, A->M, A->N, p)); +} + +void DenseGETRS(DlsMat A, int *p, realtype *b) +{ + denseGETRS(A->cols, A->N, p, b); +} + +int DensePOTRF(DlsMat A) +{ + return(densePOTRF(A->cols, A->M)); +} + +void DensePOTRS(DlsMat A, realtype *b) +{ + densePOTRS(A->cols, A->M, b); +} + +int DenseGEQRF(DlsMat A, realtype *beta, realtype *wrk) +{ + return(denseGEQRF(A->cols, A->M, A->N, beta, wrk)); +} + +int DenseORMQR(DlsMat A, realtype *beta, realtype *vn, realtype *vm, realtype *wrk) +{ + return(denseORMQR(A->cols, A->M, A->N, beta, vn, vm, wrk)); +} + +void DenseCopy(DlsMat A, DlsMat B) +{ + denseCopy(A->cols, B->cols, A->M, A->N); +} + +void DenseScale(realtype c, DlsMat A) +{ + denseScale(c, A->cols, A->M, A->N); +} + +int denseGETRF(realtype **a, int m, int n, int *p) +{ + int i, j, k, l; + realtype *col_j, *col_k; + realtype temp, mult, a_kj; + + /* k-th elimination step number */ + for (k=0; k < n; k++) { + + col_k = a[k]; + + /* find l = pivot row number */ + l=k; + for (i=k+1; i < m; i++) + if (ABS(col_k[i]) > ABS(col_k[l])) l=i; + p[k] = l; + + /* check for zero pivot element */ + if (col_k[l] == ZERO) return(k+1); + + /* swap a(k,1:n) and a(l,1:n) if necessary */ + if ( l!= k ) { + for (i=0; i 0; k--) { + col_k = a[k]; + b[k] /= col_k[k]; + for (i=0; i0) { + for(i=j; i=0; i--) { + col_i = a[i]; + for (j=i+1; j= n) + * using Householder reflections. + * + * On exit, the elements on and above the diagonal of A contain the n by n + * upper triangular matrix R; the elements below the diagonal, with the array beta, + * represent the orthogonal matrix Q as a product of elementary reflectors . + * + * v (of length m) must be provided as workspace. + * + */ + +int denseGEQRF(realtype **a, int m, int n, realtype *beta, realtype *v) +{ + realtype ajj, s, mu, v1, v1_2; + realtype *col_j, *col_k; + int i, j, k; + + /* For each column...*/ + for(j=0; j= n. + * + * v (of length m) must be provided as workspace. + */ +int denseORMQR(realtype **a, int m, int n, realtype *beta, + realtype *vn, realtype *vm, realtype *v) +{ + realtype *col_j, s; + int i, j; + + /* Initialize vm */ + for(i=0; i=0; j--) { + + col_j = a[j]; + + v[0] = ONE; + s = vm[j]; + for(i=1; i +#include + +#include +#include + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +DlsMat NewDenseMat(int M, int N) +{ + DlsMat A; + int j; + + if ( (M <= 0) || (N <= 0) ) return(NULL); + + A = NULL; + A = (DlsMat) malloc(sizeof *A); + if (A==NULL) return (NULL); + + A->data = (realtype *) malloc(M * N * sizeof(realtype)); + if (A->data == NULL) { + free(A); A = NULL; + return(NULL); + } + A->cols = (realtype **) malloc(N * sizeof(realtype *)); + if (A->cols == NULL) { + free(A->data); A->data = NULL; + free(A); A = NULL; + return(NULL); + } + + for (j=0; j < N; j++) A->cols[j] = A->data + j * M; + + A->M = M; + A->N = N; + A->ldim = M; + A->ldata = M*N; + + A->type = SUNDIALS_DENSE; + + return(A); +} + +realtype **newDenseMat(int m, int n) +{ + int j; + realtype **a; + + if ( (n <= 0) || (m <= 0) ) return(NULL); + + a = NULL; + a = (realtype **) malloc(n * sizeof(realtype *)); + if (a == NULL) return(NULL); + + a[0] = NULL; + a[0] = (realtype *) malloc(m * n * sizeof(realtype)); + if (a[0] == NULL) { + free(a); a = NULL; + return(NULL); + } + + for (j=1; j < n; j++) a[j] = a[0] + j * m; + + return(a); +} + + +DlsMat NewBandMat(int N, int mu, int ml, int smu) +{ + DlsMat A; + int j, colSize; + + if (N <= 0) return(NULL); + + A = NULL; + A = (DlsMat) malloc(sizeof *A); + if (A == NULL) return (NULL); + + colSize = smu + ml + 1; + A->data = NULL; + A->data = (realtype *) malloc(N * colSize * sizeof(realtype)); + if (A->data == NULL) { + free(A); A = NULL; + return(NULL); + } + + A->cols = NULL; + A->cols = (realtype **) malloc(N * sizeof(realtype *)); + if (A->cols == NULL) { + free(A->data); + free(A); A = NULL; + return(NULL); + } + + for (j=0; j < N; j++) A->cols[j] = A->data + j * colSize; + + A->M = N; + A->N = N; + A->mu = mu; + A->ml = ml; + A->s_mu = smu; + A->ldim = colSize; + A->ldata = N * colSize; + + A->type = SUNDIALS_BAND; + + return(A); +} + +realtype **newBandMat(int n, int smu, int ml) +{ + realtype **a; + int j, colSize; + + if (n <= 0) return(NULL); + + a = NULL; + a = (realtype **) malloc(n * sizeof(realtype *)); + if (a == NULL) return(NULL); + + colSize = smu + ml + 1; + a[0] = NULL; + a[0] = (realtype *) malloc(n * colSize * sizeof(realtype)); + if (a[0] == NULL) { + free(a); a = NULL; + return(NULL); + } + + for (j=1; j < n; j++) a[j] = a[0] + j * colSize; + + return(a); +} + +void DestroyMat(DlsMat A) +{ + free(A->data); A->data = NULL; + free(A->cols); + free(A); A = NULL; +} + +void destroyMat(realtype **a) +{ + free(a[0]); a[0] = NULL; + free(a); a = NULL; +} + +int *NewIntArray(int N) +{ + int *vec; + + if (N <= 0) return(NULL); + + vec = NULL; + vec = (int *) malloc(N * sizeof(int)); + + return(vec); +} + +int *newIntArray(int n) +{ + int *v; + + if (n <= 0) return(NULL); + + v = NULL; + v = (int *) malloc(n * sizeof(int)); + + return(v); +} + +realtype *NewRealArray(int N) +{ + realtype *vec; + + if (N <= 0) return(NULL); + + vec = NULL; + vec = (realtype *) malloc(N * sizeof(realtype)); + + return(vec); +} + +realtype *newRealArray(int m) +{ + realtype *v; + + if (m <= 0) return(NULL); + + v = NULL; + v = (realtype *) malloc(m * sizeof(realtype)); + + return(v); +} + +void DestroyArray(void *V) +{ + free(V); + V = NULL; +} + +void destroyArray(void *v) +{ + free(v); + v = NULL; +} + + +void AddIdentity(DlsMat A) +{ + int i; + + switch (A->type) { + + case SUNDIALS_DENSE: + for (i=0; iN; i++) A->cols[i][i] += ONE; + break; + + case SUNDIALS_BAND: + for (i=0; iM; i++) A->cols[i][A->s_mu] += ONE; + break; + + } + +} + + +void SetToZero(DlsMat A) +{ + int i, j, colSize; + realtype *col_j; + + switch (A->type) { + + case SUNDIALS_DENSE: + + for (j=0; jN; j++) { + col_j = A->cols[j]; + for (i=0; iM; i++) + col_j[i] = ZERO; + } + + break; + + case SUNDIALS_BAND: + + colSize = A->mu + A->ml + 1; + for (j=0; jM; j++) { + col_j = A->cols[j] + A->s_mu - A->mu; + for (i=0; itype) { + + case SUNDIALS_DENSE: + + printf("\n"); + for (i=0; i < A->M; i++) { + for (j=0; j < A->N; j++) { +#if defined(SUNDIALS_EXTENDED_PRECISION) + printf("%12Lg ", DENSE_ELEM(A,i,j)); +#elif defined(SUNDIALS_DOUBLE_PRECISION) + printf("%12lg ", DENSE_ELEM(A,i,j)); +#else + printf("%12g ", DENSE_ELEM(A,i,j)); +#endif + } + printf("\n"); + } + printf("\n"); + + break; + + case SUNDIALS_BAND: + + a = A->cols; + printf("\n"); + for (i=0; i < A->N; i++) { + start = MAX(0,i-A->ml); + finish = MIN(A->N-1,i+A->mu); + for (j=0; j < start; j++) printf("%12s ",""); + for (j=start; j <= finish; j++) { +#if defined(SUNDIALS_EXTENDED_PRECISION) + printf("%12Lg ", a[j][i-j+A->s_mu]); +#elif defined(SUNDIALS_DOUBLE_PRECISION) + printf("%12lg ", a[j][i-j+A->s_mu]); +#else + printf("%12g ", a[j][i-j+A->s_mu]); +#endif + } + printf("\n"); + } + printf("\n"); + + break; + + } + +} + + diff --git a/odemex/Parser/CVode/ida_src/src/sundials/sundials_iterative.c b/odemex/Parser/CVode/ida_src/src/sundials/sundials_iterative.c new file mode 100644 index 0000000..41ccc17 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/sundials/sundials_iterative.c @@ -0,0 +1,288 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.1 $ + * $Date: 2006/07/05 15:32:38 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the iterative.h header + * file. It contains the implementation of functions that may be + * useful for many different iterative solvers of A x = b. + * ----------------------------------------------------------------- + */ + +#include + +#include +#include + +#define FACTOR RCONST(1000.0) +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +/* + * ----------------------------------------------------------------- + * Function : ModifiedGS + * ----------------------------------------------------------------- + * This implementation of ModifiedGS is a slight modification of a + * previous modified Gram-Schmidt routine (called mgs) written by + * Milo Dorr. + * ----------------------------------------------------------------- + */ + +int ModifiedGS(N_Vector *v, realtype **h, int k, int p, + realtype *new_vk_norm) +{ + int i, k_minus_1, i0; + realtype new_norm_2, new_product, vk_norm, temp; + + vk_norm = RSqrt(N_VDotProd(v[k],v[k])); + k_minus_1 = k - 1; + i0 = MAX(k-p, 0); + + /* Perform modified Gram-Schmidt */ + + for (i=i0; i < k; i++) { + h[i][k_minus_1] = N_VDotProd(v[i], v[k]); + N_VLinearSum(ONE, v[k], -h[i][k_minus_1], v[i], v[k]); + } + + /* Compute the norm of the new vector at v[k] */ + + *new_vk_norm = RSqrt(N_VDotProd(v[k], v[k])); + + /* If the norm of the new vector at v[k] is less than + FACTOR (== 1000) times unit roundoff times the norm of the + input vector v[k], then the vector will be reorthogonalized + in order to ensure that nonorthogonality is not being masked + by a very small vector length. */ + + temp = FACTOR * vk_norm; + if ((temp + (*new_vk_norm)) != temp) return(0); + + new_norm_2 = ZERO; + + for (i=i0; i < k; i++) { + new_product = N_VDotProd(v[i], v[k]); + temp = FACTOR * h[i][k_minus_1]; + if ((temp + new_product) == temp) continue; + h[i][k_minus_1] += new_product; + N_VLinearSum(ONE, v[k],-new_product, v[i], v[k]); + new_norm_2 += SQR(new_product); + } + + if (new_norm_2 != ZERO) { + new_product = SQR(*new_vk_norm) - new_norm_2; + *new_vk_norm = (new_product > ZERO) ? RSqrt(new_product) : ZERO; + } + + return(0); +} + +/* + * ----------------------------------------------------------------- + * Function : ClassicalGS + * ----------------------------------------------------------------- + * This implementation of ClassicalGS was contributed by Homer Walker + * and Peter Brown. + * ----------------------------------------------------------------- + */ + +int ClassicalGS(N_Vector *v, realtype **h, int k, int p, + realtype *new_vk_norm, N_Vector temp, realtype *s) +{ + int i, k_minus_1, i0; + realtype vk_norm; + + k_minus_1 = k - 1; + + /* Perform Classical Gram-Schmidt */ + + vk_norm = RSqrt(N_VDotProd(v[k], v[k])); + + i0 = MAX(k-p, 0); + for (i=i0; i < k; i++) { + h[i][k_minus_1] = N_VDotProd(v[i], v[k]); + } + + for (i=i0; i < k; i++) { + N_VLinearSum(ONE, v[k], -h[i][k_minus_1], v[i], v[k]); + } + + /* Compute the norm of the new vector at v[k] */ + + *new_vk_norm = RSqrt(N_VDotProd(v[k], v[k])); + + /* Reorthogonalize if necessary */ + + if ((FACTOR * (*new_vk_norm)) < vk_norm) { + + for (i=i0; i < k; i++) { + s[i] = N_VDotProd(v[i], v[k]); + } + + if (i0 < k) { + N_VScale(s[i0], v[i0], temp); + h[i0][k_minus_1] += s[i0]; + } + for (i=i0+1; i < k; i++) { + N_VLinearSum(s[i], v[i], ONE, temp, temp); + h[i][k_minus_1] += s[i]; + } + N_VLinearSum(ONE, v[k], -ONE, temp, v[k]); + + *new_vk_norm = RSqrt(N_VDotProd(v[k],v[k])); + } + + return(0); +} + +/* + * ----------------------------------------------------------------- + * Function : QRfact + * ----------------------------------------------------------------- + * This implementation of QRfact is a slight modification of a + * previous routine (called qrfact) written by Milo Dorr. + * ----------------------------------------------------------------- + */ + +int QRfact(int n, realtype **h, realtype *q, int job) +{ + realtype c, s, temp1, temp2, temp3; + int i, j, k, q_ptr, n_minus_1, code=0; + + switch (job) { + case 0: + + /* Compute a new factorization of H */ + + code = 0; + for (k=0; k < n; k++) { + + /* Multiply column k by the previous k-1 Givens rotations */ + + for (j=0; j < k-1; j++) { + i = 2*j; + temp1 = h[j][k]; + temp2 = h[j+1][k]; + c = q[i]; + s = q[i+1]; + h[j][k] = c*temp1 - s*temp2; + h[j+1][k] = s*temp1 + c*temp2; + } + + /* Compute the Givens rotation components c and s */ + + q_ptr = 2*k; + temp1 = h[k][k]; + temp2 = h[k+1][k]; + if( temp2 == ZERO) { + c = ONE; + s = ZERO; + } else if (ABS(temp2) >= ABS(temp1)) { + temp3 = temp1/temp2; + s = -ONE/RSqrt(ONE+SQR(temp3)); + c = -s*temp3; + } else { + temp3 = temp2/temp1; + c = ONE/RSqrt(ONE+SQR(temp3)); + s = -c*temp3; + } + q[q_ptr] = c; + q[q_ptr+1] = s; + if( (h[k][k] = c*temp1 - s*temp2) == ZERO) code = k+1; + } + break; + + default: + + /* Update the factored H to which a new column has been added */ + + n_minus_1 = n - 1; + code = 0; + + /* Multiply the new column by the previous n-1 Givens rotations */ + + for (k=0; k < n_minus_1; k++) { + i = 2*k; + temp1 = h[k][n_minus_1]; + temp2 = h[k+1][n_minus_1]; + c = q[i]; + s = q[i+1]; + h[k][n_minus_1] = c*temp1 - s*temp2; + h[k+1][n_minus_1] = s*temp1 + c*temp2; + } + + /* Compute new Givens rotation and multiply it times the last two + entries in the new column of H. Note that the second entry of + this product will be 0, so it is not necessary to compute it. */ + + temp1 = h[n_minus_1][n_minus_1]; + temp2 = h[n][n_minus_1]; + if (temp2 == ZERO) { + c = ONE; + s = ZERO; + } else if (ABS(temp2) >= ABS(temp1)) { + temp3 = temp1/temp2; + s = -ONE/RSqrt(ONE+SQR(temp3)); + c = -s*temp3; + } else { + temp3 = temp2/temp1; + c = ONE/RSqrt(ONE+SQR(temp3)); + s = -c*temp3; + } + q_ptr = 2*n_minus_1; + q[q_ptr] = c; + q[q_ptr+1] = s; + if ((h[n_minus_1][n_minus_1] = c*temp1 - s*temp2) == ZERO) + code = n; + } + + return (code); +} + +/* + * ----------------------------------------------------------------- + * Function : QRsol + * ----------------------------------------------------------------- + * This implementation of QRsol is a slight modification of a + * previous routine (called qrsol) written by Milo Dorr. + * ----------------------------------------------------------------- + */ + +int QRsol(int n, realtype **h, realtype *q, realtype *b) +{ + realtype c, s, temp1, temp2; + int i, k, q_ptr, code=0; + + /* Compute Q*b */ + + for (k=0; k < n; k++) { + q_ptr = 2*k; + c = q[q_ptr]; + s = q[q_ptr+1]; + temp1 = b[k]; + temp2 = b[k+1]; + b[k] = c*temp1 - s*temp2; + b[k+1] = s*temp1 + c*temp2; + } + + /* Solve R*x = Q*b */ + + for (k=n-1; k >= 0; k--) { + if (h[k][k] == ZERO) { + code = k + 1; + break; + } + b[k] /= h[k][k]; + for (i=0; i < k; i++) b[i] -= b[k]*h[i][k]; + } + + return (code); +} diff --git a/odemex/Parser/CVode/ida_src/src/sundials/sundials_math.c b/odemex/Parser/CVode/ida_src/src/sundials/sundials_math.c new file mode 100644 index 0000000..8bc9d59 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/sundials/sundials_math.c @@ -0,0 +1,94 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.1 $ + * $Date: 2006/07/05 15:32:38 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for a simple C-language math + * library. + * ----------------------------------------------------------------- + */ + +#include +#include +#include + +#include + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +realtype RPowerI(realtype base, int exponent) +{ + int i, expt; + realtype prod; + + prod = ONE; + expt = abs(exponent); + for(i = 1; i <= expt; i++) prod *= base; + if (exponent < 0) prod = ONE/prod; + return(prod); +} + +realtype RPowerR(realtype base, realtype exponent) +{ + if (base <= ZERO) return(ZERO); + +#if defined(SUNDIALS_USE_GENERIC_MATH) + return((realtype) pow((double) base, (double) exponent)); +#elif defined(SUNDIALS_DOUBLE_PRECISION) + return(pow(base, exponent)); +#elif defined(SUNDIALS_SINGLE_PRECISION) + return(powf(base, exponent)); +#elif defined(SUNDIALS_EXTENDED_PRECISION) + return(powl(base, exponent)); +#endif +} + +realtype RSqrt(realtype x) +{ + if (x <= ZERO) return(ZERO); + +#if defined(SUNDIALS_USE_GENERIC_MATH) + return((realtype) sqrt((double) x)); +#elif defined(SUNDIALS_DOUBLE_PRECISION) + return(sqrt(x)); +#elif defined(SUNDIALS_SINGLE_PRECISION) + return(sqrtf(x)); +#elif defined(SUNDIALS_EXTENDED_PRECISION) + return(sqrtl(x)); +#endif +} + +realtype RAbs(realtype x) +{ +#if defined(SUNDIALS_USE_GENERIC_MATH) + return((realtype) fabs((double) x)); +#elif defined(SUNDIALS_DOUBLE_PRECISION) + return(fabs(x)); +#elif defined(SUNDIALS_SINGLE_PRECISION) + return(fabsf(x)); +#elif defined(SUNDIALS_EXTENDED_PRECISION) + return(fabsl(x)); +#endif +} + +realtype RExp(realtype x) +{ +#if defined(SUNDIALS_USE_GENERIC_MATH) + return((realtype) exp((double) x)); +#elif defined(SUNDIALS_DOUBLE_PRECISION) + return(exp(x)); +#elif defined(SUNDIALS_SINGLE_PRECISION) + return(expf(x)); +#elif defined(SUNDIALS_EXTENDED_PRECISION) + return(expl(x)); +#endif +} diff --git a/odemex/Parser/CVode/ida_src/src/sundials/sundials_nvector.c b/odemex/Parser/CVode/ida_src/src/sundials/sundials_nvector.c new file mode 100644 index 0000000..e8e1b83 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/sundials/sundials_nvector.c @@ -0,0 +1,233 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.3 $ + * $Date: 2007/04/06 20:33:30 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for a generic NVECTOR package. + * It contains the implementation of the N_Vector operations listed + * in nvector.h. + * ----------------------------------------------------------------- + */ + +#include + +#include + +/* + * ----------------------------------------------------------------- + * Functions in the 'ops' structure + * ----------------------------------------------------------------- + */ + +N_Vector N_VClone(N_Vector w) +{ + N_Vector v = NULL; + v = w->ops->nvclone(w); + return(v); +} + +N_Vector N_VCloneEmpty(N_Vector w) +{ + N_Vector v = NULL; + v = w->ops->nvcloneempty(w); + return(v); +} + +void N_VDestroy(N_Vector v) +{ + if (v==NULL) return; + v->ops->nvdestroy(v); + return; +} + +void N_VSpace(N_Vector v, long int *lrw, long int *liw) +{ + v->ops->nvspace(v, lrw, liw); + return; +} + +realtype *N_VGetArrayPointer(N_Vector v) +{ + return((realtype *) v->ops->nvgetarraypointer(v)); +} + +void N_VSetArrayPointer(realtype *v_data, N_Vector v) +{ + v->ops->nvsetarraypointer(v_data, v); + return; +} + +void N_VLinearSum(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z) +{ + z->ops->nvlinearsum(a, x, b, y, z); + return; +} + +void N_VConst(realtype c, N_Vector z) +{ + z->ops->nvconst(c, z); + return; +} + +void N_VProd(N_Vector x, N_Vector y, N_Vector z) +{ + z->ops->nvprod(x, y, z); + return; +} + +void N_VDiv(N_Vector x, N_Vector y, N_Vector z) +{ + z->ops->nvdiv(x, y, z); + return; +} + +void N_VScale(realtype c, N_Vector x, N_Vector z) +{ + z->ops->nvscale(c, x, z); + return; +} + +void N_VAbs(N_Vector x, N_Vector z) +{ + z->ops->nvabs(x, z); + return; +} + +void N_VInv(N_Vector x, N_Vector z) +{ + z->ops->nvinv(x, z); + return; +} + +void N_VAddConst(N_Vector x, realtype b, N_Vector z) +{ + z->ops->nvaddconst(x, b, z); + return; +} + +realtype N_VDotProd(N_Vector x, N_Vector y) +{ + return((realtype) y->ops->nvdotprod(x, y)); +} + +realtype N_VMaxNorm(N_Vector x) +{ + return((realtype) x->ops->nvmaxnorm(x)); +} + +realtype N_VWrmsNorm(N_Vector x, N_Vector w) +{ + return((realtype) x->ops->nvwrmsnorm(x, w)); +} + +realtype N_VWrmsNormMask(N_Vector x, N_Vector w, N_Vector id) +{ + return((realtype) x->ops->nvwrmsnormmask(x, w, id)); +} + +realtype N_VMin(N_Vector x) +{ + return((realtype) x->ops->nvmin(x)); +} + +realtype N_VWL2Norm(N_Vector x, N_Vector w) +{ + return((realtype) x->ops->nvwl2norm(x, w)); +} + +realtype N_VL1Norm(N_Vector x) +{ + return((realtype) x->ops->nvl1norm(x)); +} + +void N_VCompare(realtype c, N_Vector x, N_Vector z) +{ + z->ops->nvcompare(c, x, z); + return; +} + +booleantype N_VInvTest(N_Vector x, N_Vector z) +{ + return((booleantype) z->ops->nvinvtest(x, z)); +} + +booleantype N_VConstrMask(N_Vector c, N_Vector x, N_Vector m) +{ + return((booleantype) x->ops->nvconstrmask(c, x, m)); +} + +realtype N_VMinQuotient(N_Vector num, N_Vector denom) +{ + return((realtype) num->ops->nvminquotient(num, denom)); +} + +/* + * ----------------------------------------------------------------- + * Additional functions exported by the generic NVECTOR: + * N_VCloneEmptyVectorArray + * N_VCloneVectorArray + * N_VDestroyVectorArray + * ----------------------------------------------------------------- + */ + +N_Vector *N_VCloneEmptyVectorArray(int count, N_Vector w) +{ + N_Vector *vs = NULL; + int j; + + if (count <= 0) return(NULL); + + vs = (N_Vector *) malloc(count * sizeof(N_Vector)); + if(vs == NULL) return(NULL); + + for (j = 0; j < count; j++) { + vs[j] = N_VCloneEmpty(w); + if (vs[j] == NULL) { + N_VDestroyVectorArray(vs, j-1); + return(NULL); + } + } + + return(vs); +} + +N_Vector *N_VCloneVectorArray(int count, N_Vector w) +{ + N_Vector *vs = NULL; + int j; + + if (count <= 0) return(NULL); + + vs = (N_Vector *) malloc(count * sizeof(N_Vector)); + if(vs == NULL) return(NULL); + + for (j = 0; j < count; j++) { + vs[j] = N_VClone(w); + if (vs[j] == NULL) { + N_VDestroyVectorArray(vs, j-1); + return(NULL); + } + } + + return(vs); +} + +void N_VDestroyVectorArray(N_Vector *vs, int count) +{ + int j; + + if (vs==NULL) return; + + for (j = 0; j < count; j++) N_VDestroy(vs[j]); + + free(vs); vs = NULL; + + return; +} diff --git a/odemex/Parser/CVode/ida_src/src/sundials/sundials_spbcgs.c b/odemex/Parser/CVode/ida_src/src/sundials/sundials_spbcgs.c new file mode 100644 index 0000000..b73bf26 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/sundials/sundials_spbcgs.c @@ -0,0 +1,379 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2007/04/06 20:33:30 $ + * ----------------------------------------------------------------- + * Programmer(s): Peter Brown and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2004, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the scaled, preconditioned + * Bi-CGSTAB (SPBCG) iterative linear solver. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include + +/* + * ----------------------------------------------------------------- + * private constants + * ----------------------------------------------------------------- + */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +/* + * ----------------------------------------------------------------- + * Function : SpbcgMalloc + * ----------------------------------------------------------------- + */ + +SpbcgMem SpbcgMalloc(int l_max, N_Vector vec_tmpl) +{ + SpbcgMem mem; + N_Vector r_star, r, p, q, u, Ap, vtemp; + + /* Check the input parameters */ + + if (l_max <= 0) return(NULL); + + /* Get arrays to hold temporary vectors */ + + r_star = N_VClone(vec_tmpl); + if (r_star == NULL) { + return(NULL); + } + + r = N_VClone(vec_tmpl); + if (r == NULL) { + N_VDestroy(r_star); + return(NULL); + } + + p = N_VClone(vec_tmpl); + if (p == NULL) { + N_VDestroy(r_star); + N_VDestroy(r); + return(NULL); + } + + q = N_VClone(vec_tmpl); + if (q == NULL) { + N_VDestroy(r_star); + N_VDestroy(r); + N_VDestroy(p); + return(NULL); + } + + u = N_VClone(vec_tmpl); + if (u == NULL) { + N_VDestroy(r_star); + N_VDestroy(r); + N_VDestroy(p); + N_VDestroy(q); + return(NULL); + } + + Ap = N_VClone(vec_tmpl); + if (Ap == NULL) { + N_VDestroy(r_star); + N_VDestroy(r); + N_VDestroy(p); + N_VDestroy(q); + N_VDestroy(u); + return(NULL); + } + + vtemp = N_VClone(vec_tmpl); + if (vtemp == NULL) { + N_VDestroy(r_star); + N_VDestroy(r); + N_VDestroy(p); + N_VDestroy(q); + N_VDestroy(u); + N_VDestroy(Ap); + return(NULL); + } + + /* Get memory for an SpbcgMemRec containing SPBCG matrices and vectors */ + + mem = NULL; + mem = (SpbcgMem) malloc(sizeof(SpbcgMemRec)); + if (mem == NULL) { + N_VDestroy(r_star); + N_VDestroy(r); + N_VDestroy(p); + N_VDestroy(q); + N_VDestroy(u); + N_VDestroy(Ap); + N_VDestroy(vtemp); + return(NULL); + } + + /* Set the fields of mem */ + + mem->l_max = l_max; + mem->r_star = r_star; + mem->r = r; + mem->p = p; + mem->q = q; + mem->u = u; + mem->Ap = Ap; + mem->vtemp = vtemp; + + /* Return the pointer to SPBCG memory */ + + return(mem); +} + +/* + * ----------------------------------------------------------------- + * Function : SpbcgSolve + * ----------------------------------------------------------------- + */ + +int SpbcgSolve(SpbcgMem mem, void *A_data, N_Vector x, N_Vector b, + int pretype, realtype delta, void *P_data, N_Vector sx, + N_Vector sb, ATimesFn atimes, PSolveFn psolve, + realtype *res_norm, int *nli, int *nps) +{ + realtype alpha, beta, omega, omega_denom, beta_num, beta_denom, r_norm, rho; + N_Vector r_star, r, p, q, u, Ap, vtemp; + booleantype preOnLeft, preOnRight, scale_x, scale_b, converged; + int l, l_max, ier; + + if (mem == NULL) return(SPBCG_MEM_NULL); + + /* Make local copies of mem variables */ + + l_max = mem->l_max; + r_star = mem->r_star; + r = mem->r; + p = mem->p; + q = mem->q; + u = mem->u; + Ap = mem->Ap; + vtemp = mem->vtemp; + + *nli = *nps = 0; /* Initialize counters */ + converged = FALSE; /* Initialize converged flag */ + + if ((pretype != PREC_LEFT) && (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) pretype = PREC_NONE; + + preOnLeft = ((pretype == PREC_BOTH) || (pretype == PREC_LEFT)); + preOnRight = ((pretype == PREC_BOTH) || (pretype == PREC_RIGHT)); + + scale_x = (sx != NULL); + scale_b = (sb != NULL); + + /* Set r_star to initial (unscaled) residual r_0 = b - A*x_0 */ + + if (N_VDotProd(x, x) == ZERO) N_VScale(ONE, b, r_star); + else { + ier = atimes(A_data, x, r_star); + if (ier != 0) + return((ier < 0) ? SPBCG_ATIMES_FAIL_UNREC : SPBCG_ATIMES_FAIL_REC); + N_VLinearSum(ONE, b, -ONE, r_star, r_star); + } + + /* Apply left preconditioner and b-scaling to r_star = r_0 */ + + if (preOnLeft) { + ier = psolve(P_data, r_star, r, PREC_LEFT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC); + } + else N_VScale(ONE, r_star, r); + + if (scale_b) N_VProd(sb, r, r_star); + else N_VScale(ONE, r, r_star); + + /* Initialize beta_denom to the dot product of r0 with r0 */ + + beta_denom = N_VDotProd(r_star, r_star); + + /* Set r_norm to L2 norm of r_star = sb P1_inv r_0, and + return if small */ + + *res_norm = r_norm = rho = RSqrt(beta_denom); + if (r_norm <= delta) return(SPBCG_SUCCESS); + + /* Copy r_star to r and p */ + + N_VScale(ONE, r_star, r); + N_VScale(ONE, r_star, p); + + /* Begin main iteration loop */ + + for(l = 0; l < l_max; l++) { + + (*nli)++; + + /* Generate Ap = A-tilde p, where A-tilde = sb P1_inv A P2_inv sx_inv */ + + /* Apply x-scaling: vtemp = sx_inv p */ + + if (scale_x) N_VDiv(p, sx, vtemp); + else N_VScale(ONE, p, vtemp); + + /* Apply right preconditioner: vtemp = P2_inv sx_inv p */ + + if (preOnRight) { + N_VScale(ONE, vtemp, Ap); + ier = psolve(P_data, Ap, vtemp, PREC_RIGHT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC); + } + + /* Apply A: Ap = A P2_inv sx_inv p */ + + ier = atimes(A_data, vtemp, Ap ); + if (ier != 0) + return((ier < 0) ? SPBCG_ATIMES_FAIL_UNREC : SPBCG_ATIMES_FAIL_REC); + + /* Apply left preconditioner: vtemp = P1_inv A P2_inv sx_inv p */ + + if (preOnLeft) { + ier = psolve(P_data, Ap, vtemp, PREC_LEFT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC); + } + else N_VScale(ONE, Ap, vtemp); + + /* Apply b-scaling: Ap = sb P1_inv A P2_inv sx_inv p */ + + if (scale_b) N_VProd(sb, vtemp, Ap); + else N_VScale(ONE, vtemp, Ap); + + + /* Calculate alpha = / */ + + alpha = ((N_VDotProd(r, r_star) / N_VDotProd(Ap, r_star))); + + /* Update q = r - alpha*Ap = r - alpha*(sb P1_inv A P2_inv sx_inv p) */ + + N_VLinearSum(ONE, r, -alpha, Ap, q); + + /* Generate u = A-tilde q */ + + /* Apply x-scaling: vtemp = sx_inv q */ + + if (scale_x) N_VDiv(q, sx, vtemp); + else N_VScale(ONE, q, vtemp); + + /* Apply right preconditioner: vtemp = P2_inv sx_inv q */ + + if (preOnRight) { + N_VScale(ONE, vtemp, u); + ier = psolve(P_data, u, vtemp, PREC_RIGHT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC); + } + + /* Apply A: u = A P2_inv sx_inv u */ + + ier = atimes(A_data, vtemp, u ); + if (ier != 0) + return((ier < 0) ? SPBCG_ATIMES_FAIL_UNREC : SPBCG_ATIMES_FAIL_REC); + + /* Apply left preconditioner: vtemp = P1_inv A P2_inv sx_inv p */ + + if (preOnLeft) { + ier = psolve(P_data, u, vtemp, PREC_LEFT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC); + } + else N_VScale(ONE, u, vtemp); + + /* Apply b-scaling: u = sb P1_inv A P2_inv sx_inv u */ + + if (scale_b) N_VProd(sb, vtemp, u); + else N_VScale(ONE, vtemp, u); + + + /* Calculate omega = / */ + + omega_denom = N_VDotProd(u, u); + if (omega_denom == ZERO) omega_denom = ONE; + omega = (N_VDotProd(u, q) / omega_denom); + + /* Update x = x + alpha*p + omega*q */ + + N_VLinearSum(alpha, p, omega, q, vtemp); + N_VLinearSum(ONE, x, ONE, vtemp, x); + + /* Update the residual r = q - omega*u */ + + N_VLinearSum(ONE, q, -omega, u, r); + + /* Set rho = norm(r) and check convergence */ + + *res_norm = rho = RSqrt(N_VDotProd(r, r)); + if (rho <= delta) { + converged = TRUE; + break; + } + + /* Not yet converged, continue iteration */ + /* Update beta = / * alpha / omega */ + + beta_num = N_VDotProd(r, r_star); + beta = ((beta_num / beta_denom) * (alpha / omega)); + beta_denom = beta_num; + + /* Update p = r + beta*(p - omega*Ap) */ + + N_VLinearSum(ONE, p, -omega, Ap, vtemp); + N_VLinearSum(ONE, r, beta, vtemp, p); + + } + + /* Main loop finished */ + + if ((converged == TRUE) || (rho < r_norm)) { + + /* Apply the x-scaling and right preconditioner: x = P2_inv sx_inv x */ + + if (scale_x) N_VDiv(x, sx, x); + if (preOnRight) { + ier = psolve(P_data, x, vtemp, PREC_RIGHT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC); + N_VScale(ONE, vtemp, x); + } + + if (converged == TRUE) return(SPBCG_SUCCESS); + else return(SPBCG_RES_REDUCED); + } + else return(SPBCG_CONV_FAIL); +} + +/* + * ----------------------------------------------------------------- + * Function : SpbcgFree + * ----------------------------------------------------------------- + */ + +void SpbcgFree(SpbcgMem mem) +{ + + if (mem == NULL) return; + + N_VDestroy(mem->r_star); + N_VDestroy(mem->r); + N_VDestroy(mem->p); + N_VDestroy(mem->q); + N_VDestroy(mem->u); + N_VDestroy(mem->Ap); + N_VDestroy(mem->vtemp); + + free(mem); mem = NULL; +} diff --git a/odemex/Parser/CVode/ida_src/src/sundials/sundials_spgmr.c b/odemex/Parser/CVode/ida_src/src/sundials/sundials_spgmr.c new file mode 100644 index 0000000..7efd187 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/sundials/sundials_spgmr.c @@ -0,0 +1,458 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2007/04/06 20:33:30 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the scaled preconditioned + * GMRES (SPGMR) iterative linear solver. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include + +/* + * ----------------------------------------------------------------- + * private constants + * ----------------------------------------------------------------- + */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +/* + * ----------------------------------------------------------------- + * Function : SpgmrMalloc + * ----------------------------------------------------------------- + */ + +SpgmrMem SpgmrMalloc(int l_max, N_Vector vec_tmpl) +{ + SpgmrMem mem; + N_Vector *V, xcor, vtemp; + realtype **Hes, *givens, *yg; + int k, i; + + /* Check the input parameters. */ + + if (l_max <= 0) return(NULL); + + /* Get memory for the Krylov basis vectors V[0], ..., V[l_max]. */ + + V = N_VCloneVectorArray(l_max+1, vec_tmpl); + if (V == NULL) return(NULL); + + /* Get memory for the Hessenberg matrix Hes. */ + + Hes = NULL; + Hes = (realtype **) malloc((l_max+1)*sizeof(realtype *)); + if (Hes == NULL) { + N_VDestroyVectorArray(V, l_max+1); + return(NULL); + } + + for (k = 0; k <= l_max; k++) { + Hes[k] = NULL; + Hes[k] = (realtype *) malloc(l_max*sizeof(realtype)); + if (Hes[k] == NULL) { + for (i = 0; i < k; i++) {free(Hes[i]); Hes[i] = NULL;} + free(Hes); Hes = NULL; + N_VDestroyVectorArray(V, l_max+1); + return(NULL); + } + } + + /* Get memory for Givens rotation components. */ + + givens = NULL; + givens = (realtype *) malloc(2*l_max*sizeof(realtype)); + if (givens == NULL) { + for (i = 0; i <= l_max; i++) {free(Hes[i]); Hes[i] = NULL;} + free(Hes); Hes = NULL; + N_VDestroyVectorArray(V, l_max+1); + return(NULL); + } + + /* Get memory to hold the correction to z_tilde. */ + + xcor = N_VClone(vec_tmpl); + if (xcor == NULL) { + free(givens); givens = NULL; + for (i = 0; i <= l_max; i++) {free(Hes[i]); Hes[i] = NULL;} + free(Hes); Hes = NULL; + N_VDestroyVectorArray(V, l_max+1); + return(NULL); + } + + /* Get memory to hold SPGMR y and g vectors. */ + + yg = NULL; + yg = (realtype *) malloc((l_max+1)*sizeof(realtype)); + if (yg == NULL) { + N_VDestroy(xcor); + free(givens); givens = NULL; + for (i = 0; i <= l_max; i++) {free(Hes[i]); Hes[i] = NULL;} + free(Hes); Hes = NULL; + N_VDestroyVectorArray(V, l_max+1); + return(NULL); + } + + /* Get an array to hold a temporary vector. */ + + vtemp = N_VClone(vec_tmpl); + if (vtemp == NULL) { + free(yg); yg = NULL; + N_VDestroy(xcor); + free(givens); givens = NULL; + for (i = 0; i <= l_max; i++) {free(Hes[i]); Hes[i] = NULL;} + free(Hes); Hes = NULL; + N_VDestroyVectorArray(V, l_max+1); + return(NULL); + } + + /* Get memory for an SpgmrMemRec containing SPGMR matrices and vectors. */ + + mem = NULL; + mem = (SpgmrMem) malloc(sizeof(SpgmrMemRec)); + if (mem == NULL) { + N_VDestroy(vtemp); + free(yg); yg = NULL; + N_VDestroy(xcor); + free(givens); givens = NULL; + for (i = 0; i <= l_max; i++) {free(Hes[i]); Hes[i] = NULL;} + free(Hes); Hes = NULL; + N_VDestroyVectorArray(V, l_max+1); + return(NULL); + } + + /* Set the fields of mem. */ + + mem->l_max = l_max; + mem->V = V; + mem->Hes = Hes; + mem->givens = givens; + mem->xcor = xcor; + mem->yg = yg; + mem->vtemp = vtemp; + + /* Return the pointer to SPGMR memory. */ + + return(mem); +} + +/* + * ----------------------------------------------------------------- + * Function : SpgmrSolve + * ----------------------------------------------------------------- + */ + +int SpgmrSolve(SpgmrMem mem, void *A_data, N_Vector x, N_Vector b, + int pretype, int gstype, realtype delta, int max_restarts, + void *P_data, N_Vector s1, N_Vector s2, ATimesFn atimes, + PSolveFn psolve, realtype *res_norm, int *nli, int *nps) +{ + N_Vector *V, xcor, vtemp; + realtype **Hes, *givens, *yg; + realtype beta, rotation_product, r_norm, s_product, rho; + booleantype preOnLeft, preOnRight, scale2, scale1, converged; + int i, j, k, l, l_plus_1, l_max, krydim, ier, ntries; + + if (mem == NULL) return(SPGMR_MEM_NULL); + + /* Initialize some variables */ + + l_plus_1 = 0; + krydim = 0; + + /* Make local copies of mem variables. */ + + l_max = mem->l_max; + V = mem->V; + Hes = mem->Hes; + givens = mem->givens; + xcor = mem->xcor; + yg = mem->yg; + vtemp = mem->vtemp; + + *nli = *nps = 0; /* Initialize counters */ + converged = FALSE; /* Initialize converged flag */ + + if (max_restarts < 0) max_restarts = 0; + + if ((pretype != PREC_LEFT) && (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) + pretype = PREC_NONE; + + preOnLeft = ((pretype == PREC_LEFT) || (pretype == PREC_BOTH)); + preOnRight = ((pretype == PREC_RIGHT) || (pretype == PREC_BOTH)); + scale1 = (s1 != NULL); + scale2 = (s2 != NULL); + + /* Set vtemp and V[0] to initial (unscaled) residual r_0 = b - A*x_0. */ + + if (N_VDotProd(x, x) == ZERO) { + N_VScale(ONE, b, vtemp); + } else { + ier = atimes(A_data, x, vtemp); + if (ier != 0) + return((ier < 0) ? SPGMR_ATIMES_FAIL_UNREC : SPGMR_ATIMES_FAIL_REC); + N_VLinearSum(ONE, b, -ONE, vtemp, vtemp); + } + N_VScale(ONE, vtemp, V[0]); + + /* Apply left preconditioner and left scaling to V[0] = r_0. */ + + if (preOnLeft) { + ier = psolve(P_data, V[0], vtemp, PREC_LEFT); + (*nps)++; + if (ier != 0) + return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC); + } else { + N_VScale(ONE, V[0], vtemp); + } + + if (scale1) { + N_VProd(s1, vtemp, V[0]); + } else { + N_VScale(ONE, vtemp, V[0]); + } + + /* Set r_norm = beta to L2 norm of V[0] = s1 P1_inv r_0, and + return if small. */ + + *res_norm = r_norm = beta = RSqrt(N_VDotProd(V[0], V[0])); + if (r_norm <= delta) + return(SPGMR_SUCCESS); + + /* Initialize rho to avoid compiler warning message */ + + rho = beta; + + /* Set xcor = 0. */ + + N_VConst(ZERO, xcor); + + + /* Begin outer iterations: up to (max_restarts + 1) attempts. */ + + for (ntries = 0; ntries <= max_restarts; ntries++) { + + /* Initialize the Hessenberg matrix Hes and Givens rotation + product. Normalize the initial vector V[0]. */ + + for (i = 0; i <= l_max; i++) + for (j = 0; j < l_max; j++) + Hes[i][j] = ZERO; + + rotation_product = ONE; + + N_VScale(ONE/r_norm, V[0], V[0]); + + /* Inner loop: generate Krylov sequence and Arnoldi basis. */ + + for (l = 0; l < l_max; l++) { + + (*nli)++; + + krydim = l_plus_1 = l + 1; + + /* Generate A-tilde V[l], where A-tilde = s1 P1_inv A P2_inv s2_inv. */ + + /* Apply right scaling: vtemp = s2_inv V[l]. */ + + if (scale2) N_VDiv(V[l], s2, vtemp); + else N_VScale(ONE, V[l], vtemp); + + /* Apply right preconditioner: vtemp = P2_inv s2_inv V[l]. */ + + if (preOnRight) { + N_VScale(ONE, vtemp, V[l_plus_1]); + ier = psolve(P_data, V[l_plus_1], vtemp, PREC_RIGHT); + (*nps)++; + if (ier != 0) + return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC); + } + + /* Apply A: V[l+1] = A P2_inv s2_inv V[l]. */ + + ier = atimes(A_data, vtemp, V[l_plus_1] ); + if (ier != 0) + return((ier < 0) ? SPGMR_ATIMES_FAIL_UNREC : SPGMR_ATIMES_FAIL_REC); + + /* Apply left preconditioning: vtemp = P1_inv A P2_inv s2_inv V[l]. */ + + if (preOnLeft) { + ier = psolve(P_data, V[l_plus_1], vtemp, PREC_LEFT); + (*nps)++; + if (ier != 0) + return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC); + } else { + N_VScale(ONE, V[l_plus_1], vtemp); + } + + /* Apply left scaling: V[l+1] = s1 P1_inv A P2_inv s2_inv V[l]. */ + + if (scale1) { + N_VProd(s1, vtemp, V[l_plus_1]); + } else { + N_VScale(ONE, vtemp, V[l_plus_1]); + } + + /* Orthogonalize V[l+1] against previous V[i]: V[l+1] = w_tilde. */ + + if (gstype == CLASSICAL_GS) { + if (ClassicalGS(V, Hes, l_plus_1, l_max, &(Hes[l_plus_1][l]), + vtemp, yg) != 0) + return(SPGMR_GS_FAIL); + } else { + if (ModifiedGS(V, Hes, l_plus_1, l_max, &(Hes[l_plus_1][l])) != 0) + return(SPGMR_GS_FAIL); + } + + /* Update the QR factorization of Hes. */ + + if(QRfact(krydim, Hes, givens, l) != 0 ) + return(SPGMR_QRFACT_FAIL); + + /* Update residual norm estimate; break if convergence test passes. */ + + rotation_product *= givens[2*l+1]; + *res_norm = rho = ABS(rotation_product*r_norm); + + if (rho <= delta) { converged = TRUE; break; } + + /* Normalize V[l+1] with norm value from the Gram-Schmidt routine. */ + + N_VScale(ONE/Hes[l_plus_1][l], V[l_plus_1], V[l_plus_1]); + } + + /* Inner loop is done. Compute the new correction vector xcor. */ + + /* Construct g, then solve for y. */ + + yg[0] = r_norm; + for (i = 1; i <= krydim; i++) yg[i]=ZERO; + if (QRsol(krydim, Hes, givens, yg) != 0) + return(SPGMR_QRSOL_FAIL); + + /* Add correction vector V_l y to xcor. */ + + for (k = 0; k < krydim; k++) + N_VLinearSum(yg[k], V[k], ONE, xcor, xcor); + + /* If converged, construct the final solution vector x and return. */ + + if (converged) { + + /* Apply right scaling and right precond.: vtemp = P2_inv s2_inv xcor. */ + + if (scale2) N_VDiv(xcor, s2, xcor); + if (preOnRight) { + ier = psolve(P_data, xcor, vtemp, PREC_RIGHT); + (*nps)++; + if (ier != 0) + return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC); + } else { + N_VScale(ONE, xcor, vtemp); + } + + /* Add vtemp to initial x to get final solution x, and return */ + + N_VLinearSum(ONE, x, ONE, vtemp, x); + + return(SPGMR_SUCCESS); + } + + /* Not yet converged; if allowed, prepare for restart. */ + + if (ntries == max_restarts) break; + + /* Construct last column of Q in yg. */ + + s_product = ONE; + for (i = krydim; i > 0; i--) { + yg[i] = s_product*givens[2*i-2]; + s_product *= givens[2*i-1]; + } + yg[0] = s_product; + + /* Scale r_norm and yg. */ + r_norm *= s_product; + for (i = 0; i <= krydim; i++) + yg[i] *= r_norm; + r_norm = ABS(r_norm); + + /* Multiply yg by V_(krydim+1) to get last residual vector; restart. */ + N_VScale(yg[0], V[0], V[0]); + for (k = 1; k <= krydim; k++) + N_VLinearSum(yg[k], V[k], ONE, V[0], V[0]); + + } + + /* Failed to converge, even after allowed restarts. + If the residual norm was reduced below its initial value, compute + and return x anyway. Otherwise return failure flag. */ + + if (rho < beta) { + + /* Apply right scaling and right precond.: vtemp = P2_inv s2_inv xcor. */ + + if (scale2) N_VDiv(xcor, s2, xcor); + if (preOnRight) { + ier = psolve(P_data, xcor, vtemp, PREC_RIGHT); + (*nps)++; + if (ier != 0) + return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC); + } else { + N_VScale(ONE, xcor, vtemp); + } + + /* Add vtemp to initial x to get final solution x, and return. */ + + N_VLinearSum(ONE, x, ONE, vtemp, x); + + return(SPGMR_RES_REDUCED); + } + + return(SPGMR_CONV_FAIL); +} + +/* + * ----------------------------------------------------------------- + * Function : SpgmrFree + * ----------------------------------------------------------------- + */ + +void SpgmrFree(SpgmrMem mem) +{ + int i, l_max; + realtype **Hes, *givens, *yg; + + if (mem == NULL) return; + + l_max = mem->l_max; + Hes = mem->Hes; + givens = mem->givens; + yg = mem->yg; + + for (i = 0; i <= l_max; i++) {free(Hes[i]); Hes[i] = NULL;} + free(Hes); Hes = NULL; + free(mem->givens); givens = NULL; + free(mem->yg); yg = NULL; + + N_VDestroyVectorArray(mem->V, l_max+1); + N_VDestroy(mem->xcor); + N_VDestroy(mem->vtemp); + + free(mem); mem = NULL; +} diff --git a/odemex/Parser/CVode/ida_src/src/sundials/sundials_sptfqmr.c b/odemex/Parser/CVode/ida_src/src/sundials/sundials_sptfqmr.c new file mode 100644 index 0000000..626ca00 --- /dev/null +++ b/odemex/Parser/CVode/ida_src/src/sundials/sundials_sptfqmr.c @@ -0,0 +1,516 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2007/04/06 20:33:30 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the scaled preconditioned + * Transpose-Free Quasi-Minimal Residual (SPTFQMR) linear solver. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include + +/* + * ----------------------------------------------------------------- + * private constants + * ----------------------------------------------------------------- + */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +/* + * ----------------------------------------------------------------- + * Function : SptfqmrMalloc + * ----------------------------------------------------------------- + */ + +SptfqmrMem SptfqmrMalloc(int l_max, N_Vector vec_tmpl) +{ + SptfqmrMem mem; + N_Vector *r; + N_Vector q, d, v, p, u; + N_Vector r_star, vtemp1, vtemp2, vtemp3; + + /* Check the input parameters */ + if ((l_max <= 0) || (vec_tmpl == NULL)) return(NULL); + + /* Allocate space for vectors */ + + r_star = N_VClone(vec_tmpl); + if (r_star == NULL) return(NULL); + + q = N_VClone(vec_tmpl); + if (q == NULL) { + N_VDestroy(r_star); + return(NULL); + } + + d = N_VClone(vec_tmpl); + if (d == NULL) { + N_VDestroy(r_star); + N_VDestroy(q); + return(NULL); + } + + v = N_VClone(vec_tmpl); + if (v == NULL) { + N_VDestroy(r_star); + N_VDestroy(q); + N_VDestroy(d); + return(NULL); + } + + p = N_VClone(vec_tmpl); + if (p == NULL) { + N_VDestroy(r_star); + N_VDestroy(q); + N_VDestroy(d); + N_VDestroy(v); + return(NULL); + } + + r = N_VCloneVectorArray(2, vec_tmpl); + if (r == NULL) { + N_VDestroy(r_star); + N_VDestroy(q); + N_VDestroy(d); + N_VDestroy(v); + N_VDestroy(p); + return(NULL); + } + + u = N_VClone(vec_tmpl); + if (u == NULL) { + N_VDestroy(r_star); + N_VDestroy(q); + N_VDestroy(d); + N_VDestroy(v); + N_VDestroy(p); + N_VDestroyVectorArray(r, 2); + return(NULL); + } + + vtemp1 = N_VClone(vec_tmpl); + if (vtemp1 == NULL) { + N_VDestroy(r_star); + N_VDestroy(q); + N_VDestroy(d); + N_VDestroy(v); + N_VDestroy(p); + N_VDestroyVectorArray(r, 2); + N_VDestroy(u); + return(NULL); + } + + vtemp2 = N_VClone(vec_tmpl); + if (vtemp2 == NULL) { + N_VDestroy(r_star); + N_VDestroy(q); + N_VDestroy(d); + N_VDestroy(v); + N_VDestroy(p); + N_VDestroyVectorArray(r, 2); + N_VDestroy(u); + N_VDestroy(vtemp1); + return(NULL); + } + + vtemp3 = N_VClone(vec_tmpl); + if (vtemp3 == NULL) { + N_VDestroy(r_star); + N_VDestroy(q); + N_VDestroy(d); + N_VDestroy(v); + N_VDestroy(p); + N_VDestroyVectorArray(r, 2); + N_VDestroy(u); + N_VDestroy(vtemp1); + N_VDestroy(vtemp2); + return(NULL); + } + + /* Allocate memory for SptfqmrMemRec */ + mem = NULL; + mem = (SptfqmrMem) malloc(sizeof(SptfqmrMemRec)); + if (mem == NULL) { + N_VDestroy(r_star); + N_VDestroy(q); + N_VDestroy(d); + N_VDestroy(v); + N_VDestroy(p); + N_VDestroyVectorArray(r, 2); + N_VDestroy(u); + N_VDestroy(vtemp1); + N_VDestroy(vtemp2); + N_VDestroy(vtemp3); + return(NULL); + } + + /* Intialize SptfqmrMemRec data structure */ + mem->l_max = l_max; + mem->r_star = r_star; + mem->q = q; + mem->d = d; + mem->v = v; + mem->p = p; + mem->r = r; + mem->u = u; + mem->vtemp1 = vtemp1; + mem->vtemp2 = vtemp2; + mem->vtemp3 = vtemp3; + + /* Return pointer to SPTFQMR memory block */ + return(mem); +} + +#define l_max (mem->l_max) +#define r_star (mem->r_star) +#define q_ (mem->q) +#define d_ (mem->d) +#define v_ (mem->v) +#define p_ (mem->p) +#define r_ (mem->r) +#define u_ (mem->u) +#define vtemp1 (mem->vtemp1) +#define vtemp2 (mem->vtemp2) +#define vtemp3 (mem->vtemp3) + +/* + * ----------------------------------------------------------------- + * Function : SptfqmrSolve + * ----------------------------------------------------------------- + */ + +int SptfqmrSolve(SptfqmrMem mem, void *A_data, N_Vector x, N_Vector b, + int pretype, realtype delta, void *P_data, N_Vector sx, + N_Vector sb, ATimesFn atimes, PSolveFn psolve, + realtype *res_norm, int *nli, int *nps) +{ + realtype alpha, tau, eta, beta, c, sigma, v_bar, omega; + realtype rho[2]; + realtype r_init_norm, r_curr_norm; + realtype temp_val; + booleantype preOnLeft, preOnRight, scale_x, scale_b, converged; + booleantype b_ok; + int n, m, ier; + + /* Exit immediately if memory pointer is NULL */ + if (mem == NULL) return(SPTFQMR_MEM_NULL); + + temp_val = r_curr_norm = -ONE; /* Initialize to avoid compiler warnings */ + + *nli = *nps = 0; /* Initialize counters */ + converged = FALSE; /* Initialize convergence flag */ + b_ok = FALSE; + + if ((pretype != PREC_LEFT) && + (pretype != PREC_RIGHT) && + (pretype != PREC_BOTH)) pretype = PREC_NONE; + + preOnLeft = ((pretype == PREC_BOTH) || (pretype == PREC_LEFT)); + preOnRight = ((pretype == PREC_BOTH) || (pretype == PREC_RIGHT)); + + scale_x = (sx != NULL); + scale_b = (sb != NULL); + + /* Set r_star to initial (unscaled) residual r_star = r_0 = b - A*x_0 */ + /* NOTE: if x == 0 then just set residual to b and continue */ + if (N_VDotProd(x, x) == ZERO) N_VScale(ONE, b, r_star); + else { + ier = atimes(A_data, x, r_star); + if (ier != 0) + return((ier < 0) ? SPTFQMR_ATIMES_FAIL_UNREC : SPTFQMR_ATIMES_FAIL_REC); + N_VLinearSum(ONE, b, -ONE, r_star, r_star); + } + + /* Apply left preconditioner and b-scaling to r_star (or really just r_0) */ + if (preOnLeft) { + ier = psolve(P_data, r_star, vtemp1, PREC_LEFT); + (*nps)++; + if (ier != 0) + return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC); + } + else N_VScale(ONE, r_star, vtemp1); + if (scale_b) N_VProd(sb, vtemp1, r_star); + else N_VScale(ONE, vtemp1, r_star); + + /* Initialize rho[0] */ + /* NOTE: initialized here to reduce number of computations - avoid need + to compute r_star^T*r_star twice, and avoid needlessly squaring + values */ + rho[0] = N_VDotProd(r_star, r_star); + + /* Compute norm of initial residual (r_0) to see if we really need + to do anything */ + *res_norm = r_init_norm = RSqrt(rho[0]); + if (r_init_norm <= delta) return(SPTFQMR_SUCCESS); + + /* Set v_ = A*r_0 (preconditioned and scaled) */ + if (scale_x) N_VDiv(r_star, sx, vtemp1); + else N_VScale(ONE, r_star, vtemp1); + if (preOnRight) { + N_VScale(ONE, vtemp1, v_); + ier = psolve(P_data, v_, vtemp1, PREC_RIGHT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC); + } + ier = atimes(A_data, vtemp1, v_); + if (ier != 0) + return((ier < 0) ? SPTFQMR_ATIMES_FAIL_UNREC : SPTFQMR_ATIMES_FAIL_REC); + if (preOnLeft) { + ier = psolve(P_data, v_, vtemp1, PREC_LEFT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC); + } + else N_VScale(ONE, v_, vtemp1); + if (scale_b) N_VProd(sb, vtemp1, v_); + else N_VScale(ONE, vtemp1, v_); + + /* Initialize remaining variables */ + N_VScale(ONE, r_star, r_[0]); + N_VScale(ONE, r_star, u_); + N_VScale(ONE, r_star, p_); + N_VConst(ZERO, d_); + + tau = r_init_norm; + v_bar = eta = ZERO; + + /* START outer loop */ + for (n = 0; n < l_max; ++n) { + + /* Increment linear iteration counter */ + (*nli)++; + + /* sigma = r_star^T*v_ */ + sigma = N_VDotProd(r_star, v_); + + /* alpha = rho[0]/sigma */ + alpha = rho[0]/sigma; + + /* q_ = u_-alpha*v_ */ + N_VLinearSum(ONE, u_, -alpha, v_, q_); + + /* r_[1] = r_[0]-alpha*A*(u_+q_) */ + N_VLinearSum(ONE, u_, ONE, q_, r_[1]); + if (scale_x) N_VDiv(r_[1], sx, r_[1]); + if (preOnRight) { + N_VScale(ONE, r_[1], vtemp1); + ier = psolve(P_data, vtemp1, r_[1], PREC_RIGHT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC); + } + ier = atimes(A_data, r_[1], vtemp1); + if (ier != 0) + return((ier < 0) ? SPTFQMR_ATIMES_FAIL_UNREC : SPTFQMR_ATIMES_FAIL_REC); + if (preOnLeft) { + ier = psolve(P_data, vtemp1, r_[1], PREC_LEFT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC); + } + else N_VScale(ONE, vtemp1, r_[1]); + if (scale_b) N_VProd(sb, r_[1], vtemp1); + else N_VScale(ONE, r_[1], vtemp1); + N_VLinearSum(ONE, r_[0], -alpha, vtemp1, r_[1]); + + /* START inner loop */ + for (m = 0; m < 2; ++m) { + + /* d_ = [*]+(v_bar^2*eta/alpha)*d_ */ + /* NOTES: + * (1) [*] = u_ if m == 0, and q_ if m == 1 + * (2) using temp_val reduces the number of required computations + * if the inner loop is executed twice + */ + if (m == 0) { + temp_val = RSqrt(N_VDotProd(r_[1], r_[1])); + omega = RSqrt(RSqrt(N_VDotProd(r_[0], r_[0]))*temp_val); + N_VLinearSum(ONE, u_, SQR(v_bar)*eta/alpha, d_, d_); + } + else { + omega = temp_val; + N_VLinearSum(ONE, q_, SQR(v_bar)*eta/alpha, d_, d_); + } + + /* v_bar = omega/tau */ + v_bar = omega/tau; + + /* c = (1+v_bar^2)^(-1/2) */ + c = ONE / RSqrt(ONE+SQR(v_bar)); + + /* tau = tau*v_bar*c */ + tau = tau*v_bar*c; + + /* eta = c^2*alpha */ + eta = SQR(c)*alpha; + + /* x = x+eta*d_ */ + N_VLinearSum(ONE, x, eta, d_, x); + + /* Check for convergence... */ + /* NOTE: just use approximation to norm of residual, if possible */ + *res_norm = r_curr_norm = tau*RSqrt(m+1); + + /* Exit inner loop if iteration has converged based upon approximation + to norm of current residual */ + if (r_curr_norm <= delta) { + converged = TRUE; + break; + } + + /* Decide if actual norm of residual vector should be computed */ + /* NOTES: + * (1) if r_curr_norm > delta, then check if actual residual norm + * is OK (recall we first compute an approximation) + * (2) if r_curr_norm >= r_init_norm and m == 1 and n == l_max, then + * compute actual residual norm to see if the iteration can be + * saved + * (3) the scaled and preconditioned right-hand side of the given + * linear system (denoted by b) is only computed once, and the + * result is stored in vtemp3 so it can be reused - reduces the + * number of psovles if using left preconditioning + */ + if ((r_curr_norm > delta) || + (r_curr_norm >= r_init_norm && m == 1 && n == l_max)) { + + /* Compute norm of residual ||b-A*x||_2 (preconditioned and scaled) */ + if (scale_x) N_VDiv(x, sx, vtemp1); + else N_VScale(ONE, x, vtemp1); + if (preOnRight) { + ier = psolve(P_data, vtemp1, vtemp2, PREC_RIGHT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_UNREC); + N_VScale(ONE, vtemp2, vtemp1); + } + ier = atimes(A_data, vtemp1, vtemp2); + if (ier != 0) + return((ier < 0) ? SPTFQMR_ATIMES_FAIL_UNREC : SPTFQMR_ATIMES_FAIL_REC); + if (preOnLeft) { + ier = psolve(P_data, vtemp2, vtemp1, PREC_LEFT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC); + } + else N_VScale(ONE, vtemp2, vtemp1); + if (scale_b) N_VProd(sb, vtemp1, vtemp2); + else N_VScale(ONE, vtemp1, vtemp2); + /* Only precondition and scale b once (result saved for reuse) */ + if (!b_ok) { + b_ok = TRUE; + if (preOnLeft) { + ier = psolve(P_data, b, vtemp3, PREC_LEFT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC); + } + else N_VScale(ONE, b, vtemp3); + if (scale_b) N_VProd(sb, vtemp3, vtemp3); + } + N_VLinearSum(ONE, vtemp3, -ONE, vtemp2, vtemp1); + *res_norm = r_curr_norm = RSqrt(N_VDotProd(vtemp1, vtemp1)); + + /* Exit inner loop if inequality condition is satisfied + (meaning exit if we have converged) */ + if (r_curr_norm <= delta) { + converged = TRUE; + break; + } + + } + + } /* END inner loop */ + + /* If converged, then exit outer loop as well */ + if (converged == TRUE) break; + + /* rho[1] = r_star^T*r_[1] */ + rho[1] = N_VDotProd(r_star, r_[1]); + + /* beta = rho[1]/rho[0] */ + beta = rho[1]/rho[0]; + + /* u_ = r_[1]+beta*q_ */ + N_VLinearSum(ONE, r_[1], beta, q_, u_); + + /* p_ = u_+beta*(q_+beta*p_) */ + N_VLinearSum(beta, q_, SQR(beta), p_, p_); + N_VLinearSum(ONE, u_, ONE, p_, p_); + + /* v_ = A*p_ */ + if (scale_x) N_VDiv(p_, sx, vtemp1); + else N_VScale(ONE, p_, vtemp1); + if (preOnRight) { + N_VScale(ONE, vtemp1, v_); + ier = psolve(P_data, v_, vtemp1, PREC_RIGHT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC); + } + ier = atimes(A_data, vtemp1, v_); + if (ier != 0) + return((ier < 0) ? SPTFQMR_ATIMES_FAIL_UNREC : SPTFQMR_ATIMES_FAIL_REC); + if (preOnLeft) { + ier = psolve(P_data, v_, vtemp1, PREC_LEFT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC); + } + else N_VScale(ONE, v_, vtemp1); + if (scale_b) N_VProd(sb, vtemp1, v_); + else N_VScale(ONE, vtemp1, v_); + + /* Shift variable values */ + /* NOTE: reduces storage requirements */ + N_VScale(ONE, r_[1], r_[0]); + rho[0] = rho[1]; + + } /* END outer loop */ + + /* Determine return value */ + /* If iteration converged or residual was reduced, then return current iterate (x) */ + if ((converged == TRUE) || (r_curr_norm < r_init_norm)) { + if (scale_x) N_VDiv(x, sx, x); + if (preOnRight) { + ier = psolve(P_data, x, vtemp1, PREC_RIGHT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_UNREC); + N_VScale(ONE, vtemp1, x); + } + if (converged == TRUE) return(SPTFQMR_SUCCESS); + else return(SPTFQMR_RES_REDUCED); + } + /* Otherwise, return error code */ + else return(SPTFQMR_CONV_FAIL); +} + +/* + * ----------------------------------------------------------------- + * Function : SptfqmrFree + * ----------------------------------------------------------------- + */ + +void SptfqmrFree(SptfqmrMem mem) +{ + + if (mem == NULL) return; + + N_VDestroy(r_star); + N_VDestroy(q_); + N_VDestroy(d_); + N_VDestroy(v_); + N_VDestroy(p_); + N_VDestroyVectorArray(r_, 2); + N_VDestroy(u_); + N_VDestroy(vtemp1); + N_VDestroy(vtemp2); + N_VDestroy(vtemp3); + + free(mem); mem = NULL; +} diff --git a/odemex/Parser/CVode/lib/CVODE.lib b/odemex/Parser/CVode/lib/CVODE.lib new file mode 100644 index 0000000000000000000000000000000000000000..490d14208e08943252ccabb594d28a73afbe93c8 GIT binary patch literal 738340 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
%$ZTMZ$x?%}2h(nKM(g|u2o-5~MV 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 z zu?mVn69>*Hs}V2swV8{mS1??cu{!>-fALtl5lb6%QDVXa>E*SYklABPC z{2?)>KZu)afodP@$v9^l=+aSxoCVESrq#c-GMg5;324KoF*VLUpnP)`4Fxza>Q%_i zo!H>NSCWfOf_d35SGRFh&IF{5t3@JzXpncCydRhMKD@abr0S%g`2^!R9>=*zeq!4r zi`RUCFQ%GcUiRbFsL#*k{f#M*>&C)g;QUb@emf2J_AdhsNQs=Dowzz_75iei_Z?PG ztW00L9&=@@THq9Z#Dh)Dt!<0}pOO6aA6Y&?PN7%3<&_)BT@S?|p#tGX2}UYbFs6|N z8KgUq-BE1@viDtoYA`zVIk+0Z?Qit6ka_W!rlOx6DE0_~r6Ab8>KB_=tp`3UQ}Ze| zKSEI2P!APc5mSRtu6;tE8&$kVwdYVzrRH}4L@0aDp}E1+(q#eM=vzxFj0 z^1|a7aT^UN1?l(^Lhym35yw$zDBMmIY+{kN{kYLRLFv-^Q`SF;He-!bR45H@N;@$X zr0+&sF-K$8y6hvbQ4&fsX2be3V1^G@hG5$eoBXHrgi!PmhvN+5LoOj-|OQz-e=Py~1#fAoS4OlWb^z+nYQ>lg}{D)YhO>c>StQ z4}aFbukh|_+Y0|#O6Uk&!4(qCIV?*KDqI;z(qsYi72WY_X|nUp;or41*@$+8l}#$nwZt!qKFe2qma7U4 zf7EFBqe{acbsAOLq=5Nc*3a4fSvdwPGoS<{XAeUScyc3)Q*7lXaJC>ODglaquvq%X zavT}DXIfUrfTRk0KcIPNo*wCbsz96sHx-D5fOvhAUTdg$G%YC}JIjhkwKGfbZUdxv zzjE+6a8tae0I4c?8<463PL-)RpW;A;4s;bD72O9uhqCyni zN;?sgup4c~O!;iE@fnU5`#5x%(S@!)PGfKEU)-gx&4NTF(y zYd}|#g$|7s*s*r>5!y{)#Y1yI?2IEGVaGowSRyCbQ8oo9#?0OI`&W+6GhtET88sLM z8@|=-+1OV!vTatkV~A^Z0csBK!<#iDYukP3e^q6mPa53*dVdvJDVsfTY!1_lNSKuD z#vh{iE{vYCbH{Tk2FP^8cAbc4F#3AlY&jyU`c1ZGCJ;>;mQ;rW?p%|6_a2i!I0B@# z;nS8@i%RM-P6DLOX(AwPP8S2xhF|31alEW}OB_5l+?7Iwb{eJkZw?-NeoC(e&~<`0 z7CG1Ez8Vm=rXdCE0BP7;0cjk+1EgW=0R0I+`}rBdXb(&wHmF77HX5{y5PB~&=oYsT zvFR!<8=6AH0aZyT_DUIt{kYLDSNiE5BOUYyd@K5-%Q)=EjlQNtdNGr*RO6D=VjZY~aN_G!=LGvVm8aUuNCS7QFJiBEN>U zvxpE+mv8lpfD(`Au5Lpk-xhD=R4ZAVx3H0)huy9%s6VDjT0%p?<}m$Pv(VD{Z_08B zoX}yLxVj-K<&#z}>+H=l?IAMG;7r&*3>z3ppm*^-t9N0Y}a(3IYO zxE+_!Gx(h}Z@dhJC_YSW@&;fS(~QtC?7cq>qJ_c)XA#KTFepYe3`MI#946fNP~n)677fRk|4p!oMcVe`M)x+Qo1O}hh2>#LJFi`4y6re93^inO zE;NorOvd9DhhoYGJn{&S%@=Yoo@#{{pYkOUldv0Y#Y{;{HPT?v95Tsg47q7wV_bM8 z8Z8fT23Jg!eVN4FgcBFLHP`M#ikVw9w%)7Xw!)|H8Cz{0K?GL3ivVfmOrEj59`5#Y zpA;k`REVtIB5v_ja+tAYziisH1WPUlStB?%f%cEBN8hq{R?NWyXCu}#9ewrAdi1Y^ zXAm|{;2n@_eFlCqc{D1Y@xWZ7@$GtbR;(2Bg%kH%qCJn|z9?zLHt`eb%|W7eLk8fS z=d&z{I-#9;O*&ds$7__Qn3x9LAZCQ6f6I>CTMpz!V`O`jv6j>e@QxB8-r0IuD#l50 z(*p0Sv!!@$ovn2UyIZK-3P|y8cj#>fq|&V!5RWJENVh}rC`&cow;VjKvQP;+36M%q zj=XA_6YF^fbhNXj5G&t<;x^jC7-(U`(TL+HM2YpNU=xe9?Z=I7lhWmp$uM^fSTID8 zZTh68p(sZbqTEvYM71#qyU|z7lrK|_FK3{W#p#iysTC_OcCi|EeKV`2KIxC}p}4jq<;6yp^HjtvVLt*ABTRpguK+Gx27{%G%Zl zVbjNui(W)RM{F|wdkwkh_+K*QI)FNUFhefI`(`Qdk)!$55E z>5{HN&`cZ)a^%r_EEtzQ97tqset^=4V?nNOa2X5IpH&$mC-+A0StJAQLTW zOpAu2s69fkiACD><3{%|rQ2ip$aLFrP+)7w6loA1e^)I-^NHnA~MyB?85YB}(7 z8HN9_PhK#|LB6c#bSLc!G3^t3r=7}pM)?(2EH1rh;X>R|DtAh8+JiH-GPM3dvTAbM zJ7;ZM;9gBL!jt`Ig)E#HtAE-Td_TKGw@TMP>RT5@A}|ra0|V{ZPP0q!w zJf5N$jBKNqn|v>-mID4;Us>#1Nqish}uoOIExpH%abElYDn*qsC_DyZX@rK{jZ zMtO`{2cj5Px4RwaK?h>HRbLK?70P#@Vh3WCRNplYbh`un4bW^!)pkIdz7{~5z83+h zBH2jY=)>XwGZTT1yvKA*#;3HobeZ(+$BlOWA<|~!I(4oAH6Mq}*~%TX)1*Qp8Q;>`~Z;pW&^ra+@=Cj%6Wj4auFb< zJQ+|qe)h8wVbt=VkQW|h;x^hs`Mvc|T@%Mqh=Tnl!9Ef+N!xzZKRL`2hi(MHgxO+U2FDwZSK`txA_>?b+m~eEZt(c>!npvcH z?6T~Oww5KaNZ)=m?&Nf@Ro=+*#BW2JH0@LncB8GSNEwDhf0lcUL4QhKmKa}wedRdA zUaJ^)42=sx*Pgie3j3ge%S%Jol$I{>hf1oJ`hVartFpYg6kFT`dz`W0$`$TP`n=Lm z?v*Q?)z$XurbAZI*4id6wq8-366!-oyKK{=42uW;_WC^@R`mPzs27fYufPZ7t)t&_ zC~7Fi|4a2dE>xDv)I*+I+B`v|+uA!PnJ01WU5$(1daLfasMT@Rja@C&+cn6j>g_dv zsJHh5P4qUFPdP)b|Jf>>Sv~|6E*ygjCl9%F0Sm{#`GZj2XMbDe9k0CKMO<;^{X8m+ zyYij`ybg$Xk5K|h@qPkGRU$VHt4d@yM3wv<4&HAaJX$>zuM3bWd2Uxxh$|pe$@8!} zRq|zkRLPeE(s-8v(s()AReFyDQYHTnN6CK)h%L_}huo=>=izj!<3{(-4qei0{RX<*1)Er;Z9i^ww<+DDQ;nnFN;eLBHVsz;43l)* zaZu@MNGf@SsN^+{#MCezw>T72rYS-`BatsG2@OFmE5!JeFNv6NbfvABs^rOK!?4S; zFWOp`#3FtBaZC3T${SJg--b46+NmJyMq5*%O1{4_=q6S2GAf3`rKMk#uG-0ESUe%G zV>0h~?p zkGRGP;JlK5bi9cmqI-EDrK5X!^V&36?boaUVAkFOq*zP#Uf&J0U;Xzh<#WHaQYLrE zr6ktHb@KxmHSly%&xs>zdqmC6*)U-KJ2f;+=VM=?f-VMQVolia@c(6{yj{lCjU0ye z9#>=6^({M@O(OQ`HN5l52$9Ny7}gXg}3yr>4}dhn636}c|~_%VES!RrDC?@BS)#AHvrP~{Tz_Sy9toS%VQK(gAaz5Q5{Vi zF$>FMEC8e$oC9w4C52-ozjc6=vI$5j|0^J+Obf7T`ad~%_d9sB8!H|UyL=u$`xyn= z)Z=usyLs0uDMD25wgymVUq;EfNwEtnzHjG{1#WVQvp{`Ku z>KEE7es%-B5nI|qx+%KrMCZQuyNR1Lkus5^@(vX z{~D6oULk6GjUy40@wmmIm^!3SOX5p1H#98cQ@$i}urJz*DQn@lUcN_pCYNG77h0Zw z0T&sE{kWx_6Sm5C){(*Az;`UI2R5-t+kV{W4pzEWPa=_aUp!ITiI}ACMq4q3-#z%z z7j5MS>5;zuxY1V3l*3Yu!B{n-Ef&Wjg(?z8jK zW7!8klQi)E>%3re4*_5p_WVG+f7akw6#mmYFWfWm|AWp8v-v;2^D+;Dt?$l@u7zUf zMe)A5^P+hFyv~c#`_JgSDCKYNyeQtmbY6-@NwD*v5XJXNsyO=SyeJ;ko)1cv4V=fcyo}Cvrx`j%&kIqY+qC(_}(oReT99{XXn0<9#+-NI5NRRaG$1UB8 z*|YPKXku}?D%heO8Z#YR{ruMHfmo9mI-;G_an2@A*5r|bxslo2A?Kg{?@dR;qZmIj z7k4qpTVFpBX3Ag#wjY41~;Xhh)LLuwqm9X>t_r*bubGibh1?_I~WxUG+IpL2_>r~!PvbK^?=to&wnS;gpcaKTlZGCNJ8bl zYKG)h*KHVv#-@8?VOk~X8&?c&=%%IQW;m}L+%O2K=vWOntFkzBZdPSQC}5E)(u7!< zOdwSjlcR-&)axV_R8m7o>P(W-+=i^&F2(}EMoE`RGdA+bR3dp;5>sR{dDy(lXqdOj zKyG8q5iFFULna)^nxxwnB>~|1Kpr9K$VBv72ekiOF7CN!b%j8J7bhWrs0kCrQ+D zu!40#Ij*|G#S?hvXA~kCI3Q(4hChDG8tyN$Z&Z^|ycDZB-+UMtb9eG0rABEAs3=>Q zP-Uq&;X3ixs1(1fl0+8Ml90Bx4{Ol*{2xEo3@VHsr zMq4OXBQ1OwD2}5L8~PoBO)S#3A2+(cP`WtgcIbuyM(P@T;<4$ImWHCHQfN3Jr4PWt zBFM7+{B!e;*JI2oifk z?^)=PeE=9@1Yg4fxVWxII0?*NxgmAL58!ZtP6RYaAa2LR-LyTfbq`z`;8|IIs6ke7 z-sXoxL2=0!caZ351-^CMcvE0@6^w1qJMgOSggSh(QG{FYmuJqHViZI(&ceN5xMVKP z<7X8z%nL&K=0K!29eEtdEA*^xQ|FL`4=l^a=0u?rG>-=75-21|ikrC0VGa+CNxB!F zJ%+$sx%MsG66<{VCx}_=Z5WU;k{VkXd5_}@z<7%<>)9;zi&YYEO#cnF>au;QW{2Her?%`Y3ldprCNwVu1H1CEPd^z%|t7 zi@`|0tQ$4}qk2RzI@LSz>Gi=#nsqXmxUYOa&-^IsuSD^!%LNJ6i5zYY336Tx6FmQ( zAHBC5-uYt>$i9J+dx;#K7R$|UtC|%4`(5}-sTvzC_)5>F#XX;rXRPad8>>38Fn87t zEN;#1#5$k!)wC%i)xT>%C|N!`_w8W#D^GPbD$E7ZTgDk*#A12d+xwj#_0*Fm!Lcn| zA`@REgTRCFn~Fnb-}UFkaC7mj$2E$g^E1))n97B?gwhG6O&wu*PW40N6Z8BuV4V-= z^r_%q`uQWO?g@rJO{qQ}{yT7`5l}o>(p!|f3+q?Y@uu(fZ$R7^U4>=`l%09uN4&Y& zzZ0gd?UcDNVU^TIun&|TVFl&YV}4vqKDX&N$jW0<;+zprv}Hf&l(<4H@g{K_&HUpj zmbVJdIF3RTcDn_eSfp(~Zgd}2y1aSeEu1d#Z2Xw8Vk;O$riP@*REV`z;~-KoU)JLm zhhoZ*aMBRtuu}&$@=iSwH$3QtRhCi+h5thQHX1N&A4Cm!JQuf1)viY+xu1E-GRfm= zNRx+g71ahf=a0ptY>p`3wMNU@WDbK~K@wvP#E?gnibMEcCm;^Zdat;1{^_0}82A=9`^3CnIo$s+O)=?Y+ z5j?OLXCT+EXJ=p#Ujc7kxFe}vqTb|Xvi1Zf;GHgTy1;1xt(^4J+KJms^U{c$H-fkU zzl0c3wXs(X#nSAe+{dJbK4#TWQ?jLvP+B0;e_k5+V{QTyk<~|Zk@Z{*ZPLS7_XxMN zaBu+s=UO>W57)q*byo(k^O}Ys=h`E=8U>(&D`62Bu&=7`(X{ zU491JAi)B@B~5weQ>}dyzTE&d~p*K#8<1WA(0HM zxX;`bl={J?^?4}1S*UhJD05VSOcaaUt1H!l?g2lY@Jb5+Bb{i1PlWV<2(Hgks=u2T zUE9j~3hGTbceOhhBlQ##U1J8kCFQ}qdjB?Z_a6KUHc2hd(O#W}sVSNo>di?kORwtKb|B}-z6k@Y@T_rHR@!Y9@2y0^# zN3ki{_X{?$et{V5$BphgN|z=aoEgN&rkzYt!&1sC?L2*{|3`(qc!%^lw8wC;{9INQdK9{`?)g(p{{ z1KEy3z#uKbECJGDk_eh!XUr;BH_{-1YsPr*t!0%cmcR*jK*p^SJeluO;OB|2B;usc?J>Bhu>zhv`Ir>PujW;*YBd;w(1ww?`)??uo zFiuCtv{gtf7AkSNkxeLHamFB?_8d?kA+#G@RZTP2%`Cipc1!K7`0D-*iLkTdTXzG$ zAZ!w?1$GLY0l8QYoHSS#13L|gMg!2XtZHIYh^Iq~&LiV{kUg43s%c8(n{RC;Bp-62 z)+;r{SO%1x`KS+0HbUpvSy-7R$!CEezY;A&PLZZ8FLt)a0uw# ztg9!*4IWBaP028Ibkj1_x@-Xd_5dp}sff$wb1272;P{EiQaCYzz`M}&NcsdnDOu03 z$e-@?ASrvW?H8&iEzDMi@5dnjq14b7*@2X7*E`!G9>qV7H-6_bhK2=k7VjOGeglm( zzA$BF?2+uv+!5ldW7jGCWxwjQ52rzSA=>e+zSR%GvA1oL#M@9Qnd^rWjGMkSb-@4W za`4PoHwmk|4!(`60kUTscdufIsOLmHHanhmxKo4)o~*sF|w{Egoa^s zP$A&lf$y+1kI33gK8J>&@ulCKiOhG-1KYL<1cOffm6cUq@Y5Xebx)x zN{6dt8FFGHI3dyj;Gz9mB zX$Vf^yo8_qbU8{|Aul{WNmA0BzvIIKkK-srRof5w)+I`$Z9i^wzfihorx|Crc#N!u z0mj4)xchziAmc>baWQJgNFyzDoZ(%dvoChM86c_DG9Bn-KpHROvoQ&~#jBVpCnBCr zsm91PUSnv=QO1DQ{)PP}pc2XR%-KPiEE#br?^X(27T{&`tPz+MX@H{2*@RPxMXd)n z;InW|*4^vj8}iu-J~cObeG1h(TBm4rwB{*Hk)`b;D#K*9B?yh#1}~u0Qo~RR0WGtI zDwL%?ZQ@&zy9>ciTYV-f%(z&$R1vk^kqAY4VFRH=xS_>K55SS=`Q~OSE~*dwA*^b% zFvWA8`J6o!5xbeQ;Hnt8Nm;tYy%ekOhG&uRY4tH*9oL~da`?K5G2aO_OiWzeSyGuc za;DJEaS+nkngB{rRSAkOF)QrT0Qm%}n?6*{x}dq4s>w;qjES)X!-*qQ60>h6v+ITgIl!ZOb7cjH<)J+ioY|tA7!1={a=XB;AHi zvo{V`Txn0@N+e2q67vC}Dpj4xa=9uu>rSRAw17PblL{Wyfl*;A`su(#fl*drUXYBH zI-T5yh#f*7qB$&?LA=)e?RLtKuyPj~3`K>$&YxlD)LzeKKr`T^x<5WY^>?^w&wx6a z>GK#|2CqGX?*r1FLD)*Y$6$68kMpXkt1khhZYvz<7C@@MUvb=cXo}*U4oR#UpXNJt zyVZgIh}0|P*8wRNB+VGdqO%^a=x_uv6!HQZCT=NrA7|VRZG9)0@Ndx4YeS=q$^|2h z@zA8-hxYbEn;r)Ze)Oc{jiaGe)4GPW4Q(CV=q)s`Iv2Akwfi=Km^ISHq64d~$-Ue0 zkuLOGZbpTuN{n~?NGPa4nrZl;WS=(i6NSh4#D7I;24XvNv$rlr2wz>8-{G(NRS)Gz@?o$Gix#d%8EZ3f(`D>7 zz(A2;^EqgR#_{0o7;5Tx@Mnly1^aa(0y{(YSZxvV9hws~x3Wl3GFl|qTU8)}h@5bW z1DEYy?+uRqI9@-8pVhlO0y@>1Ypnr#5h8x;WY%*I_N0wruvg5%UJX*ky;mFMU)w1a zTPwb)*rXl9zY*V5d~CI#ffm}U`CkJs6`>T^I?$U8NX2;$AQkp`fK;3p0a9^(Hz3w2 zkDP=2ia@;ELfxi;FA6OIq=I;Z1HA-DL;M9zQ&Yf^mf~eP5QrL^@nt{hj=)yP3y-5! zV0RyDbfb_y+%&-0w;|Q|$8xXnYS|#;*=L6vkMB6n*bzF`cwoUX#(gtJ7^kcmh_jWC zG(2tnuncHNFj9mm@v^jFq+*1w6_fe!+I<^A9V^84Vk`thu?}ls$HaJOTC^$!0x*X| zq~IpJ3O9%lcjOcSE*7GgEL!78vxV!OhPIsYAO{6zTgNP!V9P8@Bh;cj94>HW4JBvd z5J*C&UP)kCU7WnVei!ENd}N&*1_jaJTX+9^ zGdC$Kzk-eCpDW?0SJB$h(pAE7bsO%9wItkjm2lNx+gneNa4hm~(`8?NiErICkZ^W? zZ;;jBs~V{?kH-?&em(nw)U+Z9J80UKUUo-4A+ecVCn2S%Lknryn)OZcQ7ZyATU+uG z^$!K;DjdZE4y8atd9@=P6MM1j%Ws4)`tp7(vBJ`-$_Z!|m0fsQ9eb>}njG)k1Dd^& zJ$zj|LgR``yXk;b0`jB>m3CZIq7rZ`AeC%w4s-YdSoLj%FB6?+1|X!m1%jAN?gIB#vb%f)kN|_u;kr%?-aL5R<`qk zD`$|H)JM%XQCiYLrSWHYJ3iPmDu|qeS&X6h3~xb#t-4tdxnPYojE<}~dfuLnbs%WZz5EO?WE|xrJE5x9tf?oo{hbiCFo)s| zyC&Wk_90d8lJW705lUi^R~I!N*^=6l#;uk(eJ1AF6c^66RJMAO?GPFr%!6OZ_vl38 z#^_Fa_5>snXDv_{TPds?8-%EA~9603Ji%?J=1Gz?5>jcvIB~8aiN&u*onJ zuxG%gVfEf};qD7JfVZ*c>}@LA?!;F(*00(}q91_hSH9I09pH*3w_HpSD9Zzhy*Jh@ zVIu2G5NYQ(tCm(Bj*4;|35Z3QTF zf@QiRCYAuwPSKr?+Y=7d4oC&YP!zc0odeM^A3yu~t|KrM^1@?`xQ(_@TC9IcnK+I@ zWXWlQO)S#3A2+(=mG1Wj8{fkic{Ikw$6;KYj&ZRU<6=H`Tq6K01)d+TkROo71;D{1 z>=u_|rc4}SOvG6HXb88XA>59JaFelj1uK+GH!d#S*qTs*#p=v8|A1xYlxzPXDso!# zOWwei0Jd`U?xZV+TKN1$=Fr#C?|EY)j7ejH?Cce?vsbjil6&Wyp0=b`%jW8I_SjbXJc{~>>|Vg!P$V~zrY;+<^|D{-|XED8*jziL!#ZV zN-|`Lhyspo-)JY3(SXR3d<<8ZPyD*^+X;W<$CheVtFsVxA`zBQqLgRWZT7@j0C^(j zQA?ieb_RnFf9+r}KBpKLCo-qVT*svezbH*)PEqN~B+8r%na2cqB6&VYd6LUhCzI8bZ_Qzd(su(FmpaL?8O8dIl`rlv`=9Mi5BlOWxDj4aD%304s|+^<5Z|_R-t-VV&AOu=QeiFF6Ff}ic%VN zQ~;U?Kt*K@AXZh6Y(`T-N>i%3dBJlPr0IZEkd6hU0+NPj#fzI98&DML_O=6ooWX_f z_A}WLp9*>5ahABHlpk%BL(KgIVy+ZoE(c;R8)9xe#L-Cfw?;xFjf6-V36V4s=0Ntf zdMve;RgmVfc{q2M%c?)Ef2qnFJ*QvC7$i1m=E}yA$6}I3BmDViRRhhY4py!3=bs9k zB5=3BA0uJm&tDgqtBu2-?-7_GX$nK6hAcsF6R5c)a&i>A8!=Dc!^lWEE`17HJ z9_?Hh{`@dP4|UG5qwEobJykcC2kt&~%`rXEZqtO!ZAFLUwpNr14lQq9}10=r;Vc z*S!dk{REuKpb#s=d0H8UdyU}>@S8Ev7(OZ07=CJ6#gJ>uho*qLIo#!jtD5C-W2ll~ zb8VVsaF(Tq8HfRjM(z1)w+HdbRge?7+|e%_3tv}EncN*38@{f>2%Q)#32zW?+?<27 z2hFujdl5)b!N_juq;-d71EP^I4`2mzbjdCp`_n|h-76&9l7wX1j8JAgWU<66A-j8r z#0pbM87j{FUTD+ek|!j1!IW0T{Lr%L%`VS%LFG- zra7~*3NlR?r(ZlbSDW@C2f7oGH8%iAcc;VvsrVRzyeyRR9|@>LAhxv21tQxo!_R&S zq+D4C6k=IV7q`(C3I!9NWE{n2ziFOe6N|L%$BphRrOT@Xmt)yp8LKtyFjf%K(oks* zG#rr9Cz6dx*p0qorlj^WQkV9d5Z(XhjR$saAp`M@$e~b@d(n$ASVJLTW`P?V|L8{% zWa)|Ab+@Ce!T(5w6wA!Ug}!ku*QWaFC}vqMY>DQLTwKhmE2oyivWSU{2`JE7vPkL} zP|Y>?2$tN;n4lb6z#6zp&47~TY!*V85)YI#BBBB3mS@O9=~JL9HETQc_e`lSGUO1_ z=uBw~k|k+Yjn3@iKDkS{Pp%*yXAu&OxC-${^48evmS@DD+WJbA*oqfJxg%Vcmw@#X+hH`*fp1ufZQ+y+SH%e{b9zU%<>B7XL>2$;IPMs?wPx%tZQHU~OwP3%5G?BLbxY4b0=#u8e2*IZ>y0wB$EYh|gH@ep;T`o1AG0aG$ z&D_LOst~1@(oV!AeK*>QIl9wpbmADxv^7{)g-SDkYa#I1yrCS_&>T@J#1WiztjoSbIrP+(IvnC z!+}_vEei3kv$|19ZjTd&(bLB9`nW{^!V%X6V4I7*IMu|WeOuL0q<%detZFz2I&Gkn ze5j(tooSy=^ckqQr{J4HaF+sw zfI_JQ5BCBZq+j-X@Q|U0A2!T)cv?C)62Acnj+HrpUKd$D22h(o=K^|Fd=H`g``9tZwPZ@q(ehlBSQKuvu)Robh|(tqTVIYVnFu@#C2nv1PTG-^?>~i_EsANss?nQ zKsA6K5U36i>_5Qc(56wKwSZa#;%>Yh0^I`Wae+1fY8B{qK+g)a5ztntW^uDed7<*EkUvyj?k`zfUResrADX~-WoZ7=kblvVQ0Wy* z=Z6-RFBxY9fN0%Qv9z?JbbhFGfq!XfN%^wUrMxLV@%H#i95=Zrv}oC)&rf||3lTKS5^CGvf^vfcu1Vk%Dxo0tu0)%WWk~( zSNIQ!jC<|s#ffifbiD%nGg;S@_#tIf`BhoIco{0mp|nGbKxwF|;?M~ADZ|QC1S+wT z@}+3|q4K5vlJX^xgIAO;DS;3ztqj>B!fyMESNMT-&7x45zq+g%G|H}81eq!a-z7-E z-cg8@{5B+I*L)5(*+4V)$83RbEq7R9+OYzHpGLgGU<607$8E>lIZrRMwh(_00U2nD zZPreZK;i?0H2o4s9QdMNRBG@m(l2o|YbWcMIGVL1^h+Gg+8X_$nnk!`{SrsBHb=k2 z(X93B7ah&pm?85?+&P!Mz4{3JS-WO@_kIxDp53zY07k(#P_^P;hSM-8wTO+oC0KF? z1LFca7{OnojnH>54%xYlmO$UVJ7JFQhPjz{+5Mes=wVy>lvW$0PEZ(#3mRc>>N1-& z0B^M84)hN!M6eZPp5)v@5uCB^WflkBe`U_aIIZ~Ue`l5~Q}!$zt1zn(SgXlbb2ZbL zwfc6veQRYtrn|py?W;&fxN$(%YW6mKYj;bsc1x^b_^;!}NaT1mE#XRneBeAytR*7E z$OlHknGt7irhGA616+j~K4c~bXjyryQ!5E5^F4*-MjLbuanoCiovY84K|X&82aJ;o%wbyDU`Kx(X;=eTj6 z_pkV}pSO_~HJ>Tug-55jjkZumS^w-L#c>p(`RssT6N|L%$Bpg>N|#eS=$ZRqo*%qm z2zJ-=Gyt3uZUv<&N<-5Wr4UU~8V`|dOu}yQD5lkc!>)Qv8x{W_^4N(7ZiqCq0E3MjHBEXro+1W;tLgV44p4vsoHD()zXAdUpVF)SK3 z0T&d;4R>Nx&{07~&3E6Ys-Eg1&CK|||My@2b^UcE-KXn0_c^tkTAx~?YoL|}ySFG+ z#*QPd!9h|n1{oO>+l8RzbSjg4*1Kr;!wZk1e1th{a#k%~fge@TW)L;6EK;vjW;CLk zAWP<|v3?ab$MpCcJnW}WcKq8+xmG9nO)7IE~Oer`zVnZ-Cp~kOWg=ywj+^IJQ zVU)Y1<3GtM9hq|3bm)#X(2mt&SPS-BUi=Hp_lFUL%(k^7XM>iI;;4yWP{NOQ3gtH* zU(^s!s7S5y&yKaN%~N(Z;bfEYVAoZpcrtS}RuYCvu2pFu8=Y9`b=Okl7BSh!B>ZbJF^L6%DZ{I2M)Yy=kO0`kdBi6>;07GrWOF{@a;bVq*Gmi($LjQ^yP zb=DX^Ig=$}deLb*p`+budyytOJ)_;a1R|$%aO=g|cBz)8FJN(I11SlWb(mZp*FJFx z`5e%4u`??-yl91?$QuUU^V|nT9!As-ETa(pp!Y2(Rfs!5k)pDFY6Pf1p%4eXLQrZJ z{smB~ux|pz6bpKLKq+|{eg#ku)Ut#M;0Q8BRRD@YE@I0L{aTWOYX>QGtN<*JqF4dc z7jAM3jg&&?qtoRLkfR-&Rf&#h!9a*|FaTX6^>k7ivopKlMcz^b4;}}_)YF2s_cOdGk+0v_wg{#!7lfl7 z48j1U+^V;@LxQ*nx5L50iTX&70{s;G(zGO5dd)j^gE(ig!@=SniL$g17N~=TZBPWr z#1>~LmKY9Oufu?SA;+mB&G7JWcKj#qig-P!4o8(p-QE#%ZP+{)Dwz!{#Cyk*^f?GV z2!HV>S76E1J>wpIqw0#$KjSePcYNk^7et#0n2rY%ZCTc9oo)!Jw!sil=XXlQ!7a*f zWOqGKbUYRx71ic8lpU3_8)a){O?ilT>LggZM-56uc0+=w znTEcNlzJ22NP}VgJ_1gxe;T?`(gGA1XDz<{K6zAKq+s*i>Ab zFF3bV*5Mb^l`XpP;#-GpDBh+G`31EjzI}P>?L0jGAJQqhbbPdac9e!5*7YME?W|r$ z9!BC3l(Z=e&Ev_o+3^Fi_#I~6GhQY3ekeP0t(e9gtYzf*PqsX;_0mwu)5uvQJS8J` z!NZbfV(VuYwMno~lq1L1u^tX~I!UU~%CY((OkE3V%=L0&>c5Do=Ol`9O#N)C1=G={ zF3V^eXj|vo@4WaSY&^hfH);1mx1Ve5JVGPI3(!4?Lr%P0$97hSp7Hn0al;IiE{9oF zsL6vh&~Rf@OLpDE*U7Xzu6rktSn zeCT!GajWEoezs7@*3XK!g4aJMiOe|?nG$gL+4Y~|gA`|qzz}j{(S4wNGpK=>!Z>=y zadKg{U)AZ%L*mrRjRhM3&YnkhtXpl6+F)vjN}g9C(B(OpVGZVzqVC|-U9S4IKyQWs zR+L?Ij;|M^ISHRTifcxQWr^z({pV>5Cw!Y+-N6zW-%RZi+OJSw{) z7sEeER<$lV0}pgo1#2N`Ur(MPMq&RE`-pi{*t2b(`zDrEj3G9gpZCr9Lu99_LtfT_v4UD*~TT4 zd$N|>03A9+VGn}58B(!W(!*j&nJiyG{hnuZhCwSy=|0sOl+wvl>8aPaWI9`For=fE z{r7Pp7iAllOzxRV?lld(YY>+U5SPw~OMAqn3E~pEueMj`55mV0fL%A>}PoEEz2mj6ZoqP6y!~tMQdKsB8R>X<0 zSakzIJNOE=3o6hKSKyRc(C8pyZ{lktTgP``Rw}$77z{g$>Q`ZP0}izRXy)H|3^vyE z>e0nR&qRSbW>a zYyN^wEq6~qI4{<{Sz=$h41(B^_D{OO=`&cJi_V`u>IM{ooI85GL>0gCr3X0yX@UCk z6I?cNM-&#H8!t(32IJy#q%gjjo~`lC4yJS`{qCsWTMbETRCAjV5%ici55{ia59szC?76W1c~lp~WLcES ziGy2ukM6t#zZh@wu^V{!hfCQ-6-n%9ma(Rk>801BYxjULz!m&uykkeroQQ%@_GX@! zJM3U&Iu4-@&Es4TfWHe6Lyf!BJslQyY2U>mF|?pCu{<;EcN1`i1o8)e&nKJm;^pWB zpm*G`^FfZ8tNM?V-WN`#nRg20<;8DLPs4WwC(9DmJ?pFcO{>d|?>@Fh=mFbzqLbPy zwAQvpD-}K~IVMYWJBo0#N94Dk?g%1C-=@|$g#f64`$A~DAC?SjsOob(5pguDP zVJOdyOv`|d^xY?_wEP9 z9L2Hhh@zsd_Nf&<1s0F5nvJ_K)ihFy!cVV<_yw*$#k+b>&>OJ1rgv#+EwB61+FsZD zQoW1?b-c5uW5dz7dS0vimR_p?ExcAZfTL9atL_h~EOO0={}8XhG0u^5 zVW*Ldq-!@iz13+83%IJfI1QqvIx>cB#EITK*1JZejz(5)TGJgNWS-@k%VQ4bB2%%& zA6bMja)z;#3 zW7E*7pOzMz7LH9r8!&$}8Z>z1;vX*rUfqSCDqOLLW!Y)8Y()9|d`SKgnN&W13Mfuw z0=b9C()<5Hx8~y5>U|<pyTH4I5Ea4P*y=fCiLK`BGCsjkJ|C4Z`WwQ# z6kp}@Bk*8>wHRTEc}ANed?=BeQj1>yYN*$pIZ}EXjgL`I+)AU*Dm$7A6&83 zT$_SNta0!q6@2-8mN+Vnt!53MTRy)v!blIWunQP_cmdKe_VDfUxd@--^Mm*t0haRl zsh~P5<|QD3L9c>eE7TWEoxjTXg^do~#S~+!yFhSm9F+y^2Xk;ROx`De4G1W5r-2$N z6j$@8^%C3ajs>Fm~jGaPi0qMFmsCBk`uZ$5q2G9oW0a zfSyWk8u_G%N6AFE6-B-Nf;(4*_Bvd+&-zYm%ny#@>AhD zY$*0?+pV46(s0Ze^lY6Q%gP1OH={g@<oeh}>^ck7t75siKHrs~6yGqPZw9D{NSOml$(s*K@v%u%@}2{AgYdCNdK6`seO0XL zkx%t89nV#nP!xW8lf*9&#PtrNP!2~;jZB^p9yfAocoIwmt8NPLHhSWe$&(5uMOsg7 z6K*|zg4j-*_FiGZ1oCzZXN0wdb17}B@`mVI*0^5LIhciDM_B}wN9jpZ%8m8t5|93f`ack5eT^9{p;=?+#d~x? zFC4#F4Wn<@@TS%RN54Teise1RtN>%ZV2?f6#K(H!#5wLyJ1Y7u!KG}pHK>wQ+DZpd z%BH%3QZ_Xll(Nw=KHo&2Z>G=p6ewk*%YDAT`FxvvzIQ>rkN=?e89tS@eho^6fa@_; z2vU$1Dg-S+vCITz2Z8Da4uju^;>Y7Itfk+LU&hTtoRp<23O~KM;up9-)w>^WR6=<3 zQ5T1m*ZotiDY9^)|5XWAi{r&nPv!C$3hYbz?`kVrYIIXBPOy!xVH4^dqo;R_T8F@S zZ_T!~PVDKsAtVbg=8JsKzu{*f62fOfZ*U3Uf==PNyK?}@#uWzmx&r6=B`;oC3kRep z9P*I0FgyKgzHFPKL(gvIIGpET!G|hX-sae>Hp-$V(buM zvBwg8RW{3wXQjo~@M&HwMlU=eLrm^I#L*P$$S`zTJ0>s2->`0WiV%G&c!dq$9FO38 zV@xI-!m&8#u{>jAgWgQvqB{ypbOb^UH9w-Rc^!vMsKF&}Ps#22)69J=78uKl1jxdr zi#+WEwzGjc&6R_C|Y!SJg8Y z9n>RYyg|k$`(69=_&1if=tuno%mF@?|tfQCcY}js}qD zdECpIXbDa5Ow|+3LH!NoC+M{TrAlcAC{;=?2X!Hu8l#-no3d&C=TXDAJ z&e3;5Ud{aaPMWw<6`s9ll_rU)cP#mevt|8SUj5Hg(UZndb`xfG;n=#+F}zl?qME_) z1&KAesK>Zuad_6I&r!0El|D)~WtvcsP9|G%25P5xwQo^pT&wm4%b0sk8XrOJg}tw= z!outpb(bE|54xF2USlWi5OGz+I8@nK{-iI!C^|-mC|NI;J%R)YSD+sD8=116@wEMn z9Xz}Jk;+;683|H30n$g7=wMDWcizvo*@&{|OdHOPJs@M+Sd=5&$`fdtEW@l;{q|6uJrf1qV7M8Vuu5IE@It}LnCWRY}7jzbFQJZ z0BVwj37Hpr>{- znW4mMS0MpsWE6#;-WTF`bYz$>9Z|r|HIPyt;yn#}b3JjVpn7eTi=#@=Gc6?hl-YLc9ZIhanMSa*n zzfgLJ+%w-{eb9%s$Y54`7^LcxBZhB08_$(doC7L|sV3aH07@0yOF^lEI|x)jp0b)y ze5@uEU&QBQm7vmlJt&T(jH?N>D$I&vdjBBl-BPp6*5Aw%%cCe7@9)A*F3L78ncTxl zE(>#KPN(8t6wOYpR-&R zUfxkt4VM)}Xhhl9&-j0_P&Ab6;x!p6lUVz!%w(Ymqp46OJh4zT@-s5f^oK==89sPpDcdK3WnuT6br_g!hLkXNG7+Xl6#DTVI?Yx z1w+XO;S`KyvK42tf|1xN_~iigS(=>klp9BP3iE95he~P%*dfAv6zZq_)QJ~6^WKk~ zn7Qg%m}>;O)yzhiPMy77zN)VzkQqwWq?yo-v| z#FMIBnX-zEZ~bLemU&wxOEuBKd zZgNq!amnOfpybj{^ASxrBb!>SL`Bg~mFz@L(#d2iPIatBZMk$aJ09Z;s{ih`Xs+-H zdSM9X2tVkZ4(eo~FidK#_8{S^Y2I(#Av>Oh>!&wITH>RqrGM}73CLJ=@3BvaS@YLM z&Ty&=kh_559_^raAt2%sqkz-#RXHIS6MEfqV}F&K5+uHH*`g%=3wu>%an=LV)vfod#2~wPW0b@d zo#v%;9%cf=0s`-cIQLARwN@akD%k^eY+q8VcRFoX{&P2#!F#y$8=ru{pvP{mT61=YpbA;Xg?HT51j!DLSNtXL%IG zqA^;y$wk@5C6jxtlABt?OYMBJFdEs^Y9%U)MMKFZtKlS_Ot#`Y@#GZTf8NZiF@=11 zr;dMyk;`{dUz}EAnK|NLUFiud=0?=@C&2SqXy7?r zPCTZ{yZDct6X;*{oBG2wi_SlG?n#cv5BT|q7{o5)S;stqha)5mn6%Yl2_Ws1OV*a) zoA3C#qpludE;|~wQJv+vMV;ljp_HY(a&0Nk52}2z6b06+e2#@lO?bQnO07iwJE)rI z3k1E{NEda~IrsHkiC@?h2ue+iO!58h^!-?ir3$t#xVt3G43Ci-f?-e;>xBub)?kCm z12Y?VGb6`){RTAhPDPF1sB>el(F+X@*56lm zS8AEQ+}s^RkB}0iw&oy7{nCziS+7tTP0^n(`@di(attnvYBQ2TmmY-Se|5pvMg%%^ zCv!N#3`6rcKgRbS$TQe-f2C+1^WO?_#XSD`Ty%47sKlGW(!YIBS4z@r&tmpk9iFZ~ntK zo&i5)(<4ABtK~36S?x!lluiE#>LjsM5FX!Y7+2)ms-kF(H;G^1wEEs@u%i=UuZ{E5 zaDHeA=Z7}%8o!V>Mc&rCwlpPo^bs5t$}?VQRU>Fss34B8Rl+u9RwjE*UBqlK#>UD- z*DI(~4ih45$gO>nTXJY(GP5AFbI>|}uR!?CLF;*ZO(k_Q^UT~wrLT+QdFxoqc=Yke z6OcC6_(ONziQicEsE0Xt&mNk`^@jf+v!&32eTaAH&bRT2#AGI@B-e?VwEj+#)(@~` zBui`EvNbkIuFC{+%Otv-c5hOCC_9>xB6p_8Eh`gnW$hIzstFEU(sZzkfn6iCZd>66!XAvdEw+)nfiicha z63Mt(eko8COF@Y$1sV0djOjJ8avLY-<~KqqXoymP((qQA+6IjRsyg#x^+>yODb!f~ zzhL#~vaey+9NizB7tpXvVI#H1T*Vme*c9w_hLEMev7@D$x^?MG@Ef_fwW@ZNS6+ib zl7ayh&JN=E98@aMf%jjcV{<6F9NOYhu4>H07NI5hWjk(oPqGLPq8F!x?)+U4lg!bV z7b*#@cc}eAa@eKnC?p(iiLHQ2KccdV+xtzRbU5U|lH)?`gh=q#h1$G>d#fLFDsaRN4P@hGpc<0@M|3&C@PmCoTRYWen7;E;UO@LuU zvK^hjOSS)I{k;d@oqjHlGLW3njjdXW(v{G8o6&0FrKk&37};~98QX%b%zReuQl64n z$=kyFsDS7i$EK(pi>m`W7-jURz+!EBRdfk55O=QBF6AkPl`)9@h{PO--KWG7X>wH( z(wvA}hG3!g=H?$rRvq>vO^j-Lq$h8?1FX|p1I$h^vPpUZA{=3Yfg5!7k80fwgz zR(uDVW2`w)>7TjV6$jhuQ$!HjaVi+pWF9cN^ zkwNDilSa{< zLGN#%?!|x5{2MplZ?Y7XiU$kDuO)*RX(Wt%(?G|kijRW~MRAa^S`ag! zkMfO6CVR1#?Rn=Q#OXlL@yqJB8XgvIa#6N%$>jb;$>ns)fHX(;vBIomCx(LZlgU<` zEg4FtM}9*Ih)EMSB^16fI8>UPgjiCCamnOA;im~@^5#IgW2MPT;U*Vl8<$M(GMgp{ zbE52HrHPWA$VvIhWGl{=Oz%HrBa~-S?pU%_$_4P6C5$f9@#r$udaFi;+O@GoT{ghw zcXQbRVRtEvAJSbyFNvGn(aOJhWA7r|8Ovs74b!vh`p}h|0qG^yKT9gPm4BY%aN{FreZh=Tuy>WI_ zRc}v%Qq|i(K%I}|QKy>lT>YT;8~k{RbkI8vl~oUU+5(i~!$WL5;-_-2h>6iu6-C3^ zD1L$CgUC9Z$KS6;hB{|Dx+V>eYcR){eSQZwjBG199Sa87i7*%a#_wW_gH(PUGkALt z9*JsnEky({D6A?ffQ-egk?<}34>05K2OcajB+k4=&v0j9OSC2lb5=-u*}F}_BC+yR zdp5&Xbv6V0ExtzGgOKez_U3UuPCUm3FQA&p=5S^NPIJeI5N6X|Zgh~ai7qH*x7GGh zBqx)f*CT-J_@3zDA0toXbb2c*{#NGVQmCEPJ1f35C%%EJkj#2eL?MiX$jNM6r|1+| z_F?d0lV4g8X@C=lYD7}A%7b;7ZB-k3M$52XbA7O@NSnC{?EAouBCrcz*;+~Gp7FP= zd@WMHRm-Zv0c6fu3rf`99Ng}r2PKJVpc5D|k5f~^0T|2}DP)Q4P2s0n?i^66)uQn# zYBeaeVVv)}R14bJr_KbWj^F7FDugr%dW~Vi3IV9s4!?|h-8WuEf!*7#jJHKCuf_Bl zUL!0G;Dr)+CG^L4k^I4xJbR!y`QjJ8;`m15!jNCZ5AF8)F;Em^uv^6-sJ2*`ceZ?A z`@dSW@ZT;-`r_Y4qlr9a=o6#yr5_DNF&dvHjfPpSfckqA-iIv!qq(aVTa~+)s#|T< zjkescygn~B4m(_*=I|gdHf2BeIWNWQ3%P(*tIU-1iunNJ!G;(QHp8}FR3aj|vR=Xu?y-&U z6#u+9I{dusOrOWY=_(UWHOeuOmz}wB6;6XjC91E^#&wq%gz)tZuSuVS?@YOWCseXm zXvz$gyn)Yn{2P4wS9Z%}KLXqe|BbLEwdnLKka;H5%@TjqOZX8#l)0AUm036E#t$q) zg0NGJM9q!YZzJKyHM?z*vO=re@gpg@Vj{`GQ6esRhS-SmHN9QeJMzC?nmjDv4iIA-VWa5lv|*bEof zD;a5=J@^gq6^v-~v(s3~;C6CjxO5RXVN?txF zC2tcb5C1{$O?);I>LYxzamAidd@3x@TT_y`CSOTr4@y1F0i`7KlyoI|9VoRXVGAgl zSkQYHlvl#;vx)O+|huEMWv6_tty2gI+XW;sEBvtMU< z6vg4raY)+~??!})vW-h7_a`kEeb@WIx(S0toLNEnoivQYM}_2|Nm0!})fOEQqyzOB zmrTdMln(TE(jY$-@+q50I)+!FTulLypU6q>Wbzef%Q``?4&o5}ynz$`W64+HPmJlY zb-4ozdsX{X26JOQ`{c#5(30vK z-=vL2Yl>d-#nGF>DeidzYJ(c4!4}G(DPp(%WBQ2p?a6LNH4J038M#sJh?|7g5Q}ed zkG9~BA(V4aM+>Rif5$D)6;($7XMatd0;5L?E!Ms;N)pGpjlucd)# zVWWhW=plSY*M|8c5|(iKd|z_zPzNGZGEGpdTf9hdJkGW&G3aZ+9Q`F&R5yB41Y#e< zPYLP>lw8x8`9Z~8oo>mJ2eqk5kkJrR9u=hwCl~Hriy(DDm5`7w7c!vnXlwY=PB6WR z<$NHHk-h&y(7?j!MxDLlBlaj8CNN}Y`MFqHffGTg`xU~V)H2!*pwu$jLjUOu|LFoy z-2{6Vs7#?A0HqLRpw1J&a!^Y04p2(+K2VB}t->Mv!bljDYI9Bn)k&~CKqf<|F`(KB zbq6TbzT5{&wJ(o?Qtiugpw1G$-Joy@F(mV(t#qL>L8%smqjuGTuzgW22zw|kg>M$9 zQ-yk%Ple)oC>4+AK&g1V3QENTVUo6p-*kY@9Fv{CJ!rP%tghx4&!}clL@G;FS9by#L|G zg2Ks(JI8xZPP_~P9A>w8cnr=p2g;n^KNVvnbM-^<$infwdtfRQVORR7f`UomsZ$C@ zj~_F>AfG$WuguQr&x;ufro)%_NkDVa)Pit!Us44;>;MNCgn27Ozuf*jGl81gheb(y zb;pC%JvBV70Oul1n#_wUB%0%Iq@IL0|B)z9G3(c-jYGJLrt*k>UWidR2}y(yGUAD` zWeELU_5VJ-5@G)#krD#m_y0zI{rBqsfOZ-r^0Bbpl)}lyy!0by8W#QIP<(R@fx1AW zy?5+nN@_9E#)ji}aq=;4E=ujXD>CTpUD!aT7Mga9_vD+t(=f6-gR4wKTz%U7-&M46 znaor#`l`xe@(MO4Z`W8mMmL48sbGP<2>)s^YAz`Cwt=$>>TLt7J@vK$gm*JPw7bMF z=!#-N&$R{p96hxcMz=u)oi8bqv|?PwOLKcO^QCU6oxUwb*T;G_E$56?R_*K>UbC~iww$oYc+IWgl^-9cD?+V zDT*=c>%Xp!QHDw6Qku$4ctV0gr zX6adP;W*{cosWPsdbmz#-hCiSd2wIGm!PQfOPu^ZZwY=xtAe4DdqE)hw~K7Vd_7aI zOg@-|>x=7AJB!nLoPUg2ZF!_Kh6C_nJIMD&aec_{u%);r7q&ulU{)Iaw-gIVJgay@ z+(Bx+<0J&AvQ_kOy`tKsACu0D9UyVzL1Ciirmv<_deQX6BqN zP}9N-ed>OnTIExmBT(zczXqiyjoDY@$SUa7LMmMd0}9F(2hIruy&Qb1SG%`^Qb)t_ zCGSEh|D9mN3b6r{LL33r4pNM})~|FFm5K+W#jmAi=?Qss9C=$FMX@HCEZpRxY~zy2 z9k1kGRNuR3PYtgP7GSi(`ln_XU8W5<32V;TC&s*x*2j^gk`nf*bWlnk2%nR5GJT3O zFd^hkSX$E?b6+iQ#Dd!1)#K`T{WdlBn&1eaIylv{#t6^rKCu5)`bf&$g%i^EqH
%TTc=sgQQqWz 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 KmQgh#o&O&QNg*Zx literal 0 HcmV?d00001 diff --git a/odemex/Parser/CVode/setupCVode.m b/odemex/Parser/CVode/setupCVode.m new file mode 100644 index 0000000..bf31417 --- /dev/null +++ b/odemex/Parser/CVode/setupCVode.m @@ -0,0 +1,170 @@ +% This file compiles CVode for use with MATLAB + +chooseCompiler; +mkdir( [cvodeDir '/tmp'] ); + +% List of directories to include in the compilation +list = { 'cvodes' 'nvec_ser' 'sundials' }; + +% Make a list of filenames to include in the compilation +names = ''; +sourceDir = [ parserDir 'CVode/' ]; + +for q = 1 : length( list ) + fList = dir( sprintf( '%s/cv_src/src/%s/*.c', sourceDir, list{q} ) ); + + for l = 1 : length( fList ) + names = sprintf( '%s ''%s/cv_src/src/%s/%s''', names, sourceDir, list{q}, fList(l).name ); + end +end + +% for q = 1 : length( list ) +% tmp = ls( sprintf( '%s/cv_src/src/%s/*.c', sourceDir, list{q} ) ); +% % Under Windows we need to add the directory name +% % under linux this is already done. +% if ~isunix +% tmp = [ repmat( sprintf( '%s/cv_src/src/%s/', sourceDir, list{q} ), size( tmp, 1 ), 1 ), tmp, repmat( ' ', size( tmp, 1 ), 1 )]; +% end +% +% [a, b] = size(tmp); +% +% names = [ names ' ' reshape( tmp.', 1, a*b ) ]; +% end + +% Get rid of extra spaces since the compiler seems to dislike these. +nLen = 1; +len = length( names ); +while( nLen < len ) + len = nLen; + names = strrep( names, sprintf( '\n' ), ' ' ); + names = strrep( names, sprintf( '\r\n' ), ' ' ); + names = strrep( names, ' ', ' ' ); + nLen = length( names ); +end + +if ( compiler < 3 ) + % Compile the CVode source files! + eval( sprintf( 'mex -v -c -O -outdir ''%s/tmp'' -I''%s/cv_src/include/'' %s COMPFLAGS="$COMPFLAGS %s"', cvodeDir, sourceDir, names, flags ) ); +% eval( sprintf( 'mex %s -v -c -outdir ''%s/tmp'' -I''%s/cv_src/include/'' ''%s'' COMPFLAGS="$COMPFLAGS %s" "%s" "%s"', extraflags, cvodeDir, sourceDir, names, flags, lapack, blas ) ); +end + +% Bind the object code files into a library. +% To be able to do that the lib.exe needs to be +% in the system path. +disp('Generating library ...'); + +% LCCWIN32 +if compiler == 1 + disp( 'Compiler: Lcc-win32' ); + eval( sprintf( '!"%s/bin/lcclib" /OUT:"%s\\tmp\\%s" "%s\\tmp\\*.obj"', compilerLocation, cvodeDir, libraryName, cvodeDir ) ); + delete( [ cvodeDir '/tmp/*.obj' ] ); + movefile( [ cvodeDir '/tmp/*.lib' ], [ cvodeDir '/lib' ] ); + rmdir( [ cvodeDir '/tmp' ] ) +end + +% MSVC +if compiler == 2 + disp( 'Compiler: Microsoft Visual C++' ) + + curDir = pwd; + %cd( [ compilerLocation '\bin\'] ) + + p = [ sprintf( 'PATH=%s\\Common7\\IDE;%s\\VC\\BIN;%s\\Common7\\Tools;%s\\Framework\\v3.5;%s\\Framework\\v2.0.50727;%s\\VC\\VCPackages\nlib "%s\\tmp\\*.obj" /OUT:"%s\\lib\\%s"\ncd\n', vsroot, vsroot, vsroot, netroot, netroot, vsroot, curDir, curDir, libraryName ) ]; + + %fid = fopen( [ compilerLocation '\bin\mslibmaker.bat' ], 'w' ); + % fprintf( fid, '%s\n', p ); + %fclose( fid ); + + fid = fopen( [ 'mslibmaker.bat' ], 'w' ); + fprintf( fid, '%s\n', p ); + fclose( fid ); + + dos( 'mslibmaker', '-echo' ); + delete mslibmaker.bat; + + delete( [ cvodeDir '/tmp/*.obj' ] ); + rmdir( [ cvodeDir '/tmp' ] ) +end + +% GCC win +if compiler == 3 + eval( sprintf( 'mex %s -v -c -outdir ''%s/tmp'' -I''%s/cv_src/include/'' ''%s'' COMPFLAGS="$COMPFLAGS %s" "%s" "%s"', extraflags, cvodeDir, sourceDir, names, flags, lapack, blas ) ); + + clear names, tmp; + names = ''; + tmp = ls( sprintf( '%s\\tmp\\*.obj', cvodeDir ) ); + + tmp = [ repmat( sprintf( '"%s\\tmp\\', cvodeDir ), size( tmp, 1 ), 1 ), tmp, repmat( '" ', size( tmp, 1 ), 1 )]; + [a, b] = size(tmp); + names = [ names reshape( tmp.', 1, a*b ) ]; + + nLen = 1; + len = length( names ); + while( nLen < len ) + len = nLen; + names = strrep( names, ' ', ' ' ); + nLen = length( names ); + end + + if ( exist( sprintf( '%s\\lib\\%s', cvodeDir, libraryName ) ) ~= 0 ) + delete( sprintf( '%s\\lib\\%s', cvodeDir, libraryName ) ); + disp( 'Old library deleted and updated with new version' ); + end + + eval( ['!' cygwinLib 'ar cr ' sprintf( '"%s\\lib\\%s" %s', cvodeDir, libraryName, names ) ] ); + + delete( [ cvodeDir '/tmp/*.obj' ] ); + rmdir( [ cvodeDir '/tmp' ] ) + +end + +% GCC linux +if compiler == 4 + eval( strrep( strcat( sprintf( 'mex %s -v -c -outdir ''%s/tmp'' -I''%s/cv_src/include/'' %s CFLAGS="$CFLAGS -fPIC %s"', extraflags, cvodeDir, sourceDir, names, flags ) ), sprintf( '\n' ), ' ' ) ); + + clear names; + names = ''; + tmp = ls( sprintf( '%s/tmp/*.o', cvodeDir ) ); + + tmp = strrep( tmp, sprintf('\n'), ' ' ); + names = strrep( tmp, sprintf('\t'), ' ' ); + + if ( exist( sprintf( '%s/lib/%s', cvodeDir, libraryName ) ) ~= 0 ) + delete( sprintf( '%s/lib/%s', cvodeDir, libraryName ) ); + disp( 'Old library deleted and updated with new version' ); + end + ['ar cr ' sprintf( '"%s/lib/%s" %s', cvodeDir, libraryName, strrep( names, '''', '"' ) ) ] + system( ['ar cr ' sprintf( '"%s/lib/%s" %s', cvodeDir, libraryName, strrep( names, '''', '"' ) ) ] ); + + delete( [ cvodeDir '/tmp/*.o' ] ); + rmdir( [ cvodeDir '/tmp' ] ) + +end + +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Parser/CVode/setupIDA.m b/odemex/Parser/CVode/setupIDA.m new file mode 100644 index 0000000..5cd544b --- /dev/null +++ b/odemex/Parser/CVode/setupIDA.m @@ -0,0 +1,154 @@ +% This file compiles CVode for use with MATLAB + +chooseCompiler; +mkdir tmp; + +% List of directories to include in the compilation +list = { 'ida' 'nvec_ser' 'sundials' }; + +% Make a list of filenames to include in the compilation +names = ''; +for q = 1 : length( list ) + sprintf( 'ida_src/src/%s/*.c', list{q} ) + tmp = ls( sprintf( 'ida_src/src/%s/*.c', list{q} ) ); + % Under Windows we need to add the directory name + % under linux this is already done. + if ~isunix + tmp = [ repmat( sprintf( 'ida_src/src/%s/', list{q} ), size( tmp, 1 ), 1 ), tmp, repmat( ' ', size( tmp, 1 ), 1 )]; + end + + [a, b] = size(tmp); + + names = [ names ' ' reshape( tmp.', 1, a*b ) ]; +end + +% Get rid of extra spaces since the compiler seems to dislike these. +nLen = 1; +len = length( names ); +while( nLen < len ) + len = nLen; + names = strrep( names, ' ', ' ' ); + nLen = length( names ); +end + +if ( compiler < 3 ) + % Compile the CVode source files! + eval( sprintf( 'mex -v -c -O -outdir tmp -Iida_src/include/ %s COMPFLAGS="$COMPFLAGS %s"', names, flags ) ); +end + +% Bind the object code files into a library. +% To be able to do that the lib.exe needs to be +% in the system path. +disp('Generating library ...'); + +% LCCWIN32 +if compiler == 1 + disp( 'Compiler: Lcc-win32' ); + eval( sprintf( '!"%s/bin/lcclib" /OUT:tmp\\%s tmp\\*.obj', compilerLocation, idaName ) ); + delete tmp/*.obj; + movefile( 'tmp/*.lib', 'lib'); + rmdir( 'tmp' ) +end + +% MSVC +if compiler == 2 + disp( 'Compiler: Microsoft Visual C++' ) + + curDir = pwd; + cd( [ compilerLocation '\bin\'] ) + + p = [ sprintf( 'PATH=%s\\Common7\\IDE;%s\\VC\\BIN;%s\\Common7\\Tools;%s\\Framework\\v3.5;%s\\Framework\\v2.0.50727;%s\\VC\\VCPackages\nlib "%s\\tmp\\*.obj" /OUT:"%s\\lib\\%s"\ncd\n', vsroot, vsroot, vsroot, netroot, netroot, vsroot, curDir, curDir, idaName ) ]; + + fid = fopen( [ compilerLocation '\bin\mslibmaker.bat' ], 'w' ); + fprintf( fid, '%s\n', p ); + fclose( fid ); + + dos( 'mslibmaker', '-echo' ); + delete mslibmaker.bat; + + cd( curDir ); + delete tmp/*.obj; + rmdir( 'tmp' ) +end + +% GCC win +if compiler == 3 + eval( sprintf( 'mex %s -v -c -outdir tmp -Iida_src/include/ %s COMPFLAGS="$COMPFLAGS %s" "%s" "%s"', extraflags, names, flags, lapack, blas ) ); + + clear names, tmp; + names = ''; + tmp = ls( sprintf( '%s\\tmp\\*.obj', cvodeDir ) ); + + tmp = [ repmat( sprintf( '"%s\\tmp\\', cvodeDir ), size( tmp, 1 ), 1 ), tmp, repmat( '" ', size( tmp, 1 ), 1 )]; + [a, b] = size(tmp); + names = [ names reshape( tmp.', 1, a*b ) ]; + + nLen = 1; + len = length( names ); + while( nLen < len ) + len = nLen; + names = strrep( names, ' ', ' ' ); + nLen = length( names ); + end + + if ( exist( sprintf( '%s\\lib\\%s', cvodeDir, idaName ) ) ~= 0 ) + delete( sprintf( '%s\\lib\\%s', cvodeDir, idaName ) ); + disp( 'Old library deleted and updated with new version' ); + end + + eval( ['!' cygwinLib 'ar cr ' sprintf( '"%s\\lib\\%s" %s', cvodeDir, idaName, names ) ] ); + + delete tmp/*.obj; + rmdir( 'tmp' ) + +end + +% GCC linux +if compiler == 4 + + eval( strrep( strcat( sprintf( 'mex %s -v -c -outdir tmp -Iida_src/include/ %s COMPFLAGS="$COMPFLAGS %s"', extraflags, names, flags ) ), sprintf( '\n' ), ' ' ) ); + + clear names, tmp; + names = ''; + tmp = ls( sprintf( '%s/tmp/*.o', cvodeDir ) ); + + tmp = strrep( tmp, sprintf('\n'), ' ' ); + names = strrep( tmp, sprintf('\t'), ' ' ); + + if ( exist( sprintf( '%s/lib/%s', cvodeDir, idaName ) ) ~= 0 ) + delete( sprintf( '%s/lib/%s', cvodeDir, idaName ) ); + disp( 'Old library deleted and updated with new version' ); + end + system( ['ar cr ' sprintf( '"%s/lib/%s" %s', cvodeDir, idaName, names ) ] ); + + delete tmp/*.o; + rmdir( 'tmp' ) + +end +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Parser/cParserSet.m b/odemex/Parser/cParserSet.m new file mode 100644 index 0000000..801e69b --- /dev/null +++ b/odemex/Parser/cParserSet.m @@ -0,0 +1,135 @@ +% Function to set options of the parser +% +% Possible options are: +% solver Type of solver to use (* is default) +% 1 dense solver* +% 2 dense solver with LAPACK/BLAS +% 3 scaled preconditioned GMRES +% 4 preconditioned Bi-CGStab solver +% 5 preconditioned TFQMR iterative 6 solver +% 10 non-stiff problems +% +% blockSize Number of time steps to allocate each block +% when output times are not specified. +% Default: 1000 +% +% maxErrFail Maximum number of times the error criterions may +% fail within one timestep (many failures means +% long simulation time). +% Default: 15 +% +% maxConvFail Number of times the convergence of the linear +% subproblem may fail during one timestep. +% Default: 1000000 +% +% maxStep Maximum number of time steps allowed +% Default: 1000000000 +% +% nonNegative Will enforce non negativity of the solutions +% note that this amounts to reiterating a step +% whenever it is even slightly negative +% resulting in significant slowdowns +% Default: 0 (off) +% +% fixedRange Makes sure that when a dynamic time interval +% [ start finish ] is given, the end time actually +% corresponds to the specified end time. +% Default: 1 (on) +% +% aJac Use analytic Jacobian RHS for sensitivity +% calculation (experimental!!) +% +% minStep minimum stepsize (default = 1e-14) +% +% maxStepSize maximum stepsize (default = 1e14) +% +% Written by J. Vanlier +% Contact: j.vanlier@tue.nl + +function options = cParserSet( varargin ) + +inputArgs = { 'debug', 'fJac', 'aJac', 'solver', 'blockSize', 'maxErrFail', 'maxConvFail', 'maxStep', 'nonNegative', 'minStep', 'fixedRange', 'maxStepSize' }; +defaultVals = { 0, 0, 0, 1, 1000, 15, 1000000, 1000000000, 0, 1e-14, 1, 1e5 }; + +start = 1; + +if nargin == 0 + options = []; +else + try + if isa( varargin{ 1 }, 'char' ) + start = 1; + options = []; + else + if isa( varargin{ 1 }, 'struct' ) + options = varargin{1}; + start = 2; + else + disp( 'Argument one is invalid' ); + return; + end + end + catch + end +end + +if ~isempty( options ) + for a = 1 : length( inputArgs ) + try + getfield( options, inputArgs{a} ); + catch + disp( 'Invalid options structure!' ); + return; + end + end +else + for a = 1 : length( defaultVals ) + options = setfield( options, inputArgs{a}, defaultVals{a} ); + end +end + +for a = start : 2 : nargin - 1 + try + found = 0; + for b = 1 : length( inputArgs ) + if strcmp( varargin{ a }, inputArgs{ b } ) + found = 1; + end + end + if found == 1 + options = setfield( options, varargin{ a }, varargin{ a + 1 } ); + else + disp( sprintf( 'Invalid option: %s', varargin{ a } ) ) + end + catch + disp( sprintf( 'Problem setting options.' ) ) + end +end + +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Parser/compileC.m b/odemex/Parser/compileC.m new file mode 100644 index 0000000..08cd8e2 --- /dev/null +++ b/odemex/Parser/compileC.m @@ -0,0 +1,75 @@ +% This function compiles the ODE file +% +% function compileC( outputName ) +% +% Input arguments +% outputName - filename without extension that specifies the name +% of the binary. +% +% Written by J. Vanlier +% Contact: j.vanlier@tue.nl + +function compileC( outputName, IDA ) + + DAE = 0; + if nargin > 1 + if IDA == 1 + DAE = 1; + end + end + + compilerPath = fileparts( mfilename( 'fullpath' ) ); + addpath( [ compilerPath '/CVode' ] ); + tempPath = [ compilerPath '/temp' ]; + eval( 'chooseCompiler' ); + + if nargin == 0 + disp( 'Please specify an output name for the MEX file (without extension)' ); + return; + end + + if DAE == 0 + eval( 'chooseCompiler' ); + if ~isunix + eval(sprintf('mex %s COMPFLAGS="$COMPFLAGS %s" -output %s -I"%s" "%s" "%s" "%s" "%s%s"', extraflags, flags, outputName, [compilerPath '/CVode/cv_src/include'], [compilerPath '/outputC/mexG.c'], [compilerPath '/outputC/ode.c'], [compilerPath '/outputC/model/dxdt.c'], [compilerPath '/CVode/lib/'], libraryName ) ); + else + eval(sprintf('mex %s CLIBS="\\$CLIBS -L./" COMPFLAGS="\\$COMPFLAGS %s -fPIC" -output %s -I"%s" "%s" "%s" "%s" "%s%s"', extraflags, flags, outputName, [compilerPath '/CVode/cv_src/include'], [compilerPath '/outputC/mexG.c'], [compilerPath '/outputC/ode.c'], [compilerPath '/outputC/model/dxdt.c'], [compilerPath '/CVode/lib/'], libraryName ) ); + end + else + eval( 'chooseCompiler' ); + if ~isunix + eval(sprintf('mex %s COMPFLAGS="$COMPFLAGS %s" -output %s -I"%s" "%s" "%s" "%s" "%s%s"', extraflags, flags, outputName, [compilerPath '/CVode/ida_src/include'], [compilerPath '/outputC_IDA/mexG.c'], [compilerPath '/outputC_IDA/ode.c'], [compilerPath '/outputC_IDA/model/dxdt.c'], [compilerPath '/CVode/lib/'], idaName ) ); + else + eval(sprintf('mex %s COMPFLAGS="$COMPFLAGS %s -fPIC" -output %s -I"%s" "%s" "%s" "%s" "%s%s"', extraflags, flags, outputName, [compilerPath '/CVode/ida_src/include'], [compilerPath '/outputC_IDA/mexG.c'], [compilerPath '/outputC_IDA/ode.c'], [compilerPath '/outputC_IDA/model/dxdt.c'], [compilerPath '/CVode/lib/'], idaName ) ); + + end + +end + +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Parser/convertToC.m b/odemex/Parser/convertToC.m new file mode 100644 index 0000000..b775c9e --- /dev/null +++ b/odemex/Parser/convertToC.m @@ -0,0 +1,535 @@ +% M-File to C-file RHS parser +% +% function convertToC( mStruct, odeInput, dependencies, options ) +% +% Input arguments: +% mStruct - Structure containing state, parameter and input +% indices and constants in fields s p u and c +% respectively +% odeInput - Filename of main input RHS file +% dependencies - Filename of files the RHS file depends on +% (options) - This argument is optional and can be set with +% cParserSet (example: cParserSet( 'blockSize', 5000 )) +% +% ** Note that there is no support for vectors, cell arrays, structures or +% functions with more than one output argument! Also note that in order to +% take powers, use intPow( x, integer exponent ) for integer powers and +% pow( x, double exponent ). Note that the former results in a considerable +% computational improvement. +% +% Written by J. Vanlier +% Contact: j.vanlier@tue.nl + +function convertToC( mStruct, odeInput, dependencies, options ) + + parserPath = fileparts( mfilename( 'fullpath' ) ); + addpath( [ parserPath '/parserDependencies' ], '-begin' ); + + if nargin < 1 + disp( 'This file requires at least a structure with variable indices and one input filename' ); + end + + l = 'Input filenames: '; + + %% Basic input checking + if exist( odeInput ) == 0 + disp( 'Input file does not exist' ); + return; + else + l = sprintf( '%s"%s"', l, odeInput ); + end + + depNames = {}; + try + for a = 1 : length( dependencies ) + if exist( dependencies{ a } ) == 0 + disp( sprintf( 'Dependency file %s does not exist', dependencies{a} ) ); + return; + else + l = sprintf( '%s, "%s"', l, dependencies{ a } ); + [jnk b] = fileparts( dependencies{ a } ); + depNames{ a } = b; + end + end + catch + if nargin > 2 + if ~isempty( dependencies ) + disp( 'ERROR: Failure processing dependency list. Make sure it is a cell array' ); + return; + end + end + end + + disp( sprintf( '\nODE RHS m-file parser\n%s\n', l ) ); + + %% Grab parser options + fixedRange = 1; + try + fixedRange = getField( options, 'fixedRange' ); + catch + end + + try + aJac = getField( options, 'aJac' ); + catch + aJac = 0; + end + if ( aJac == 1 ) + disp( 'Evaluate sensitivity jacobian' ); + end + + try + fJac = getField( options, 'fJac' ); + catch + fJac = 0; + end + if ( fJac == 1 ) + disp( 'Evaluate jacobian' ); + end + + try + debug = getField( options, 'debug' ); + catch + debug = 0; + end + if ( debug == 1 ) + disp( '<< DEBUG MODE >>' ); + end + + try + solver = getField( options, 'solver' ); + catch + solver = 1; + end + switch solver + case 1 + disp( 'Solver: Dense' ); + case 2 + disp( 'Solver: Dense solver with MATLAB BLAS' ); + case 3 + disp( 'Solver: Scaled preconditioned GMRES' ); + case 4 + disp( 'Solver: Bi-CGStab' ); + case 5 + disp( 'Solver: TFQMR' ); + case 10 + disp( 'Solver Adams Moulton order 1-12' ); + otherwise + disp( 'ERROR: Non existant solver specified. Aborting!' ); + return; + end + + try + blockSize = getfield( options, 'blockSize' ); + catch + blockSize = 1000; + end + disp( sprintf( 'Blocksize: %d timepoints', blockSize ) ); + + try + maxErrFail = getfield( options, 'maxErrFail' ); + catch + maxErrFail = 15; + end + disp( sprintf( 'Maximum number of error test failures: %d', maxErrFail ) ); + + try + maxConvFail = getfield( options, 'maxConvFail' ); + catch + maxConvFail = 1000000; + end + disp( sprintf( 'Maximum number of convergence failures (solving linear system): %d', maxConvFail ) ); + + try + maxStep = getfield( options, 'maxStep' ); + catch + maxStep = 1000000000; + end + disp( sprintf( 'Maximum number of time steps to evaluate: %d', maxStep ) ); + + try + maxStepSize = getField( options, 'maxStepSize' ); + catch + maxStepSize = 1e14; + end + disp( sprintf( 'Maximum step size: %d', maxStepSize ) ); + + try + minStep = getField( options, 'minStep' ); + catch + minStep = 1e-14; + end + disp( sprintf( 'Minimum step size: %e', minStep ) ); + + try + nonNegative = getField( options, 'nonNegative' ); + catch + nonNegative = 0; + end + if max( nonNegative ) == 1 + if length( nonNegative ) == length( fieldnames( mStruct.s ) ) + disp( 'Enforce Non Negativity of subset of solutions' ); + else + disp( 'Warning, Non Negative list should be as long as the number of states. Ignoring Non Negativity flag.' ); + nonNegative = 0; + end + else + disp( 'Not enforcing Non Negativity of the solutions' ); + end + + %% Start declaring things we need + odeOutput = [ parserPath '/outputC/model/dxdt.c' ]; + hOutput = [ parserPath '/outputC/model/dxdtDefs.h']; + expressionTokens = '&()[]/*+-^@ %<>,;={}|'; + + try + convertables = { odeInput, dependencies{:} }; + catch + convertables = { odeInput }; + end + + % Declare and sort the states + try + [ states ] = grabFieldNames( mStruct.s ); + [ stateIndices ] = grabIndices( states, mStruct.s ); + nStates = max(cell2mat(stateIndices)); + catch + disp( 'ERROR: Input structure requires state indices' ); + end + + % Declare the parameters + try + [ parameters, parameterIndices ] = grabFieldNames( mStruct.p ); + [ parameterIndices ] = grabIndices( parameters, mStruct.p ); + nPars = max(cell2mat(parameterIndices)); + catch + disp( 'ERROR: Input structure requires parameter indices' ); + end + + % Declare the constants + try + [ constants, constantIndices ] = grabFieldNames( mStruct.c ); + [ constantIndices ] = grabIndices( constants, mStruct.c ); + catch + disp( 'No constants' ); + constants = {}; + end + + % Declare the inputs + try + [ inputs, inputIndices ] = grabFieldNames( mStruct.u ); + [ inputIndices ] = grabIndices( inputs, mStruct.u ); + catch + disp( 'No inputs' ); + inputs = {}; + end + + %% Load the files + for a = 1 : length( convertables ) + try + [ g{a} ] = textread( convertables{ a }, '%s', 'delimiter', '\n' ); + catch + disp( sprintf( 'Error! Cannot find file %s', convertables{a} ) ); + end + + % Make sure comments are turned C/C++ compatible + for b = 1 : length( g{a} ) + if findstr( g{a}{b}, '%' ) > 0 + g{a}{b} = strcat( strrep( g{a}{b}, '%', '/*' ), '*/' ); + end + end + g{a} = strrep( g{a}, '~', '!' ); + end + + % Remove all lines before function keyword + for a = 1 : length( convertables ) + b = 1; + while( 1 ) + if b > length( g{a} ) + disp( sprintf( 'Error! Function %s is missing function keyword! Aborting!\n' ), convertables{a} ); + return; + end + if ( findstr( lower( g{a}{b} ), 'function' ) ) + break; + end + g{a}(b) = []; + end + end + + % Find out what name the user used for the different vectors + [ outVars, inVars ] = analyseFunctionHeader( g{1}{1} ); + timeVar = inVars{1}; + stateVar = inVars{2}; + parVar = inVars{3}; + inVar = inVars{4}; + try + structVar = inVars{5}; + catch + disp( '*** WARNING: No structure as input argument' ); + end + outVar = outVars{1}; + + %% Replace structure references + for a = 1 : length( convertables ) + for b = 1 : length( g{a} ) + g{a}{b} = replaceStructNames( g{a}{b}, states, stateIndices, '.s' ); + g{a}{b} = replaceStructNames( g{a}{b}, parameters, parameterIndices, '.p' ); + try + g{a}{b} = replaceStructNames( g{a}{b}, inputs, inputIndices, '.u' ); + catch + end + try + g{a}{b} = replaceStructNames( g{a}{b}, constants, constantIndices, '.c' ); + catch + end + end + end + + %% Parse the file + for a = 1 : length( convertables ) + identifierLists{a} = {}; + identifierIteratorLists{a} = {}; + end + for a = 1 : length( convertables ) + for b = 2 : length( g{ a } ) + [ token, remainder, removedChars ] = strtok2( g{a}{b}, expressionTokens ); + + g{a}{b} = ''; + while( ~isempty( remainder ) || ~isempty( token ) || ~isempty( removedChars ) ) + found = 0; + + % Ignore comments + if length( removedChars ) > 1 + if ~isempty( findstr( removedChars, '//' ) ) || ~isempty( findstr( removedChars, '/*' ) ) + g{a}{b} = strcat( g{a}{b}, removedChars, token, remainder ); + break; + end + end + % Remove lines with vector stuff in them + if strcmp( token, ':' ) || strcmp( lower( token ), 'zeros' ) + disp( sprintf( 'Warning: Vectorised code detected; [%s] line ignored!', strcat( g{a}{b}, removedChars, token, remainder ) ) ); + g{a}{b} = ''; + break; + end + if ~isempty( str2num( token ) ) + found = 1; + end + if strcmp( token, 'for' ) + [ itervar, remainder, removedChars ] = strtok2( remainder, expressionTokens ); + [ iterstart, remainder, removedChars ] = strtok2( remainder, expressionTokens ); + [ dummy, remainder, removedChars ] = strtok2( remainder, expressionTokens ); + [ iterend, remainder, removedChars ] = strtok2( remainder, expressionTokens ); + + str = sprintf('for(%s=%s;%s<=%s;%s++){',itervar,(iterstart),itervar,(iterend),itervar); + identifierIteratorLists{a} = { identifierIteratorLists{a}{:}, itervar }; + g{a}{b} = str; + token = ''; + found = 1; + end + if strcmp( token, 'if' ) + remainder = sprintf( '%s{', remainder ); + found = 1; + end + if strcmp( token, 'else' ); + token = sprintf( '} else {', g{a}{b} ); + found = 1; + end + if strcmp( token, 'end' ); + token = '}'; + found = 1; + end + if strcmp( token, timeVar ) + found = 1; + end + if strcmp( lower(token), lower(depNames) ) + found = 1; + end + if strcmp( token, stateVar ) | strcmp( token, parVar ) | strcmp( token, inVar ) | strcmp( token, outVar ) + % Only process assignments + tmp = strtok( remainder, ' ' ); + if strcmp( tmp(1), '(' ) + if strcmp( token, stateVar ) token = 'stateVars'; end; + if strcmp( token, parVar ) token = 'data->p'; end; + if strcmp( token, inVar ) token = 'data->u'; end; + if strcmp( token, outVar ) token = 'ydots'; end; + [ cal, remainder ] = grabBetweenBrackets( remainder ); + cal = dec1( cal ); + token = sprintf( '%s', token ); + remainder = sprintf( '[%s]%s', cal, remainder ); + found = 1; + end + end + + if strcmp( token, 'cell' ) | ( ( ( exist( token ) == 0 ) | ( exist( token ) == 1 ) ) && ( found == 0 ) ) + if ~isempty( strtok( token ) ) + ignoreToken = 0; + for i = 1 : numel(identifierIteratorLists{a}) + if strcmp(token,identifierIteratorLists{a}{i}) == 1 + ignoreToken = 1; + end + end + if ignoreToken == 0 + identifierLists{a} = { identifierLists{a}{:}, token }; + end + end + end + g{a}{b} = strcat( g{a}{b}, removedChars, token ); + [ token, remainder, removedChars ] = strtok2( remainder, expressionTokens ); + + % Modified by Mario Bortolozzi and Joep Vanlier + %if found == 0, + % if ( ( exist( token, 'var' ) == 0 ) || ( exist( token, 'var' ) == 1 ) ), + % if ~isempty( strtok( token ) ) +% % identifierLists{a} = { token }; + % identifierLists{a} = { identifierLists{a}{:}, token }; + % end + % end + %end + %g{a}{b} = strcat( g{a}{b}, removedChars, token ); + %[ token, remainder, removedChars ] = strtok2( remainder, expressionTokens ); + + end + end + end + + %% Start generating the right hand side file + c = 1; + l = ''; + + l = sprintf( '#include "../dxdt.h"\n\n' ); + + for a = 2 : length( convertables ) + [ outVars, inVars, funcName ] = analyseFunctionHeader( g{a}{1} ); + identifierLists{a} = { identifierLists{a}{:}, outVars{:} }; + + if length( outVars ) == 1 + % Print the function header + l = sprintf( '%srealtype %s( %s ) {\n\n', l, funcName, printList( inVars, 'realtype ' ) ); + + % Print the list of identifiers + l = sprintf( '%s\t%s;\n', l, printUniqueList( identifierLists{a}, inVars ) ); + + % Print the list of iterator identifiers + l = sprintf( '%s\t%s;\n', l, printUniqueList( identifierIteratorLists{a}, inVars, 'int' ) ); + + % Print the rest of the file + for b = 2 : length( g{a} ) + l = sprintf( '%s\t%s\n', l, g{a}{b} ); + end + l = sprintf( '%s\treturn %s;\n\n}\n\n', l, outVars{ 1 } ); + end + end + + % Print RHS function header + l = sprintf( '%s\n\nint rhs( realtype t, N_Vector y, N_Vector ydot, void *f_data ) {\n\n\tstruct mData *data = ( struct mData * ) f_data;\n\n', l ); + + % Print the list of identifiers + l = sprintf( '%s\t%s;\n', l, printUniqueList( identifierLists{1} ) ); + if numel(identifierIteratorLists{1}) > 0, l = sprintf( '%s\t%s;\n', l, printUniqueList( identifierIteratorLists{1},{},'int' ) ); end; + + % Fetch variables + l = sprintf( '%s\n\trealtype *stateVars;', l ); + l = sprintf( '%s\n\trealtype *ydots;\n', l ); + + l = sprintf( '%s\n\tstateVars = NV_DATA_S(y);\n', l ); + l = sprintf( '%s\tydots = NV_DATA_S(ydot);\n\n', l ); + + % Print the rest of the file + for b = 2 : length( g{1} ) + l = sprintf( '%s\t%s\n', l, g{1}{b} ); + end + + l = sprintf( '%s\n\n\t#ifdef NON_NEGATIVE\n\t\treturn', l ); + + if max( nonNegative ) == 1 + for a = 1 : length( states ) - 1 + if nonNegative( a ) == 1 + l = sprintf( '%s ( stateVars[%d] < 0.0f ) || ', l, a - 1 ); + end + end + if nonNegative( length( states ) ) == 1 + l = sprintf( '%s ( stateVars[%d] < 0.0f )', l, length( states ) - 1 ); + end + else + l = sprintf( '%s 0', l ); + end + + l = sprintf( '%s;\n\t#else\n\t\treturn 0;\n\t#endif\n\n};\n', l ); + + mz = 0; + try + for a = 1 : length( inputIndices ) + mz = max( [ mz, max( inputIndices{a} ) ] ); + end + catch + end + + if ( ( aJac == 1 ) | ( fJac == 1 ) ) + disp( 'Generating Jacobian information' ); + jacGen1; + l = [ l sensRHS ]; + end + + %if aJac == 1 + % s = sprintf( '\n#define AJAC\n#define N_STATES %d\n#define N_PARAMS %d\n#define N_INPUTS %d\n#define SOLVER %d\n#define BLOCK_SIZE %d\n\n#define MAX_CONV_FAIL %d\n#define MAX_STEPS %d\n#define MAX_ERRFAILS %d\n#define MIN_STEPSIZE %.30f\n#define MAX_STEPSIZE %.30f\n\n', max( cell2mat( stateIndices ) ), max( cell2mat( parameterIndices ) ), mz, solver, blockSize, maxConvFail, maxStep, maxErrFail, minStep, maxStepSize ); + %else + s = sprintf( '\n#define N_STATES %d\n#define N_PARAMS %d\n#define N_INPUTS %d\n#define SOLVER %d\n#define BLOCK_SIZE %d\n\n#define MAX_CONV_FAIL %d\n#define MAX_STEPS %d\n#define MAX_ERRFAILS %d\n#define MIN_STEPSIZE %.30f\n#define MAX_STEPSIZE %.30f\n\n', max( cell2mat( stateIndices ) ), max( cell2mat( parameterIndices ) ), mz, solver, blockSize, maxConvFail, maxStep, maxErrFail, minStep, maxStepSize ); + %end + + if aJac == 1 + s = sprintf( '%s#define AJAC\n', s ); + end + + if fJac == 1 + s = sprintf( '%s#define FJAC\n', s ); + end + + if debug == 1 + s = sprintf( '%s#define DEBUG\n', s ); + end + + if max( nonNegative ) == 1 + s = sprintf( '%s#define NON_NEGATIVE\n', s ); + end + if fixedRange == 1 + s = sprintf( '%s#define FIXEDRANGE\n', s ); + end + + fid = fopen( odeOutput, 'w' ); + fprintf( fid, '%s\n', l ); + fclose( fid ); + + fid = fopen( hOutput, 'w' ); + fprintf( fid, '%s\n', s ); + fclose( fid ); + + disp( 'Files generated!' ); + + +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Parser/convertToC_IDA.m b/odemex/Parser/convertToC_IDA.m new file mode 100644 index 0000000..b7418da --- /dev/null +++ b/odemex/Parser/convertToC_IDA.m @@ -0,0 +1,445 @@ +% M-File to C-file RHS parser +% +% function convertToC_IDA( mStruct, odeInput, dependencies, options ) +% +% Input arguments: +% mStruct - Structure containing state, parameter and input +% indices and constants in fields s p u and c +% respectively +% odeInput - Filename of main input RHS file +% dependencies - Filename of files the RHS file depends on +% (options) - This argument is optional and can be set with +% cParserSet (example: cParserSet( 'blockSize', 5000 )) +% +% ** Note that there is no support for vectors, cell arrays, structures or +% functions with more than one output argument! Also note that in order to +% take powers, use intPow( x, integer exponent ) for integer powers and +% pow( x, double exponent ). Note that the former results in a considerable +% computational improvement. +% +% Written by J. Vanlier +% Contact: j.vanlier@tue.nl + +function convertToC( mStruct, odeInput, dependencies, options, M ) + + parserPath = fileparts( mfilename( 'fullpath' ) ); + addpath( [ parserPath '/parserDependencies' ], '-begin' ); + + if nargin < 1 + disp( 'This file requires at least a structure with variable indices and one input filename' ); + end + + l = 'Input filenames: '; + + if nargin < 5 + M = eye( length(fieldnames(mStruct.s)) ); + end + + %% Basic input checking + if exist( odeInput ) == 0 + disp( 'Input file does not exist' ); + return; + else + l = sprintf( '%s"%s"', l, odeInput ); + end + + depNames = {}; + try + for a = 1 : length( dependencies ) + if exist( dependencies{ a } ) == 0 + disp( sprintf( 'Dependency file %s does not exist', dependencies{a} ) ); + return; + else + l = sprintf( '%s, "%s"', l, dependencies{ a } ); + [jnk b] = fileparts( dependencies{ a } ); + depNames{ a } = b; + end + end + catch + if nargin > 2 + if ~isempty( dependencies ) + disp( 'ERROR: Failure processing dependency list. Make sure it is a cell array' ); + return; + end + end + end + + disp( sprintf( '\nODE RHS m-file parser\n%s\n', l ) ); + + %% Grab parser options + try + solver = getField( options, 'solver' ); + catch + solver = 1; + end + switch solver + case 1 + disp( 'Solver: Dense' ); + case 2 + disp( 'Solver: Dense solver with MATLAB BLAS' ); + case 3 + disp( 'Solver: Scaled preconditioned GMRES' ); + case 4 + disp( 'Solver: Bi-CGStab' ); + case 5 + disp( 'Solver: TFQMR' ); + case 10 + disp( 'Solver Adams Moulton order 1-12' ); + otherwise + disp( 'ERROR: Non existant solver specified. Aborting!' ); + return; + end + + try + blockSize = getfield( options, 'blockSize' ); + catch + blockSize = 1000; + end + disp( sprintf( 'Blocksize: %d timepoints', blockSize ) ); + + try + maxErrFail = getfield( options, 'maxErrFail' ); + catch + maxErrFail = 15; + end + disp( sprintf( 'Maximum number of error test failures: %d', maxErrFail ) ); + + try + maxConvFail = getfield( options, 'maxConvFail' ); + catch + maxConvFail = 1000000; + end + disp( sprintf( 'Maximum number of convergence failures (solving linear system): %d', maxConvFail ) ); + + try + maxStep = getfield( options, 'maxStep' ); + catch + maxStep = 1000000000; + end + disp( sprintf( 'Maximum number of time steps to evaluate: %d', maxStep ) ); + + try + minStep = getField( options, 'minStep' ); + catch + minStep = 1e-14; + end + disp( sprintf( 'Minimum step size: %e', minStep ) ); + + try + nonNegative = getField( options, 'nonNegative' ); + catch + nonNegative = 0; + end + if max( nonNegative ) == 1 + if length( nonNegative ) == length( fieldnames( mStruct.s ) ) + disp( 'Enforce Non Negativity of subset of solutions' ); + else + disp( 'Warning, Non Negative list should be as long as the number of states. Ignoring Non Negativity flag.' ); + nonNegative = 0; + end + else + disp( 'Not enforcing Non Negativity of the solutions' ); + end + + %% Start declaring things we need + + odeOutput = [ parserPath '/outputC_IDA/model/dxdt.c' ]; + hOutput = [ parserPath '/outputC_IDA/model/dxdtDefs.h' ]; + expressionTokens = '()[]/*+-^@ %<>,;={}'; + + try + convertables = { odeInput, dependencies{:} }; + catch + convertables = { odeInput }; + end + + % Declare and sort the states + try + [ states ] = grabFieldNames( mStruct.s ); + [ stateIndices ] = grabIndices( states, mStruct.s ); + catch + disp( 'ERROR: Input structure requires state indices' ); + end + + % Declare the parameters + try + [ parameters, parameterIndices ] = grabFieldNames( mStruct.p ); + [ parameterIndices ] = grabIndices( parameters, mStruct.p ); + catch + disp( 'ERROR: Input structure requires parameter indices' ); + end + + % Declare the constants + try + [ constants, constantIndices ] = grabFieldNames( mStruct.c ); + [ constantIndices ] = grabIndices( constants, mStruct.c ); + catch + disp( 'No constants' ); + constants = {}; + end + + % Declare the inputs + try + [ inputs, inputIndices ] = grabFieldNames( mStruct.u ); + [ inputIndices ] = grabIndices( inputs, mStruct.u ); + catch + disp( 'No inputs' ); + inputs = {}; + end + + % Currently the number of equations equals the number of states + nEqs = length( states ); + + %% Load the files + for a = 1 : length( convertables ) + try + [ g{a} ] = textread( convertables{ a }, '%s', 'delimiter', '\n' ); + catch + disp( sprintf( 'Error! Cannot find file %s', convertables{a} ) ); + end + + % Make sure comments are turned C/C++ compatible + for b = 1 : length( g{a} ) + if findstr( g{a}{b}, '%' ) > 0 + g{a}{b} = strcat( strrep( g{a}{b}, '%', '/*' ), '*/' ); + end + end + g{a} = strrep( g{a}, '~', '!' ); + end + + % Remove all lines before function keyword + for a = 1 : length( convertables ) + b = 1; + while( 1 ) + if b > length( g{a} ) + disp( sprintf( 'Error! Function %s is missing function keyword! Aborting!\n' ), convertables{a} ); + return; + end + if ( findstr( lower( g{a}{b} ), 'function' ) ) + break; + end + g{a}(b) = []; + end + end + + % Find out what name the user used for the different vectors + [ outVars, inVars ] = analyseFunctionHeader( g{1}{1} ); + timeVar = inVars{1}; + stateVar = inVars{2}; + parVar = inVars{3}; + inVar = inVars{4}; + outVar = outVars{1}; + + %% Replace structure references + for a = 1 : length( convertables ) + for b = 1 : length( g{a} ) + g{a}{b} = replaceStructNames( g{a}{b}, states, stateIndices, '.s' ); + g{a}{b} = replaceStructNames( g{a}{b}, parameters, parameterIndices, '.p' ); + try + g{a}{b} = replaceStructNames( g{a}{b}, inputs, inputIndices, '.u' ); + catch + end + try + g{a}{b} = replaceStructNames( g{a}{b}, constants, constantIndices, '.c' ); + catch + end + end + end + + %% Parse the file + identifierLists = {{}, {}}; + + for a = 1 : length( convertables ) + for b = 2 : length( g{ a } ) + [ token, remainder, removedChars ] = strtok2( g{a}{b}, expressionTokens ); + g{a}{b} = ''; + while( ~isempty( remainder ) || ~isempty( token ) || ~isempty( removedChars ) ) + found = 0; + + % Ignore comments + if length( removedChars ) > 1 + if ~isempty( findstr( removedChars, '//' ) ) || ~isempty( findstr( removedChars, '/*' ) ) + g{a}{b} = strcat( g{a}{b}, removedChars, token, remainder ); + break; + end + end + % Remove lines with vector stuff in them + if strcmp( token, ':' ) || strcmp( lower( token ), 'zeros' ) + disp( sprintf( 'Warning: Vectorised code detected; [%s] line ignored!', strcat( g{a}{b}, removedChars, token, remainder ) ) ); + g{a}{b} = ''; + break; + end + if ~isempty( str2num( token ) ) + found = 1; + end + if strcmp( token, 'if' ) + remainder = sprintf( '%s{', remainder ); + found = 1; + end + if strcmp( token, 'else' ); + token = sprintf( '} else {', g{a}{b} ); + found = 1; + end + if strcmp( token, 'end' ); + token = '}'; + found = 1; + end + if strcmp( token, timeVar ) + found = 1; + end + if strcmp( lower(token), lower(depNames) ) + found = 1; + end + if strcmp( token, stateVar ) | strcmp( token, parVar ) | strcmp( token, inVar ) | strcmp( token, outVar ) + % Only process assignments + tmp = strtok( remainder, ' ' ); + if strcmp( tmp(1), '(' ) + if strcmp( token, stateVar ) token = 'stateVars'; end; + if strcmp( token, parVar ) token = 'data->p'; end; + if strcmp( token, inVar ) token = 'data->u'; end; + if strcmp( token, outVar ) token = 'dEqs'; end; + [ cal, remainder ] = grabBetweenBrackets( remainder ); + cal = dec1( cal ); + token = sprintf( '%s', token ); + remainder = sprintf( '[%s]%s', cal, remainder ); + found = 1; + end + end + if strcmp( token, 'cell' ) |( ( ( exist( token ) == 0 ) | ( exist( token ) == 1 ) ) && ( found == 0 ) ) + if ~isempty( token ) + identifierLists{a} = { identifierLists{a}{:}, token }; + end + end + g{a}{b} = strcat( g{a}{b}, removedChars, token ); + [ token, remainder, removedChars ] = strtok2( remainder, expressionTokens ); + end + end + end + + %% Start generating the right hand side file + c = 1; + l = ''; + + l = sprintf( '#include "../dxdt.h"\n\n' ); + + for a = 2 : length( convertables ) + [ outVars, inVars, funcName ] = analyseFunctionHeader( g{a}{1} ); + identifierLists{a} = { identifierLists{a}{:}, outVars{:} }; + + if length( outVars ) == 1 + % Print the function header + l = sprintf( '%srealtype %s( %s ) {\n\n', l, funcName, printList( inVars, 'realtype ' ) ); + + % Print the list of identifiers + l = sprintf( '%s\t%s;\n', l, printUniqueList( identifierLists{a}, inVars ) ); + + % Print the rest of the file + for b = 2 : length( g{a} ) + l = sprintf( '%s\t%s\n', l, g{a}{b} ); + end + l = sprintf( '%s\treturn %s;\n\n}\n\n', l, outVars{ 1 } ); + end + end + + % Print RHS function header + l = sprintf( '%s\n\nint rhs( realtype t, N_Vector y, N_Vector ydot, N_Vector resid, void *f_data ) {\n\n\tstruct mData *data = ( struct mData * ) f_data;\n\n', l ); + + % Print the list of identifiers + l = sprintf( '%s\t%s;', l, printUniqueList( identifierLists{1} ) ); + + % Fetch variables + l = sprintf( '%s\n\trealtype *stateVars;', l ); + l = sprintf( '%s\n\trealtype *ydots;\n', l ); + l = sprintf( '%s\n\trealtype *resids;\n', l ); + l = sprintf( '%s\trealtype\tdEqs[%d];\n', l, nEqs ); + + % Make a list of derivative variables + l = sprintf( '%s\n\tstateVars = NV_DATA_S(y);', l ); + l = sprintf( '%s\n\tydots = NV_DATA_S(ydot);\n', l ); + l = sprintf( '%s\n\tresids = NV_DATA_S(resid);\n', l ); + + % Print the rest of the file + for b = 2 : length( g{1} ) + l = sprintf( '%s\t%s\n', l, g{1}{b} ); + end + + % Build up the residual vector using the mass matrix + for b = 1 : length( M ) + z = ''; + for c = 1 : length( M ) + if M( b, c ) ~= 0 + z = sprintf( '%s + %d * ydots[%d]', z, M( b, c ), c - 1 ); + end + end + l = sprintf( '%s\n\tresids[%d] = %s - dEqs[%d];', l, b - 1, z, b - 1 ); + end + + l = sprintf( '%s\n\n\t#ifdef NON_NEGATIVE\n\t\treturn', l ); + + if max( nonNegative ) == 1 + for a = 1 : length( states ) - 1 + if nonNegative( a ) == 1 + l = sprintf( '%s ( stateVars[%d] < 0.0f ) || ', l, a - 1 ); + end + end + if nonNegative( length( states ) ) == 1 + l = sprintf( '%s ( stateVars[%d] < 0.0f )', l, length( states ) - 1 ); + end + else + l = sprintf( '%s 0', l ); + end + + l = sprintf( '%s;\n\t#else\n\t\treturn 0;\n\t#endif\n\n};\n', l ); + + mz = 0; + try + for a = 1 : length( inputIndices ) + mz = max( [ mz, max( inputIndices{a} ) ] ); + end + catch + end + + s = sprintf( '\n#define N_STATES %d\n#define N_PARAMS %d\n#define N_INPUTS %d\n#define SOLVER %d\n#define BLOCK_SIZE %d\n\n#define MAX_CONV_FAIL %d\n#define MAX_STEPS %d\n#define MAX_ERRFAILS %d\n#define MIN_STEPSIZE %.30f\n\n', length( states ), length( parameters ), mz, solver, blockSize, maxConvFail, maxStep, maxErrFail, minStep ); + + if max( nonNegative ) == 1 + s = sprintf( '%s#define NON_NEGATIVE\n', s ); + end + + fid = fopen( odeOutput, 'w' ); + fprintf( fid, '%s\n', l ); + fclose( fid ); + + fid = fopen( hOutput, 'w' ); + fprintf( fid, '%s\n', s ); + fclose( fid ); + + disp( 'Files generated!' ); + + +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Parser/outputC/dxdt.h b/odemex/Parser/outputC/dxdt.h new file mode 100644 index 0000000..3fdaddd --- /dev/null +++ b/odemex/Parser/outputC/dxdt.h @@ -0,0 +1,40 @@ +/* + Joep Vanlier, 2011 + + Licensing: + Copyright (C) 2009-2011 Joep Vanlier. All rights + reserved. + + Contact:joep.vanlier@gmail.com + + This file is part of the puaMAT. + + puaMAT is free software: you can redistribute it + and/or modify it under the terms of the GNU General + Public License as published by the Free Software + Foundation, either version 3 of the License, or (at + your option) any later version. + + puaMAT is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A + PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General + Public License along with puaMAT. If not, see + http://www.gnu.org/licenses/ +*/ +#include "ode.h" +#include "model/dxdtDefs.h" + +#ifndef _DXDT_H_ +#define _DXDT_H_ + +#define realtype double + +int rhs(realtype t, N_Vector y, N_Vector ydot, void *f_data); +int sensRhs (int Ns, realtype t, N_Vector y, N_Vector ydot, N_Vector *yS, N_Vector *ySdot, void *user_data, N_Vector tmp1, N_Vector tmp2); +int fJac(long int N, realtype t, N_Vector y, N_Vector fy, DlsMat Jac, void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +#endif diff --git a/odemex/Parser/outputC/mexG.c b/odemex/Parser/outputC/mexG.c new file mode 100644 index 0000000..2d18bad --- /dev/null +++ b/odemex/Parser/outputC/mexG.c @@ -0,0 +1,473 @@ +/* + Joep Vanlier, 2011 + + Licensing: + Copyright (C) 2009-2011 Joep Vanlier. All rights + reserved. + + Contact:joep.vanlier@gmail.com + + This file is part of the puaMAT. + + puaMAT is free software: you can redistribute it + and/or modify it under the terms of the GNU General + Public License as published by the Free Software + Foundation, either version 3 of the License, or (at + your option) any later version. + + puaMAT is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A + PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General + Public License along with puaMAT. If not, see + http://www.gnu.org/licenses/ +*/ +#include "ode.h" +#include "dxdt.h" +#include "time.h" +#include "string.h" + +const int numInputArgs = 5; +const int numOutputArgs = 1; + +void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { + + time_t tStart, tEnd; + struct mVector t; + struct mVector tol; + struct mData data; + int k, p, q, ind; + int nBlocks; + realtype t0; + realtype y[ N_STATES ]; + realtype *yOutput; + realtype *tOutput; + int mSize; + + int sensitivity; + double *sensitivities; + double *sensitivityOutputs; + double *tols; + unsigned int sensitivityBlock; + size_t sensitivityBlockSize; + int *sParList; + + /* Structures required for CVode */ + int flag; + N_Vector y0 = NULL; + N_Vector *yS0 = NULL; + void *cvode_mem = NULL; + void *pData = NULL; + realtype tret; + + /* Function pointer for the RHS */ + int (*f)(realtype t, N_Vector y, N_Vector ydot, void *f_data) = &rhs; + + /* Function pointer for the analytic jacobian of the right hand side */ + #ifdef AJAC + int (*g)(int Ns, realtype t, N_Vector y, N_Vector ydot, N_Vector *yS, N_Vector *ySdot, void *user_data, N_Vector tmp1, N_Vector tmp2) = &sensRhs; + #endif + + #ifdef FJAC + int (*fj)(long int N, realtype t, N_Vector y, N_Vector fy, DlsMat Jac, void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) = &fJac; + #endif + + if (nrhs == 0) { + printf( "Call function as:\ny = funcName(t, y0[%d], p[%d], u[%d], [reltol, abstol, maxtime])\n", N_STATES, N_PARAMS, N_INPUTS ); + return; + } + + if ( nrhs < numInputArgs ) mexErrMsgTxt( "ERROR: Incorrect number of input arguments\nFormat should be: (t, y0, x, u, [reltol, abstol, max_integration_time], sensitivity*)\n* are optional" ); + + /* Check input dimensions */ + if ( mxGetNumberOfElements( prhs[1] ) != N_STATES ) { + printf( "ERROR: Initial condition vector has incorrect length! Expected %d, found %d", N_STATES, mxGetNumberOfElements( prhs[1] ) ); + mexErrMsgTxt( "" ); + } + if ( mxGetNumberOfElements( prhs[2] ) != N_PARAMS ) { + printf( "ERROR: Parameter vector has incorrect length! Expected %d, found %d", N_PARAMS, mxGetNumberOfElements( prhs[2] ) ); + mexErrMsgTxt( "" ); + } + if ( mxGetNumberOfElements( prhs[3] ) != N_INPUTS ) { + printf( "ERROR: Input vector has incorrect length! Expected %d, found %d", N_INPUTS, mxGetNumberOfElements( prhs[3] ) ); + mexErrMsgTxt( "" ); + } + if ( mxGetNumberOfElements( prhs[4] ) != 3 ) { + mexErrMsgTxt( "ERROR: Tolerance vector should be of the form [ relative tolerance, absolute tolerance, maximal time allowed for integration in seconds ]" ); + } + + /* Grab vectors for own use from MATLAB */ + grabVectorFromMatlab( &t, prhs[0] ); + grabVectorFromMatlab( &tol, prhs[4] ); + + if ( t.length < 1 ) + mexErrMsgTxt( "ERROR: Time vector should be at least one element. Either provide a single time to obtain a single value at time t, a begin and end time if the solver is allowed to determine the timesteps or a series of timepoints at which to compute the solution." ); + + sensitivity = 0; + if ( nrhs > 5 ) { + if ( t.length < 3 ) { + mexErrMsgTxt( "ERROR: Sensitivity analysis is currently only supported for fixed time vector problems. Please supply a time vector longer than 2." ); + } else { + if ( nlhs > 2 ) { + if ( nrhs < 7 ) + { + /* Include sensitivity analysis */ + sensitivity = *mxGetPr( prhs[5] ); + } else { + if ( mxGetNumberOfElements( prhs[6] ) < ( N_STATES + N_PARAMS ) * N_STATES ) + mexErrMsgTxt( "Initial condition vector for sensitivity analysis is of incorrect length!" ); + else + sensitivity = *mxGetPr( prhs[5] ); + } + } else mexErrMsgTxt( "Sensitivity analysis requires 3 outputs" ); + } + } + + if ( prhs[3] != NULL ) + data.u = mxGetPr( prhs[3] ); + else + data.u = NULL; + + if ( sensitivity == 0 ) { + /* Set parameter pointer to matlab structure */ + data.p = mxGetPr( prhs[2] ); + /* Copy initial condition to local structure */ + memcpy( y, mxGetPr( prhs[1] ), sizeof( realtype ) * mxGetNumberOfElements( prhs[1] ) ); + y0 = N_VMake_Serial( N_STATES, y ); /* Warning, realtype has to be double for this */ + } else { + /* Allocate memory for the parameters and initial conditions */ + data.p = malloc( sizeof( realtype ) * ( N_STATES + N_PARAMS ) ); + /* Copy parameters to local structure */ + memcpy( &data.p[0], mxGetPr( prhs[2] ), sizeof( realtype ) * mxGetNumberOfElements( prhs[2] ) ); + /* Copy initial conditions to local structure */ + memcpy( &data.p[N_PARAMS], mxGetPr( prhs[1] ), sizeof( realtype ) * mxGetNumberOfElements( prhs[1] ) ); + /* Set initial condition pointer to appropriate address */ + y0 = N_VMake_Serial( N_STATES, &data.p[N_PARAMS] ); /* Warning, realtype has to be double for this */ + } + + /* Set begin time */ + if ( t.length == 1 ) + t0 = 0.0; + else + t0 = t.val[0]; + + /* Start up CVode */ + #if SOLVER < 10 + cvode_mem = CVodeCreate( CV_BDF, CV_NEWTON ); + #else + cvode_mem = CVodeCreate( CV_ADAMS, CV_FUNCTIONAL ); + #endif + + + /* Initialise CVode */ + if ( CVodeInit( cvode_mem, f, t0, y0 ) != CV_SUCCESS ) { + N_VDestroy_Serial( y0 ); + mexErrMsgTxt( "ERROR: Failed to initialise CVode" ); + } + + /* Specify tolerances */ + if ( CVodeSStolerances( cvode_mem, tol.val[0], tol.val[1] ) != CV_SUCCESS ) { + N_VDestroy_Serial( y0 ); + CVodeFree( &cvode_mem ); + mexErrMsgTxt( "ERROR: Failed to set tolerances" ); + } + + CVodeSetMaxStep( cvode_mem, MAX_STEPSIZE ); + CVodeSetMinStep( cvode_mem, MIN_STEPSIZE ); + CVodeSetMaxConvFails( cvode_mem, MAX_CONV_FAIL ); + CVodeSetMaxNumSteps( cvode_mem, MAX_STEPS ); + CVodeSetMaxErrTestFails( cvode_mem, MAX_ERRFAILS ); + CVodeSetMaxTime( cvode_mem, tol.val[2] ); + + /* We need to pass our parameters and inputs to the ODE file */ + pData = &data; + if ( CVodeSetUserData( cvode_mem, pData ) != CV_SUCCESS ) { + mexErrMsgTxt( "ERROR: Failed passing parameters and initial conditions" ); + } + + #if SOLVER == 1 + /* Attach dense linear solver module */ + if ( CVDense( cvode_mem, N_STATES ) != CV_SUCCESS ) { + N_VDestroy_Serial( y0 ); + CVodeFree( &cvode_mem ); + mexErrMsgTxt( "ERROR: Failed to attach linear solver module" ); + } + #endif + #if SOLVER == 2 + /* Use LAPACK solver */ + if ( CVLapackDense( cvode_mem, N_STATES ) != CV_SUCCESS ) { + N_VDestroy_Serial( y0 ); + CVodeFree( &cvode_mem ); + mexErrMsgTxt( "ERROR: Failed to attach linear solver module" ); + } + #endif + + #ifdef FJAC + if ( CVDlsSetDenseJacFn(cvode_mem, fj) != CV_SUCCESS ) { + N_VDestroy_Serial( y0 ); + CVodeFree( &cvode_mem ); + mexErrMsgTxt( "Failed to supply analytical Jacobian of RHS" ); + } + #endif + #if SOLVER == 3 + /* Use scaled preconditioned GMRES */ + if ( CVSpgmr( cvode_mem, PREC_BOTH, 0 ) != CV_SUCCESS ) { + N_VDestroy_Serial( y0 ); + CVodeFree( &cvode_mem ); + mexErrMsgTxt( "ERROR: Failed to attach linear solver module" ); + } + #endif + #if SOLVER == 4 + /* Use preconditioned Bi-CGStab solver */ + if ( CVSpbcg( cvode_mem, PREC_BOTH, 0 ) != CV_SUCCESS ) { + N_VDestroy_Serial( y0 ); + CVodeFree( &cvode_mem ); + mexErrMsgTxt( "ERROR: Failed to attach linear solver module" ); + } + #endif + #if SOLVER == 5 + /* Use preconditioned TFQMR iterative solver */ + if ( CVSptfqmr( cvode_mem, PREC_BOTH, 0 ) != CV_SUCCESS ) { + N_VDestroy_Serial( y0 ); + CVodeFree( &cvode_mem ); + mexErrMsgTxt( "ERROR: Failed to attach linear solver module" ); + } + #endif + +/* Current implementation keeps tolerances the same for all vectors + if ( CVodeSVtolerances( cvode_mem, reltol, abstol ) != CV_SUCCESS ) { + mexErrMsgTxt( "ERROR: Failed to set SV tolerances" ); + } */ + + if ( sensitivity == 1 ) + { + sensitivityBlock = ( N_STATES + N_PARAMS ) * N_STATES; + sensitivityBlockSize = sizeof( double ) * ( N_STATES + N_PARAMS ) * N_STATES; + + /* Create an empty list of vectors for the sensitivities */ + yS0 = N_VCloneEmptyVectorArray( N_STATES + N_PARAMS, y0 ); + + if ( nrhs < 7 ) { + /* Allocate memory for the sensitivities at the current point */ + sensitivities = malloc( sensitivityBlockSize ); + + /* Initialise the sensitivities */ + for ( k = 0; k < ( N_STATES + N_PARAMS ) * N_STATES; k++ ) { + sensitivities[ k ] = 0; + } + + /* Sensitivity initial conditions should be one on the diagonal for initial condition sensitivities */ + ind = N_STATES * N_PARAMS; + for ( k = 0; k < N_STATES; k++ ) { + sensitivities[ ind + k + k * N_STATES ] = 1; + } + } else { + sensitivities = mxGetPr( prhs[6] ); + } + + tols = malloc( ( N_STATES + N_PARAMS ) * sizeof( double ) ); + + /* Set the pointer to the sensitivity matrix so that CVode can find it */ + for ( k = 0; k < N_STATES + N_PARAMS; k++ ) { + N_VSetArrayPointer_Serial( &sensitivities[k * N_STATES], yS0[k] ); + tols[ k ] = tol.val[1]; + } + + sParList = malloc( sizeof( int ) * ( N_STATES + N_PARAMS ) ); + for ( k = 0; k < N_PARAMS; k++ ) { + sParList[k] = k; + } + for ( k = N_PARAMS; k < N_PARAMS+N_STATES; k++ ) { + sParList[k] = k; + } + + /* Initialise the sensitivity module of CVode */ + #ifdef AJAC + flag = CVodeSensInit( cvode_mem, N_STATES+N_PARAMS, CV_SIMULTANEOUS, g, yS0 ); + #else + flag = CVodeSensInit( cvode_mem, N_STATES+N_PARAMS, CV_SIMULTANEOUS, NULL, yS0 ); + #endif + + flag = CVodeSensSStolerances( cvode_mem, tol.val[0], tols ); + flag = CVodeSetSensParams( cvode_mem, data.p, NULL, sParList ); + + free( sParList ); + + if ( flag != CV_SUCCESS ) { + N_VDestroy_Serial( y0 ); + N_VDestroyVectorArray_Serial( yS0, N_STATES + N_PARAMS ); + free( sensitivities ); + free( data.p ); + free( tols ); + free( cvode_mem ); + mexErrMsgTxt( "ERROR: Failed to set the sensitivity analysis parameters" ); + } + + /* Allocate memory for the output sensitivities */ + if ( nlhs > 2 ) mxDestroyArray(plhs[2]); + plhs[2] = mxCreateDoubleMatrix( sensitivityBlock, t.length, mxREAL ); + sensitivityOutputs = mxGetPr( plhs[2] ); + } + + + /* Start the timer */ + time( &tStart ); + + if ( t.length == 2 ) { + nBlocks = 1; + mSize = nBlocks * BLOCK_SIZE; + + /* No steps were specified, just begin and end (dynamic memory allocation) */ + if ( nlhs > 0 ) mxDestroyArray(plhs[0]); + plhs[0] = mxCreateDoubleMatrix( 1, BLOCK_SIZE, mxREAL ); + tOutput = mxGetPr(plhs[0]); + tOutput[0] = t.val[0]; + + if ( nlhs > 1 ) mxDestroyArray(plhs[1]); + plhs[1] = mxCreateDoubleMatrix( N_STATES, BLOCK_SIZE, mxREAL ); + yOutput = mxGetPr(plhs[1]); + memcpy( &yOutput[0], &NV_DATA_S( y0 )[0], sizeof( realtype ) * N_STATES ); + + p = 0; k = 0; + tret = t.val[0]; + while ( tret < t.val[1] ) + { + p = p + N_STATES; k++; + flag = CVode( cvode_mem, t.val[1], y0, &tret, CV_ONE_STEP ); + if ( flag < 0 ) handleError( cvode_mem, y0, flag, plhs, nrhs, 0, NULL, NULL, NULL ); + + /* Check if the memory is still sufficient to store the output */ + if ( ( k + 1 ) > mSize ) { + /* If we run out of memory, increase the storage size */ + nBlocks ++; + mSize = nBlocks * BLOCK_SIZE; + + /* We're not done yet so resize the block */ + tOutput = reAllocate2DOutputMemory( tOutput, cvode_mem, y0, plhs[0], 1, mSize ); + yOutput = reAllocate2DOutputMemory( yOutput, cvode_mem, y0, plhs[1], N_STATES, mSize ); + } + + /* Fetch the output */ + memcpy( &yOutput[p], &NV_DATA_S( y0 )[0], sizeof( realtype ) * N_STATES ); + tOutput[k] = tret; + time( &tEnd ); + if ( difftime( tEnd, tStart ) > tol.val[2] ) { + printf( "WARNING: Simulation time exceeded! Aborting simulation at t = %e\n", tret ); + break; + } + + } + + #ifdef FIXEDRANGE + /* Added by Ir. C. A. Tiemann to support fixed end time */ + tret = tOutput[k-1]; + memcpy( &NV_DATA_S( y0 )[0], &yOutput[p-N_STATES], sizeof( realtype ) * N_STATES ); + flag = CVode( cvode_mem, t.val[1], y0, &tret, CV_NORMAL ); + memcpy( &yOutput[p], &NV_DATA_S( y0 )[0], sizeof( realtype ) * N_STATES ); + tOutput[k] = tret; + #endif + + if ( nBlocks > 1 ) { + printf( "WARNING: Required %d memory reallocations. Consider increasing block size.\n\n", nBlocks ); + } + + /* After we are done simulating, we tighten the memory block to the true size */ + tOutput = reAllocate2DOutputMemory( tOutput, cvode_mem, y0, plhs[0], 1, k + 1 ); + yOutput = reAllocate2DOutputMemory( yOutput, cvode_mem, y0, plhs[1], N_STATES, k + 1 ); + + } else { + /* Only one time point */ + if ( t.length == 1 ) { + + /* Steps were specified --> Static memory allocation (faster) */ + if ( nlhs > 0 ) mxDestroyArray(plhs[0]); + plhs[0] = mxCreateDoubleMatrix( 1, 1, mxREAL ); + tOutput = mxGetPr(plhs[0]); + if ( nlhs > 1 ) mxDestroyArray(plhs[1]); + plhs[1] = mxCreateDoubleMatrix( N_STATES, 1, mxREAL ); + yOutput = mxGetPr(plhs[1]); + tret = 0.0; + + /* Simulate up to a point */ + flag = CVode( cvode_mem, t.val[0], y0, &tret, CV_NORMAL ); + if ( flag < 0 ) handleError( cvode_mem, y0, flag, plhs, nrhs, 0, NULL, NULL, NULL ); + + memcpy( &yOutput[0], &NV_DATA_S( y0 )[0], sizeof( realtype ) * N_STATES ); + tOutput[0] = tret; + } else { + + /* Steps were specified --> Static memory allocation (faster) */ + if ( nlhs > 0 ) mxDestroyArray(plhs[0]); + plhs[0] = mxCreateDoubleMatrix( 1, t.length, mxREAL ); + tOutput = mxGetPr(plhs[0]); + tOutput[0] = t.val[0]; + tret = t.val[0]; + + if ( nlhs > 1 ) mxDestroyArray(plhs[1]); + + plhs[1] = mxCreateDoubleMatrix( N_STATES, t.length, mxREAL ); + yOutput = mxGetPr(plhs[1]); + + memcpy( &yOutput[0], &NV_DATA_S( y0 )[0], sizeof( realtype ) * N_STATES ); + + if ( sensitivity == 1 ) { + memcpy( &sensitivityOutputs[ 0 ], sensitivities, sensitivityBlockSize ); + } + + /* Fixed steps were specified */ + p = N_STATES; + q = sensitivityBlock; + + for ( k = 1; k < t.length; k++ ) { + flag = CVode( cvode_mem, t.val[k], y0, &tret, CV_NORMAL ); + if ( flag < 0 ) handleError( cvode_mem, y0, flag, plhs, nrhs, sensitivity, yS0, sensitivities, &data ); + /* Fetch the output */ + memcpy( &yOutput[p], &NV_DATA_S( y0 )[0], sizeof( realtype ) * N_STATES ); + p = p + N_STATES; + tOutput[k] = t.val[k]; + if ( sensitivity == 1 ) { + flag = CVodeGetSens(cvode_mem, &tret, yS0); + if ( flag < 0 ) + handleError( cvode_mem, y0, flag, plhs, nrhs, sensitivity, yS0, sensitivities, &data ); + else { + memcpy( &sensitivityOutputs[ q ], sensitivities, sensitivityBlockSize ); + q = q + sensitivityBlock; + } + } + + time( &tEnd ); + if ( difftime( tEnd, tStart ) > tol.val[2] ) { + printf( "WARNING: Simulation time exceeded! Aborting simulation", t.val[k] ); + tOutput = reAllocate2DOutputMemory( tOutput, cvode_mem, y0, plhs[0], 1, k ); + yOutput = reAllocate2DOutputMemory( yOutput, cvode_mem, y0, plhs[1], N_STATES, k ); + break; + } + } + } + } + N_VDestroy_Serial( y0 ); + + /* Free CVode memory */ + CVodeFree( &cvode_mem ); + + if ( sensitivity == 1 ) { + free( data.p ); + free( tols ); + if ( nrhs < 7 ) free( sensitivities ); + N_VDestroyVectorArray_Serial( yS0, N_STATES + N_PARAMS ); + } + + /* If we desire only one output, we probably meant the solution array + since it is pretty pointless to output the time array */ + if ( nlhs == 1 ) { + mxDestroyArray( plhs[0] ); + plhs[0] = plhs[1]; + } + +} + + + diff --git a/odemex/Parser/outputC/model/aJac.c b/odemex/Parser/outputC/model/aJac.c new file mode 100644 index 0000000..424c30f --- /dev/null +++ b/odemex/Parser/outputC/model/aJac.c @@ -0,0 +1,50 @@ + t0 = MatrixWithNoName[0][0] = -p_2; + MatrixWithNoName[0][1] = p_4; + MatrixWithNoName[1][1] = -p_2; + MatrixWithNoName[1][2] = p_5; + MatrixWithNoName[2][2] = -p_2; + MatrixWithNoName[2][3] = p_6; + MatrixWithNoName[3][3] = -p_2; + MatrixWithNoName[3][4] = p_7; + MatrixWithNoName[4][4] = -p_2; + MatrixWithNoName[4][5] = p_8; + MatrixWithNoName[5][5] = -p_2; + MatrixWithNoName[5][6] = p_9; + MatrixWithNoName[6][6] = -p_2; + MatrixWithNoName[6][7] = p_10; + MatrixWithNoName[7][7] = -p_2; + MatrixWithNoName[7][8] = p_11; + MatrixWithNoName[8][8] = -p_2; + MatrixWithNoName[8][9] = p_12; + MatrixWithNoName[9][9] = -p_2; + MatrixWithNoName[9][10] = p_13; + MatrixWithNoName[10][10] = -p_2; + MatrixWithNoName[10][11] = p_14; + MatrixWithNoName[11][11] = -p_2; + MatrixWithNoName[11][12] = p_15; + MatrixWithNoName[12][12] = -p_2; + MatrixWithNoName[12][13] = p_16; + MatrixWithNoName[13][13] = -p_2; + MatrixWithNoName[13][14] = p_17; + MatrixWithNoName[14][14] = -p_2; + MatrixWithNoName[14][15] = p_18; + MatrixWithNoName[15][15] = -p_2; + MatrixWithNoName[15][16] = p_19; + MatrixWithNoName[16][16] = -p_2; + MatrixWithNoName[16][17] = p_20; + MatrixWithNoName[17][17] = -p_2; + MatrixWithNoName[17][18] = p_21; + MatrixWithNoName[18][18] = -p_2; + MatrixWithNoName[18][19] = p_22; + MatrixWithNoName[19][19] = -p_2; + MatrixWithNoName[19][20] = p_23; + MatrixWithNoName[20][20] = -p_2; + MatrixWithNoName[20][21] = p_24; + MatrixWithNoName[21][21] = -p_2; + MatrixWithNoName[21][22] = p_25; + MatrixWithNoName[22][22] = -p_2; + MatrixWithNoName[22][23] = p_26; + MatrixWithNoName[23][0] = p_0*p_1*x_23*1.0/pow(p_1*(x_23*x_23)+1.0,2.0)*-2.0; + MatrixWithNoName[23][23] = -p_2; + MatrixWithNoName[23][24] = p_27; + MatrixWithNoName[24][24] = -p_2; diff --git a/odemex/Parser/outputC/model/dxdt.c b/odemex/Parser/outputC/model/dxdt.c new file mode 100644 index 0000000..00d821e --- /dev/null +++ b/odemex/Parser/outputC/model/dxdt.c @@ -0,0 +1,154 @@ +#include "../dxdt.h" + + + +int rhs( realtype t, N_Vector y, N_Vector ydot, void *f_data ) { + + struct mData *data = ( struct mData * ) f_data; + + realtype ApoB_count , CE_count , DNL , J_ApoB_prod , J_CE_ER_deformation , J_CE_ER_formation , J_CE_HDL_for , J_CE_HDL_upt , J_CE_HDL_upt_1 , J_CE_HDL_upt_2 , J_CE_deformation , J_CE_formation , J_CE_upt_1 , J_CE_upt_2 , J_CE_upt_ph , J_FC_metabolism , J_FC_production , J_FFA_prod , J_FFA_upt_1 , J_FFA_upt_2 , J_TG_ER_formation , J_TG_ER_formation_DNL , J_TG_ER_production , J_TG_formation , J_TG_formation_DNL , J_TG_hyd_1 , J_TG_hyd_2 , J_TG_hyd_ph , J_TG_metabolism , J_TG_metabolism_DNL , J_TG_production , J_TG_upt_1 , J_TG_upt_2 , J_TG_upt_ph , J_VLDL_CE , J_VLDL_CE_1 , J_VLDL_CE_2 , J_VLDL_TG , J_VLDL_TG_1 , J_VLDL_TG_2 , J_VLDL_TG_DNL_1 , J_VLDL_TG_DNL_2 , TG_count , VLDL_clearance , VLDL_diameter , Vm_ApoB_prod , Vm_CE_ER_def , Vm_CE_ER_for , Vm_CE_def , Vm_CE_for , Vm_FC_met , Vm_FC_prod , Vm_FFA_prod , Vm_FFA_upt , Vm_HDL_CE_for , Vm_HDL_CE_upt , Vm_TG_CE_upt , Vm_TG_CE_upt_0 , Vm_TG_CE_upt_ph , Vm_TG_CE_upt_ph_0 , Vm_TG_ER_for , Vm_TG_ER_prod , Vm_TG_for , Vm_TG_hyd , Vm_TG_hyd_ph , Vm_TG_met , Vm_TG_prod , Vm_VLDL_CE , Vm_VLDL_TG , dDNL , dFFA , dVLDL_TG_C_ratio , dVLDL_clearance , dVLDL_diameter , dVLDL_production , dhep_CE_abs , dhep_FC_abs , dhep_HDL_CE_upt , dhep_TG_abs , dplasma_C , dplasma_C_HDL , dplasma_TG , dxdt , hep_CE , hep_CE_ER , hep_FC , hep_TG , hep_TG_DNL , hep_TG_ER , hep_TG_ER_DNL , lipo_rc , lipo_vc , mvCE , mvFC , mvPL , mvTG , mwApoB , mwCE , mwFC , mwPL , mwTG , navg , npi , plasma_C , plasma_C_HDL , plasma_FFA , plasma_TG , plasma_volume , rs , uH ; + + realtype *stateVars; + realtype *ydots; + + stateVars = NV_DATA_S(y); + ydots = NV_DATA_S(ydot); + + + + mwTG =859.2; + mvTG =946.8384; + mwCE =647.9; + mvCE =685.4782; + mwFC =386.7; + mvFC =394.8207; + mwPL =786; + mvPL =773.424; + mwApoB =546340; + navg =6.0221; + uH =1.6605; + plasma_volume =0.001; + rs =2; + npi =3.1416; + + hep_FC =stateVars[0]; + hep_CE =stateVars[1]; + hep_CE_ER =stateVars[2]; + hep_TG =stateVars[3]; + hep_TG_ER =stateVars[4]; + hep_TG_DNL =stateVars[5]; + hep_TG_ER_DNL =stateVars[6]; + plasma_TG =stateVars[7]; + plasma_C =stateVars[8]; + plasma_C_HDL =stateVars[9]; + plasma_FFA =stateVars[10]; + + Vm_FC_prod =data->p[0]; + Vm_FC_met =data->p[1]; + Vm_CE_for =data->p[2]; + Vm_CE_def =data->p[3]; + Vm_CE_ER_for =data->p[4]; + Vm_CE_ER_def =data->p[5]; + Vm_TG_prod =data->p[6]; + Vm_TG_met =data->p[7]; + Vm_TG_for =data->p[8]; + Vm_TG_ER_prod =data->p[9]; + Vm_TG_ER_for =data->p[10]; + Vm_FFA_upt =data->p[11]; + Vm_FFA_prod =data->p[12]; + Vm_VLDL_TG =data->p[13]; + Vm_VLDL_CE =data->p[14]; + Vm_TG_CE_upt =data->p[15]; + Vm_TG_CE_upt_ph =data->p[16]; + Vm_TG_hyd =data->p[17]; + Vm_TG_hyd_ph =data->p[18]; + Vm_HDL_CE_for =data->p[19]; + Vm_HDL_CE_upt =data->p[20]; + Vm_ApoB_prod =data->p[21]; + Vm_TG_CE_upt_0 =data->p[22]; + Vm_TG_CE_upt_ph_0 =data->p[23]; + + J_FC_production =Vm_FC_prod; + J_FC_metabolism =Vm_FC_met *hep_FC; + J_CE_formation =Vm_CE_for *hep_FC; + J_CE_deformation =Vm_CE_def *hep_CE; + J_CE_ER_formation =Vm_CE_ER_for *hep_FC; + J_CE_ER_deformation =Vm_CE_ER_def *hep_CE_ER; + J_TG_production =Vm_TG_prod; + J_TG_metabolism =Vm_TG_met *hep_TG; + J_TG_metabolism_DNL =Vm_TG_met *hep_TG_DNL; + J_TG_formation =Vm_TG_for *hep_TG_ER; + J_TG_formation_DNL =Vm_TG_for *hep_TG_ER_DNL; + J_TG_ER_production =Vm_TG_ER_prod; + J_TG_ER_formation =Vm_TG_ER_for *hep_TG; + J_TG_ER_formation_DNL =Vm_TG_ER_for *hep_TG_DNL; + J_FFA_upt_1 =Vm_FFA_upt *plasma_FFA; + J_FFA_upt_2 =Vm_FFA_upt *plasma_FFA *plasma_volume; + J_FFA_prod =Vm_FFA_prod; + J_VLDL_TG_1 =Vm_VLDL_TG *hep_TG_ER; + J_VLDL_TG_DNL_1 =Vm_VLDL_TG *hep_TG_ER_DNL; + J_VLDL_CE_1 =Vm_VLDL_CE *hep_CE_ER; + J_VLDL_TG_2 =Vm_VLDL_TG *hep_TG_ER /plasma_volume; + J_VLDL_TG_DNL_2 =Vm_VLDL_TG *hep_TG_ER_DNL /plasma_volume; + J_VLDL_CE_2 =Vm_VLDL_CE *hep_CE_ER /plasma_volume; + J_TG_upt_1 =Vm_TG_CE_upt *plasma_TG; + J_CE_upt_1 =Vm_TG_CE_upt *plasma_C; + J_TG_upt_ph =Vm_TG_CE_upt_ph *plasma_TG; + J_CE_upt_ph =Vm_TG_CE_upt_ph *plasma_C; + J_CE_HDL_for =Vm_HDL_CE_for; + J_CE_HDL_upt_1 =Vm_HDL_CE_upt *plasma_C_HDL; + J_TG_hyd_1 =Vm_TG_hyd *plasma_TG; + J_TG_hyd_ph =Vm_TG_hyd_ph *plasma_TG; + J_TG_upt_2 =Vm_TG_CE_upt *plasma_TG *plasma_volume; + J_CE_upt_2 =Vm_TG_CE_upt *plasma_C *plasma_volume; + J_CE_HDL_upt_2 =Vm_HDL_CE_upt *plasma_C_HDL *plasma_volume; + J_TG_hyd_2 =Vm_TG_hyd *plasma_TG *plasma_volume; + J_VLDL_TG =Vm_VLDL_TG * (hep_TG_ER +hep_TG_ER_DNL); + J_VLDL_CE =Vm_VLDL_CE *hep_CE_ER; + J_ApoB_prod =Vm_ApoB_prod; + ApoB_count =J_ApoB_prod *navg *pow(10,23) *pow(10,-6); + TG_count =J_VLDL_TG *navg *pow(10,23) *pow(10,-6) /ApoB_count; + CE_count =J_VLDL_CE *navg *pow(10,23) *pow(10,-6) /ApoB_count; + DNL = (hep_TG_DNL +hep_TG_ER_DNL) / (hep_TG +hep_TG_ER +hep_TG_DNL +hep_TG_ER_DNL); + lipo_vc = ( (TG_count *mvTG) + (CE_count *mvCE) ) * (pow(10,21) / (navg *pow(10,23))); + lipo_rc =pow((3 *lipo_vc) / (4 *npi),1/3); + VLDL_diameter = (lipo_vc +lipo_rc) *2; + VLDL_clearance = (Vm_TG_CE_upt +Vm_TG_CE_upt_ph) / (Vm_TG_CE_upt_0 +Vm_TG_CE_upt_ph_0); + J_CE_HDL_upt =Vm_HDL_CE_upt *plasma_C_HDL; + dhep_TG_abs =hep_TG +hep_TG_ER +hep_TG_DNL +hep_TG_ER_DNL; + dhep_CE_abs =hep_CE +hep_CE_ER; + dhep_FC_abs =hep_FC; + dplasma_C =plasma_C +plasma_C_HDL; + dplasma_TG =plasma_TG; + dVLDL_TG_C_ratio =TG_count /CE_count; + dVLDL_diameter =VLDL_diameter; + dVLDL_production =J_VLDL_TG; + dVLDL_clearance =VLDL_clearance; + dDNL =DNL; + dFFA =plasma_FFA; + dplasma_C_HDL =plasma_C_HDL; + dhep_HDL_CE_upt =J_CE_HDL_upt *plasma_volume; + + ydots[0] =J_FC_production -J_FC_metabolism -J_CE_formation +J_CE_deformation -J_CE_ER_formation +J_CE_ER_deformation; + ydots[1] =J_CE_formation -J_CE_deformation +J_CE_upt_2 +J_CE_HDL_upt_2; + ydots[2] =J_CE_ER_formation -J_CE_ER_deformation -J_VLDL_CE_1; + ydots[3] = -J_TG_metabolism +J_TG_formation -J_TG_ER_formation + (J_FFA_upt_2/3.0) +J_TG_upt_2 +J_TG_hyd_2; + ydots[4] = -J_TG_formation +J_TG_ER_formation -J_VLDL_TG_1; + ydots[5] =J_TG_production -J_TG_metabolism_DNL +J_TG_formation_DNL -J_TG_ER_formation_DNL; + ydots[6] =J_TG_ER_production -J_TG_formation_DNL +J_TG_ER_formation_DNL -J_VLDL_TG_DNL_1; + ydots[7] =J_VLDL_TG_2 +J_VLDL_TG_DNL_2 -J_TG_upt_1 -J_TG_upt_ph -J_TG_hyd_1 -J_TG_hyd_ph; + ydots[8] =J_VLDL_CE_2 -J_CE_upt_1 -J_CE_upt_ph; + ydots[9] =J_CE_HDL_for -J_CE_HDL_upt_1; + ydots[10] =J_FFA_prod -J_FFA_upt_1; + + + + + #ifdef NON_NEGATIVE + return 0; + #else + return 0; + #endif + +}; + diff --git a/odemex/Parser/outputC/model/dxdtDefs.h b/odemex/Parser/outputC/model/dxdtDefs.h new file mode 100644 index 0000000..9987c4e --- /dev/null +++ b/odemex/Parser/outputC/model/dxdtDefs.h @@ -0,0 +1,15 @@ + +#define N_STATES 11 +#define N_PARAMS 24 +#define N_INPUTS 0 +#define SOLVER 1 +#define BLOCK_SIZE 1000 + +#define MAX_CONV_FAIL 1000000 +#define MAX_STEPS 1000000000 +#define MAX_ERRFAILS 15 +#define MIN_STEPSIZE 0.000000000000010000000000000000 +#define MAX_STEPSIZE 100000000000000.000000000000000000000000000000 + +#define FIXEDRANGE + diff --git a/odemex/Parser/outputC/ode.c b/odemex/Parser/outputC/ode.c new file mode 100644 index 0000000..2543276 --- /dev/null +++ b/odemex/Parser/outputC/ode.c @@ -0,0 +1,225 @@ +/* + Joep Vanlier, 2011 + + Licensing: + Copyright (C) 2009-2011 Joep Vanlier. All rights + reserved. + + Contact:joep.vanlier@gmail.com + + This file is part of the puaMAT. + + puaMAT is free software: you can redistribute it + and/or modify it under the terms of the GNU General + Public License as published by the Free Software + Foundation, either version 3 of the License, or (at + your option) any later version. + + puaMAT is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A + PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General + Public License along with puaMAT. If not, see + http://www.gnu.org/licenses/ +*/ +#include "ode.h" +#include "model/dxdtDefs.h" + +void grabVectorFromMatlab( struct mVector *vector, const mxArray *prhs ) { + if ( mxIsDouble( prhs ) ) { + vector->length = mxGetN( prhs ) * mxGetM( prhs ); + vector->val = mxGetPr( prhs ); + } else { + mexErrMsgTxt( "ERROR: Check your parameters! Are they all doubles?" ); + } +} + +realtype interpolate( realtype *time, realtype *data, int n, realtype t, int type ) { + + realtype *deriv2; + realtype val; + + int max = n-1; + int min = 0; + int cur = max/2; + + double a, b, h, tmp; + + /* Out of bounds? */ + if ( t >= time[ max ] ) + return data[ n-1 ]; + else if ( t <= time[ min ] ) + return data[ 0 ]; + + /* Where are we? */ + while ( min != max - 1 ) + { + if ( time[ cur ] <= t ) + min = cur; + else + max = cur; + + cur = min + ( max - min ) / 2; + } + + switch( type ) + { + /* Piecewise */ + case 0: + val = data[ min ]; + return val; + break; + /* Linear Interpolation */ + case 1: + val = data[min] + ( t - time[min] ) * ( data[max] - data[min] ) / ( time[max] - time[min] ); + return val; + break; + /* Spline Interpolation */ + case 2: + deriv2 = &data[n]; + h = time[max] - time[min]; + a = ( time[ max ] - t ) / h; + b = ( t - time[ min ] ) / h; + val = a * data[ min ] + b * data[ max ] + ( ( a * a * a - a ) * deriv2[ min ] + ( b * b * b - b ) * deriv2[ max ] ) * ( h * h ) / 6.0; + return val; + break; + } +} + +realtype tpow(realtype x, unsigned int y) { + realtype z = y&1? x : 1; + while(y >>= 1) { + x *= x; + if(y & 1) z *= x; + } + return z; +} + +realtype intPow( double x, int y ) { + if(y < 0) + return 1.0/tpow(x, -y); + else + return tpow(x, y); +} + +realtype maximum( realtype a, realtype b ) { + return (a > b ? a : b); +} + +realtype minimum( realtype a, realtype b ) { + return (a > b ? b : a); +} + +void memErr( void *cvode_mem, N_Vector y0, void *pOld, const char *msg ) { + N_VDestroy_Serial( y0 ); + CVodeFree( &cvode_mem ); + mxFree( pOld ); + mexErrMsgTxt( msg ); +} + +void handleError( void *cvode_mem, N_Vector y0, int flag, mxArray *plhs[], int nrhs, int sensitivity, N_Vector *yS0, realtype *sensitivities, struct mData *data ) { + + #ifdef DEBUG + long int temp; + realtype tempreal; + #endif + + #ifdef DEBUG + printf( "<<< DEBUG OUTPUT >>>\n" ); + printf( "PARAMETERS: \n" ); + for ( temp = 0; temp < N_PARAMS; temp++ ) { + printf( "P(%d) = %f\n", temp, data->p[ temp ] ); + } + CVodeGetNumSteps(cvode_mem, &temp); + printf( "Number of steps taken by the solver: %d\n", temp ); + CVodeGetNumErrTestFails(cvode_mem, &temp); + printf( "Number of local error test failures: %d\n", temp ); + CVodeGetLastStep(cvode_mem, &tempreal); + printf( "Last stepsize: %f\n", tempreal ); + CVodeGetCurrentStep(cvode_mem, &tempreal); + printf( "Last step: %f\n", tempreal ); + #endif + + if ( sensitivity == 1 ) { + if ( nrhs < 7 ) free( sensitivities ); + free( data->p ); + N_VDestroyVectorArray_Serial( yS0, N_STATES + N_PARAMS ); + if ( plhs[2] != NULL ) mxDestroyArray(plhs[2]); + } + + if ( plhs[1] != NULL ) mxDestroyArray(plhs[1]); + if ( plhs[0] != NULL ) mxDestroyArray(plhs[0]); + + N_VDestroy_Serial( y0 ); + /*printf( "Freeing..." );*/ + /*CVodeFree( &cvode_mem );*/ + /*printf( "Success!\n" );*/ + + switch( flag ) { + case CV_MEM_NULL: + printf( "ERROR: No memory was allocated for cvode_mem\n" ); + break; + case CV_NO_MALLOC: + printf( "ERROR: Forgot or failed CVodeInit\n" ); + break; + case CV_ILL_INPUT: + printf( "ERROR: Input for CVode was illegal\n" ); + break; + case CV_TOO_CLOSE: + printf( "ERROR: Initial time too close to final time\n" ); + break; + case CV_TOO_MUCH_WORK: + printf( "ERROR: Solver took maximum number of internal steps, but hasn't reached t_out\n" ); + break; + case CV_TOO_MUCH_ACC: + printf( "ERROR: Could not attain desired accuracy\n" ); + break; + case CV_ERR_FAILURE: + printf( "ERROR: Error tests failed too many times\n" ); + break; + case CV_CONV_FAILURE: + printf( "ERROR: Convergence failure in solving the linear system\n" ); + break; + case CV_LINIT_FAIL: + printf( "ERROR: Linear solver failed to initialize\n" ); + break; + case CV_LSETUP_FAIL: + printf( "ERROR: Linear solver setup failed\n" ); + break; + case CV_RHSFUNC_FAIL: + printf( "ERROR: Right hand side failed in an unrecoverable manner\n" ); + break; + case CV_REPTD_RHSFUNC_ERR: + printf( "ERROR: Convergence test failures occured too many times in RHS\n" ); + break; + case CV_UNREC_RHSFUNC_ERR: + printf( "ERROR: Unrecoverable error in the RHS\n" ); + break; + case CV_RTFUNC_FAIL: + printf( "ERROR: Rootfinding function failed!\n" ); + break; + default: + printf( "ERROR: I have no idea what's going on :(\n" ); + break; + } + + mexErrMsgTxt( "Aborting" ); +} + +realtype *reAllocate2DOutputMemory( realtype *pMem, void *cvode_mem, N_Vector y0, mxArray *plhs, mwSize dim1, mwSize dim2 ) { + void *pOld; + + pOld = pMem; + pMem = mxRealloc( pMem, sizeof( realtype ) * dim1 * dim2 ); + + if ( pMem == NULL ) memErr( cvode_mem, y0, pOld, "ERROR: Insufficient memory for reallocation during simulation loop!" ); + + mxSetPr( plhs, pMem ); + mxSetM( plhs, dim1 ); + mxSetN( plhs, dim2 ); + + return pMem; +} diff --git a/odemex/Parser/outputC/ode.h b/odemex/Parser/outputC/ode.h new file mode 100644 index 0000000..392b1a6 --- /dev/null +++ b/odemex/Parser/outputC/ode.h @@ -0,0 +1,74 @@ +/* + Joep Vanlier, 2011 + + Licensing: + Copyright (C) 2009-2011 Joep Vanlier. All rights + reserved. + + Contact:joep.vanlier@gmail.com + + This file is part of the puaMAT. + + puaMAT is free software: you can redistribute it + and/or modify it under the terms of the GNU General + Public License as published by the Free Software + Foundation, either version 3 of the License, or (at + your option) any later version. + + puaMAT is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A + PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General + Public License along with puaMAT. If not, see + http://www.gnu.org/licenses/ +*/ +#include "mex.h" +#include "cvodes.h" +#include "model/dxdtDefs.h" +#include +#include +#include + +#define N_PI (3.141592653589793) +#define N_EXP (2.7182818284590455) + +#if SOLVER == 2 + #include "cvodes_lapack.h" +#endif +#if SOLVER == 3 + #include "cvodes_spgmr.h" +#endif +#if SOLVER == 4 + #include "cvodes_spbcgs.h" +#endif +#if SOLVER == 5 + #include "cvodes_sptfqmr.h" +#endif + +#ifndef ODE_H +#define ODE_H + +struct mVector { + double *val; + int length; +}; + +struct mData { + realtype *u; + realtype *p; +}; + +void grabVectorFromMatlab( struct mVector *vector, const mxArray *prhs ); +void handleError( void *cvode_mem, N_Vector y0, int flag, mxArray *plhs[], int nrhs, int sensitivity, N_Vector *yS0, realtype *sensitivities, struct mData *data ); +void memErr( void *cvode_mem, N_Vector y0, void *pOld, const char *msg ); +realtype *reAllocate2DOutputMemory( realtype *pMem, void *cvode_mem, N_Vector y0, mxArray *plhs, int dim1, int dim2 ); + +realtype interpolate( realtype *time, realtype *data, int n, realtype t, int type ); +realtype maximum( realtype x, realtype y ); +realtype minimum( realtype x, realtype y ); +realtype intPow( realtype x, int y ); + +#endif diff --git a/odemex/Parser/outputC_IDA/dxdt.h b/odemex/Parser/outputC_IDA/dxdt.h new file mode 100644 index 0000000..b77175b --- /dev/null +++ b/odemex/Parser/outputC_IDA/dxdt.h @@ -0,0 +1,39 @@ +/* + Joep Vanlier, 2011 + + Licensing: + Copyright (C) 2009-2011 Joep Vanlier. All rights + reserved. + + Contact:joep.vanlier@gmail.com + + This file is part of the puaMAT. + + puaMAT is free software: you can redistribute it + and/or modify it under the terms of the GNU General + Public License as published by the Free Software + Foundation, either version 3 of the License, or (at + your option) any later version. + + puaMAT is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A + PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General + Public License along with puaMAT. If not, see + http://www.gnu.org/licenses/ +*/ +#include "ode.h" +#include "model/dxdtDefs.h" + +#ifndef _DXDT_H_ +#define _DXDT_H_ + +#define realtype double + +int rhs( realtype t, N_Vector y, N_Vector ydot, N_Vector resid, void *f_data ); + + +#endif diff --git a/odemex/Parser/outputC_IDA/mexG.c b/odemex/Parser/outputC_IDA/mexG.c new file mode 100644 index 0000000..db85759 --- /dev/null +++ b/odemex/Parser/outputC_IDA/mexG.c @@ -0,0 +1,340 @@ +/* + Joep Vanlier, 2011 + + Licensing: + Copyright (C) 2009-2011 Joep Vanlier. All rights + reserved. + + Contact:joep.vanlier@gmail.com + + This file is part of the puaMAT. + + puaMAT is free software: you can redistribute it + and/or modify it under the terms of the GNU General + Public License as published by the Free Software + Foundation, either version 3 of the License, or (at + your option) any later version. + + puaMAT is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A + PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General + Public License along with puaMAT. If not, see + http://www.gnu.org/licenses/ +*/ +#include "ode.h" +#include "dxdt.h" +#include "time.h" +#include "string.h" + +const int numInputArgs = 5; +const int numOutputArgs = 1; + +void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { + + time_t tStart, tEnd; + struct mVector t; + struct mVector tol; + struct mData data; + int k, p; + int nBlocks; + realtype t0; + realtype y[ N_STATES ]; + realtype yd[ N_STATES ]; + realtype *yOutput; + realtype *tOutput; + int mSize; + + int sensitivity; + + /* Structures required for IDA */ + int flag; + N_Vector y0 = NULL; + N_Vector yp0 = NULL; + N_Vector *yS0 = NULL; + void *cvode_mem = NULL; + void *pData = NULL; + realtype tret; + + /* Function pointer for the RHS */ + int (*f)(realtype t, N_Vector y, N_Vector ydot, N_Vector rr, void *f_data) = &rhs; + + if (nrhs == 0) { + printf( "Call function as:\ny = funcName(t, y0[%d], p[%d], u[%d], [reltol, abstol, maxtime])\n", N_STATES, N_PARAMS, N_INPUTS ); + return; + } + + if ( nrhs < numInputArgs ) mexErrMsgTxt( "ERROR: Incorrect number of input arguments\nFormat should be: (t, y0, x, u, [reltol, abstol, max_integration_time])\n" ); + + /* Check input dimensions */ + if ( mxGetNumberOfElements( prhs[1] ) != N_STATES ) { + printf( "ERROR: Initial condition vector has incorrect length! Expected %d, found %d", N_STATES, mxGetNumberOfElements( prhs[1] ) ); + mexErrMsgTxt( "" ); + } + if ( mxGetNumberOfElements( prhs[2] ) != N_PARAMS ) { + printf( "ERROR: Parameter vector has incorrect length! Expected %d, found %d", N_PARAMS, mxGetNumberOfElements( prhs[2] ) ); + mexErrMsgTxt( "" ); + } + if ( mxGetNumberOfElements( prhs[3] ) != N_INPUTS ) { + printf( "ERROR: Input vector has incorrect length! Expected %d, found %d", N_INPUTS, mxGetNumberOfElements( prhs[3] ) ); + mexErrMsgTxt( "" ); + } + if ( mxGetNumberOfElements( prhs[4] ) != 3 ) { + mexErrMsgTxt( "ERROR: Tolerance vector should be of the form [ relative tolerance, absolute tolerance, maximal time allowed for integration in seconds ]" ); + } + + /* Grab vectors for own use from MATLAB */ + grabVectorFromMatlab( &t, prhs[0] ); + grabVectorFromMatlab( &tol, prhs[4] ); + + if ( t.length < 1 ) + mexErrMsgTxt( "ERROR: Time vector should be at least one element. Either provide a single time to obtain a single value at time t, a begin and end time if the solver is allowed to determine the timesteps or a series of timepoints at which to compute the solution." ); + + sensitivity = 0; + if ( nrhs > 5 ) { + mexErrMsgTxt( "ERROR: Sensitivity analysis is currently not supported for DAE problems." ); + } + + if ( prhs[3] != NULL ) + data.u = mxGetPr( prhs[3] ); + else + data.u = NULL; + + /* Set parameter pointer to matlab structure */ + data.p = mxGetPr( prhs[2] ); + /* Copy initial condition to local structure */ + memcpy( y, mxGetPr( prhs[1] ), sizeof( realtype ) * mxGetNumberOfElements( prhs[1] ) ); + memset( yd, 0, sizeof( realtype ) * mxGetNumberOfElements( prhs[1] ) ); + y0 = N_VMake_Serial( N_STATES, y ); /* Warning, realtype has to be double for this */ + yp0 = N_VMake_Serial( N_STATES, yd ); /* Warning, realtype has to be double for this */ + + /* Compute appropriate initial condition for ydot */ + f(0, y0, yp0, yp0, &data); + for ( k = 0; k < N_STATES; k++ ) + NV_DATA_S(yp0)[k] = - NV_DATA_S(yp0)[k]; + + /* Set begin time */ + if ( t.length == 1 ) + t0 = 0.0; + else + t0 = t.val[0]; + + /* Start up IDA */ + cvode_mem = IDACreate( ); + + /* Initialise IDA */ + if ( IDAInit( cvode_mem, f, t0, y0, yp0 ) != IDA_SUCCESS ) { + N_VDestroy_Serial( y0 ); + N_VDestroy_Serial( yp0 ); + mexErrMsgTxt( "ERROR: Failed to initialise IDA" ); + } + + /* Specify tolerances */ + if ( IDASStolerances( cvode_mem, tol.val[0], tol.val[1] ) != IDA_SUCCESS ) { + N_VDestroy_Serial( y0 ); + N_VDestroy_Serial( yp0 ); + IDAFree( &cvode_mem ); + mexErrMsgTxt( "ERROR: Failed to set tolerances" ); + } + + IDASetMinStep( cvode_mem, MIN_STEPSIZE ); + IDASetMaxConvFails( cvode_mem, MAX_CONV_FAIL ); + IDASetMaxNumSteps( cvode_mem, MAX_STEPS ); + IDASetMaxErrTestFails( cvode_mem, MAX_ERRFAILS ); + IDASetMaxTime( cvode_mem, tol.val[2] ); + + #if SOLVER == 1 + /* Attach dense linear solver module */ + if ( IDADense( cvode_mem, N_STATES ) != IDA_SUCCESS ) { + N_VDestroy_Serial( y0 ); + N_VDestroy_Serial( yp0 ); + IDAFree( &cvode_mem ); + mexErrMsgTxt( "ERROR: Failed to attach linear solver module" ); + } + #endif + #if SOLVER == 2 + /* Use LAPACK solver */ + if ( IDALapackDense( cvode_mem, N_STATES ) != IDA_SUCCESS ) { + N_VDestroy_Serial( y0 ); + N_VDestroy_Serial( yp0 ); + IDAFree( &cvode_mem ); + mexErrMsgTxt( "ERROR: Failed to attach linear solver module" ); + } + #endif + #if SOLVER == 3 + /* Use scaled preconditioned GMRES */ + if ( IDASpgmr( cvode_mem, PREC_BOTH, 0 ) != IDA_SUCCESS ) { + N_VDestroy_Serial( y0 ); + N_VDestroy_Serial( yp0 ); + IDAFree( &cvode_mem ); + mexErrMsgTxt( "ERROR: Failed to attach linear solver module" ); + } + #endif + #if SOLVER == 4 + /* Use preconditioned Bi-CGStab solver */ + if ( IDASpbcg( cvode_mem, PREC_BOTH, 0 ) != IDA_SUCCESS ) { + N_VDestroy_Serial( y0 ); + N_VDestroy_Serial( yp0 ); + IDAFree( &cvode_mem ); + mexErrMsgTxt( "ERROR: Failed to attach linear solver module" ); + } + #endif + #if SOLVER == 5 + /* Use preconditioned TFQMR iterative solver */ + if ( IDASptfqmr( cvode_mem, PREC_BOTH, 0 ) != IDA_SUCCESS ) { + N_VDestroy_Serial( y0 ); + N_VDestroy_Serial( yp0 ); + IDAFree( &cvode_mem ); + mexErrMsgTxt( "ERROR: Failed to attach linear solver module" ); + } + #endif + +/* Current implementation keeps tolerances the same for all vectors + if ( IDASVTolerances( cvode_mem, reltol, abstol ) != IDA_SUCCESS ) { + mexErrMsgTxt( "ERROR: Failed to set SV tolerances" ); + }*/ + + /* We need to pass our parameters and inputs to the ODE file */ + pData = &data; + if ( IDASetUserData( cvode_mem, pData ) != IDA_SUCCESS ) { + mexErrMsgTxt( "ERROR: Failed passing parameters and initial conditions" ); + } + + IDASetLineSearchOffIC( cvode_mem, 1 ); + IDASetMaxNumStepsIC( cvode_mem, 100 ); + IDASetMaxNumJacsIC( cvode_mem, 100 ); + IDASetMaxNumItersIC( cvode_mem, 100 ); + + // flag = IDACalcIC( cvode_mem, IDA_Y_INIT, 0.001 ); + // if ( ( flag < 0 ) && ( flag != IDA_NO_RECOVERY ) ) handleError( cvode_mem, y0, yp0, flag, plhs ); + + /* Start the timer */ + time( &tStart ); + + if ( t.length == 2 ) { + nBlocks = 1; + mSize = nBlocks * BLOCK_SIZE; + + /* No steps were specified, just begin and end (dynamic memory allocation) */ + if ( nlhs > 0 ) mxDestroyArray(plhs[0]); + plhs[0] = mxCreateDoubleMatrix( 1, BLOCK_SIZE, mxREAL ); + tOutput = mxGetPr(plhs[0]); + tOutput[0] = t.val[0]; + + if ( nlhs > 1 ) mxDestroyArray(plhs[1]); + plhs[1] = mxCreateDoubleMatrix( N_STATES, BLOCK_SIZE, mxREAL ); + yOutput = mxGetPr(plhs[1]); + memcpy( &yOutput[0], &NV_DATA_S( y0 )[0], sizeof( realtype ) * N_STATES ); + + p = 0; k = 0; + tret = t.val[0]; + while ( tret < t.val[1] ) + { + p = p + N_STATES; k++; + flag = IDASolve( cvode_mem, t.val[1], &tret, y0, yp0, IDA_ONE_STEP ); + if ( flag < 0 ) handleError( cvode_mem, y0, yp0, flag, plhs ); + + /* Check if the memory is still sufficient to store the output */ + if ( ( k + 1 ) > mSize ) { + /* If we run out of memory, increase the storage size */ + nBlocks ++; + mSize = nBlocks * BLOCK_SIZE; + + /* We're not done yet so resize the block */ + tOutput = reAllocate2DOutputMemory( tOutput, cvode_mem, y0, yp0, plhs[0], 1, mSize ); + yOutput = reAllocate2DOutputMemory( yOutput, cvode_mem, y0, yp0, plhs[1], N_STATES, mSize ); + } + + /* Fetch the output */ + memcpy( &yOutput[p], &NV_DATA_S( y0 )[0], sizeof( realtype ) * N_STATES ); + tOutput[k] = tret; + time( &tEnd ); + if ( difftime( tEnd, tStart ) > tol.val[2] ) { + printf( "WARNING: Simulation time exceeded! Aborting simulation at t = %e\n", tret ); + break; + } + + } + if ( nBlocks > 1 ) { + printf( "WARNING: Required %d memory reallocations. Consider increasing block size.\n\n", nBlocks ); + } + + /* After we are done simulating, we tighten the memory block to the true size */ + tOutput = reAllocate2DOutputMemory( tOutput, cvode_mem, y0, yp0, plhs[0], 1, k + 1 ); + yOutput = reAllocate2DOutputMemory( yOutput, cvode_mem, y0, yp0, plhs[1], N_STATES, k + 1 ); + + } else { + /* Only one time point */ + if ( t.length == 1 ) { + + /* Steps were specified --> Static memory allocation (faster) */ + if ( nlhs > 0 ) mxDestroyArray(plhs[0]); + plhs[0] = mxCreateDoubleMatrix( 1, 1, mxREAL ); + tOutput = mxGetPr(plhs[0]); + if ( nlhs > 1 ) mxDestroyArray(plhs[1]); + plhs[1] = mxCreateDoubleMatrix( N_STATES, 1, mxREAL ); + yOutput = mxGetPr(plhs[1]); + tret = 0.0; + + /* Simulate up to a point */ + flag = IDASolve( cvode_mem, t.val[0], &tret, y0, yp0, IDA_NORMAL ); + if ( flag < 0 ) handleError( cvode_mem, y0, yp0, flag, plhs ); + + memcpy( &yOutput[0], &NV_DATA_S( y0 )[0], sizeof( realtype ) * N_STATES ); + tOutput[0] = tret; + } else { + /* Steps were specified --> Static memory allocation (faster) */ + if ( nlhs > 0 ) mxDestroyArray(plhs[0]); + plhs[0] = mxCreateDoubleMatrix( 1, t.length, mxREAL ); + tOutput = mxGetPr(plhs[0]); + tOutput[0] = t.val[0]; + tret = t.val[0]; + + if ( nlhs > 1 ) mxDestroyArray(plhs[1]); + plhs[1] = mxCreateDoubleMatrix( N_STATES, t.length, mxREAL ); + yOutput = mxGetPr(plhs[1]); + + memcpy( &yOutput[0], &NV_DATA_S( y0 )[0], sizeof( realtype ) * N_STATES ); + + /* Fixed steps were specified */ + p = N_STATES; + + for ( k = 1; k < t.length; k++ ) { + flag = IDASolve( cvode_mem, t.val[k], &tret, y0, yp0, IDA_NORMAL ); + if ( flag < 0 ) handleError( cvode_mem, y0, yp0, flag, plhs ); + + /* Fetch the output */ + memcpy( &yOutput[p], &NV_DATA_S( y0 )[0], sizeof( realtype ) * N_STATES ); + p = p + N_STATES; + tOutput[k] = t.val[k]; + + time( &tEnd ); + if ( difftime( tEnd, tStart ) > tol.val[2] ) { + printf( "WARNING: Simulation time exceeded! Aborting simulation", t.val[k] ); + tOutput = reAllocate2DOutputMemory( tOutput, cvode_mem, y0, yp0, plhs[0], 1, k ); + yOutput = reAllocate2DOutputMemory( yOutput, cvode_mem, y0, yp0, plhs[1], N_STATES, k ); + break; + } + } + } + } + N_VDestroy_Serial( y0 ); + N_VDestroy_Serial( yp0 ); + + /* Free IDA memory */ + IDAFree( &cvode_mem ); + + /* If we desire only one output, we probably meant the solution array + since it is pretty pointless to output the time array */ + if ( nlhs == 1 ) { + mxDestroyArray( plhs[0] ); + plhs[0] = plhs[1]; + } + +} + + + diff --git a/odemex/Parser/outputC_IDA/ode.c b/odemex/Parser/outputC_IDA/ode.c new file mode 100644 index 0000000..a8b3fee --- /dev/null +++ b/odemex/Parser/outputC_IDA/ode.c @@ -0,0 +1,204 @@ +/* + Joep Vanlier, 2011 + + Licensing: + Copyright (C) 2009-2011 Joep Vanlier. All rights + reserved. + + Contact:joep.vanlier@gmail.com + + This file is part of the puaMAT. + + puaMAT is free software: you can redistribute it + and/or modify it under the terms of the GNU General + Public License as published by the Free Software + Foundation, either version 3 of the License, or (at + your option) any later version. + + puaMAT is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A + PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General + Public License along with puaMAT. If not, see + http://www.gnu.org/licenses/ +*/ +#include "ode.h" + +void grabVectorFromMatlab( struct mVector *vector, const mxArray *prhs ) { + if ( mxIsDouble( prhs ) ) { + vector->length = mxGetN( prhs ) * mxGetM( prhs ); + vector->val = mxGetPr( prhs ); + } else { + mexErrMsgTxt( "ERROR: Check your parameters! Are they all doubles?" ); + } +} + +realtype interpolate( realtype *time, realtype *data, int n, realtype t, int type ) { + + realtype *deriv2; + realtype val; + + int max = n-1; + int min = 0; + int cur = max/2; + + double a, b, h, tmp; + + /* Out of bounds? */ + if ( t >= time[ max ] ) + return data[ n-1 ]; + else if ( t <= time[ min ] ) + return data[ 0 ]; + + /* Where are we? */ + while ( min != max - 1 ) + { + if ( time[ cur ] <= t ) + min = cur; + else + max = cur; + + cur = min + ( max - min ) / 2; + } + + switch( type ) + { + /* Piecewise */ + case 0: + val = data[ min ]; + return val; + break; + /* Linear Interpolation */ + case 1: + val = data[min] + ( t - time[min] ) * ( data[max] - data[min] ) / ( time[max] - time[min] ); + return val; + break; + /* Spline Interpolation */ + case 2: + deriv2 = &data[n]; + h = time[max] - time[min]; + a = ( time[ max ] - t ) / h; + b = ( t - time[ min ] ) / h; + val = a * data[ min ] + b * data[ max ] + ( ( a * a * a - a ) * deriv2[ min ] + ( b * b * b - b ) * deriv2[ max ] ) * ( h * h ) / 6.0; + return val; + break; + } +} inline; +realtype tpow(realtype x, unsigned int y) { + realtype z = y&1? x : 1; + while(y >>= 1) { + x *= x; + if(y & 1) z *= x; + } + return z; +} inline; + +realtype intPow( double x, int y ) { + if(y < 0) + return 1.0/tpow(x, -y); + else + return tpow(x, y); +} inline; + +realtype maximum( realtype a, realtype b ) { + return (a > b ? a : b); +} inline; + +realtype minimum( realtype a, realtype b ) { + return (a > b ? b : a); +} inline; + +void memErr( void *cvode_mem, N_Vector y0, N_Vector yp0, void *pOld, const char *msg ) { + N_VDestroy_Serial( y0 ); + N_VDestroy_Serial( yp0 ); + printf( "Freeing..." ); + IDAFree(&cvode_mem ); + printf( "Success!\n" ); + + mxFree( pOld ); + mexErrMsgTxt( msg ); +} inline; + +void handleError( void *cvode_mem, N_Vector y0, N_Vector yp0, int flag, mxArray *plhs[] ) { + + if ( plhs[1] != NULL ) mxDestroyArray(plhs[1]); + if ( plhs[0] != NULL ) mxDestroyArray(plhs[0]); + N_VDestroy_Serial( y0 ); + N_VDestroy_Serial( yp0 ); + printf( "Freeing..." ); + //IDAFree( &cvode_mem ); + printf( "Success!\n" ); + + switch( flag ) { + case IDA_NO_MALLOC: + printf( "ERROR: IDAInit not called\n" ); + break; + case IDA_NO_RECOVERY: + printf( "ERROR: There were recoverable errors but IC failed to recover.\n" ); + break; + case IDA_BAD_EWT: + printf( "ERROR: Error weight vector component zero\n" ); + break; + case IDA_FIRST_RES_FAIL: + printf( "ERROR: Error in user residual function\n" ); + break; + case IDA_CONSTR_FAIL: + printf( "CalcIC could not find solution satisfying constraints\n" ); + break; + case IDA_LINESEARCH_FAIL: + printf( "ERROR: Linesearch failed\n" ); + break; + case IDA_MEM_NULL: + printf( "ERROR: No memory was allocated for cvode_mem\n" ); + break; + case IDA_ILL_INPUT: + printf( "ERROR: Input for CVode was illegal\n" ); + break; + case IDA_TOO_MUCH_WORK: + printf( "ERROR: Solver took maximum number of internal steps, but hasn't reached t_out\n" ); + break; + case IDA_TOO_MUCH_ACC: + printf( "ERROR: Could not attain desired accuracy\n" ); + break; + case IDA_LINIT_FAIL: + printf( "ERROR: Linear solver failed to initialize\n" ); + break; + case IDA_LSETUP_FAIL: + printf( "ERROR: Linear solver setup failed\n" ); + break; + case IDA_RES_FAIL: + printf( "ERROR: Right hand side failed in an unrecoverable manner\n" ); + break; + case IDA_RTFUNC_FAIL: + printf( "ERROR: Rootfinding function failed!\n" ); + break; + case IDA_LSOLVE_FAIL: + printf( "ERROR: Linear solver failed\n" ); + break; + case IDA_CONV_FAIL: + printf( "ERROR: No Newton Convergence\n" ); + break; + default: + printf( "ERROR: I have no idea what's going on :(\n" ); + break; + } + mexErrMsgTxt( "Aborting" ); +} inline; + +realtype *reAllocate2DOutputMemory( realtype *pMem, void *cvode_mem, N_Vector y0, N_Vector yp0, mxArray *plhs, mwSize dim1, mwSize dim2 ) { + void *pOld; + + pOld = pMem; + pMem = mxRealloc( pMem, sizeof( realtype ) * dim1 * dim2 ); + + if ( pMem == NULL ) memErr( cvode_mem, y0, yp0, pOld, "ERROR: Insufficient memory for reallocation during simulation loop!" ); + + mxSetPr( plhs, pMem ); + mxSetM( plhs, dim1 ); + mxSetN( plhs, dim2 ); + + return pMem; +} inline; diff --git a/odemex/Parser/outputC_IDA/ode.h b/odemex/Parser/outputC_IDA/ode.h new file mode 100644 index 0000000..cd1f97a --- /dev/null +++ b/odemex/Parser/outputC_IDA/ode.h @@ -0,0 +1,73 @@ +/* + Joep Vanlier, 2011 + + Licensing: + Copyright (C) 2009-2011 Joep Vanlier. All rights + reserved. + + Contact:joep.vanlier@gmail.com + + This file is part of the puaMAT. + + puaMAT is free software: you can redistribute it + and/or modify it under the terms of the GNU General + Public License as published by the Free Software + Foundation, either version 3 of the License, or (at + your option) any later version. + + puaMAT is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A + PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General + Public License along with puaMAT. If not, see + http://www.gnu.org/licenses/ +*/ +#include "mex.h" +#include "ida.h" +#include "model/dxdtDefs.h" +#include +#include + +#define N_PI (3.141592653589793) +#define N_EXP (2.7182818284590455) + +#if SOLVER == 2 + #include "idas_lapack.h" +#endif +#if SOLVER == 3 + #include "idas_spgmr.h" +#endif +#if SOLVER == 4 + #include "idas_spbcgs.h" +#endif +#if SOLVER == 5 + #include "idas_sptfqmr.h" +#endif + +#ifndef ODE_H +#define ODE_H + +struct mVector { + double *val; + int length; +}; + +struct mData { + realtype *u; + realtype *p; +}; + +void grabVectorFromMatlab( struct mVector *vector, const mxArray *prhs ); +void handleError( void *cvode_mem, N_Vector y0, N_Vector yp0, int flag, mxArray *plhs[] ); +void memErr( void *cvode_mem, N_Vector y0, N_Vector yp0, void *pOld, const char *msg ); +realtype *reAllocate2DOutputMemory( realtype *pMem, void *cvode_mem, N_Vector y0, N_Vector yp0, mxArray *plhs, int dim1, int dim2 ); + +realtype interpolate( realtype *time, realtype *data, int n, realtype t, int type ); +realtype maximum( realtype x, realtype y ); +realtype minimum( realtype x, realtype y ); +realtype intPow( realtype x, int y ); + +#endif diff --git a/odemex/Parser/parserDependencies/Interpolate.m b/odemex/Parser/parserDependencies/Interpolate.m new file mode 100644 index 0000000..21dad30 --- /dev/null +++ b/odemex/Parser/parserDependencies/Interpolate.m @@ -0,0 +1,28 @@ + +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Parser/parserDependencies/analyseFunctionHeader.m b/odemex/Parser/parserDependencies/analyseFunctionHeader.m new file mode 100644 index 0000000..72a5664 --- /dev/null +++ b/odemex/Parser/parserDependencies/analyseFunctionHeader.m @@ -0,0 +1,59 @@ +function [ outVars, inVars, funcName ] = analyseFunctionHeader( string ) + +outVars = {}; +inVars = {}; + +% remove function handle +string = strrep( string, 'function', '' ); + +[ pre post ] = strtok( string, '=' ); + +funcName = fliplr( strtok( fliplr(strtok( post, '(' ) ), ' =' ) ); + +[ tok rem ] = strtok( pre, '[], ' ); +if isempty( tok ) + disp( 'WARNING: No output variable when parsing function' ); +end +while ( ~isempty( rem ) | ~isempty( tok ) ) + outVars = { outVars{:}, tok }; + [ tok rem ] = strtok( rem, '[], ' ); +end + +post = grabBetweenBrackets( post ); +[ tok rem ] = strtok( post, '[], ' ); + +if isempty( tok ) + disp( 'WARNING: No input variable when parsing function' ); +end +while ( ~isempty( rem ) | ~isempty( tok ) ) + inVars = { inVars{:}, tok }; + [ tok rem ] = strtok( rem, '[], ' ); +end + +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Parser/parserDependencies/dec1.m b/odemex/Parser/parserDependencies/dec1.m new file mode 100644 index 0000000..a1da31d --- /dev/null +++ b/odemex/Parser/parserDependencies/dec1.m @@ -0,0 +1,41 @@ +% Attempt to subtract 1 and evaluate. If it cannot be evaluated return a +% string expression + +function string = dec1( string ) + +string = [ '(' string ') - 1' ]; + +try + tmp = eval( string ); + string = num2str( tmp ); +catch + +end + +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Parser/parserDependencies/grabBetweenBrackets.m b/odemex/Parser/parserDependencies/grabBetweenBrackets.m new file mode 100644 index 0000000..1ecb14b --- /dev/null +++ b/odemex/Parser/parserDependencies/grabBetweenBrackets.m @@ -0,0 +1,58 @@ +function [ between, rest ] = grabBetweenBrackets( inputString ) + +brackets = 1; +ptr = 1; +between = ''; + +while( ~strcmp( inputString( ptr ), '(' ) ) + ptr = ptr + 1; +end + +ptr = ptr + 1; +startPtr = ptr; + +while ( ( brackets > 0 ) & ( ptr <= length( inputString ) ) ) + if strcmp( inputString( ptr ), '(' ) + brackets = brackets + 1; + end + if strcmp( inputString( ptr ), ')' ) + brackets = brackets - 1; + end + ptr = ptr + 1; +end + +if ( brackets > 0 ) + disp( sprintf( 'WARNING: No closing bracket detected.\nRelevant code: %s!\n', inputString ) ); +end + +between = inputString( startPtr : ptr - 2 ); +rest = inputString( ptr : end ); + + +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Parser/parserDependencies/grabFieldNames.m b/odemex/Parser/parserDependencies/grabFieldNames.m new file mode 100644 index 0000000..bc2361b --- /dev/null +++ b/odemex/Parser/parserDependencies/grabFieldNames.m @@ -0,0 +1,31 @@ +function [ names, indices ] = grabFieldNames( inputStruct ) + + names = fieldnames( inputStruct ); + [ names, indices ] = sortList( names ); +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Parser/parserDependencies/grabIndices.m b/odemex/Parser/parserDependencies/grabIndices.m new file mode 100644 index 0000000..501aee7 --- /dev/null +++ b/odemex/Parser/parserDependencies/grabIndices.m @@ -0,0 +1,33 @@ +function [ indices ] = grabIndices( names, struct ) + + for a = 1 : length( names ) + indices{ a } = getfield( struct, names{a} ); + end +end +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Parser/parserDependencies/intPow.m b/odemex/Parser/parserDependencies/intPow.m new file mode 100644 index 0000000..529782a --- /dev/null +++ b/odemex/Parser/parserDependencies/intPow.m @@ -0,0 +1,30 @@ +function y = intPow( double, int ) + y = double ^ int; + +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Parser/parserDependencies/jacGen1.m b/odemex/Parser/parserDependencies/jacGen1.m new file mode 100644 index 0000000..b3d0522 --- /dev/null +++ b/odemex/Parser/parserDependencies/jacGen1.m @@ -0,0 +1,125 @@ + +%modelStruct = mStruct; +eval( sprintf( '%s = mStruct;', structVar ) ); + +jacFileName = [ parserPath '/outputC/model/aJac.c' ]; + +disp( 'Computing RHS derivatives ...' ); +for a = 1 : nStates + eval( sprintf( 'syms x_%d;', a - 1 ) ); + eval( sprintf( 'x(%d) = x_%d;', a, a - 1 ) ); +end + +try + for a = 1 : length( fieldnames( mStruct.u ) ) + eval( sprintf( 'syms u_%d;', a - 1 ) ); + eval( sprintf( 'u(%d) = u_%d;', a, a - 1 ) ); + end +catch +end + +for a = 1 : nStates + nPars + for b = 1 : nStates + eval( sprintf( 'syms s_%d_%d;', a - 1 , b - 1 ) ); + eval( sprintf( 'S(%d, %d) = s_%d_%d;', b, a, a - 1, b - 1) ); + end +end + +for a = 1 : nPars + eval( sprintf( 'syms p_%d;', a - 1 ) ); + eval( sprintf( 'p(%d) = p_%d;', a, a - 1 ) ); +end + +m_file = textread( odeInput, '%s', 'delimiter', '\n' ); + +m_file = sprintf( '%s\n', m_file{2:end} ); +eval( m_file ); + +for a = 1 : nStates + for b = 1 : nStates + dfdy( b, a ) = diff( dx(a), x(b) ); + end +end + +for a = 1 : nStates + for b = 1 : nPars + dfdp( a, b ) = diff( dx(a), p(b) ); + end +end + +for a = 1 : nStates + dfdp( a, a+nPars ) = 0; +end + +if ( aJac == 1 ) + + %% Generate the analytical sensitivity equations + disp( 'Generating sensitivity equations ...' ); + ccode( ( dfdy.' * S + dfdp ).', 'file', jacFileName ); + + disp( 'Reading sensitivity equation C-file' ); + c_file = textread( jacFileName, '%s', 'delimiter', '\n' ); + + disp( 'Replacing state names' ); + c_file = regexprep( c_file, 'MatrixWithNoName\[(\d*)\]', 'NV_DATA_S(ySdot[$1])' ); + c_file = regexprep( c_file, 'p_(\d*)', 'data->p[$1]' ); + c_file = regexprep( c_file, 'u_(\d*)', 'data->u[$1]' ); + c_file = regexprep( c_file, 'x_(\d*)', 'stateVars[$1]' ); + c_file = regexprep( c_file, 's_(\d*)_(\d*)', 'NV_DATA_S(yS[$1])[$2]' ); + c_file = regexprep( c_file, '^t0 = ', '' ); + + fullstring = sprintf( '%s\n', c_file{:} ); + + [startIndex, endIndex, tokIndex, matchStr, tokenStr] = regexp( fullstring, 't(\d*)' ); + + maxT = 0; + for a = 1 : length( tokenStr ) + val = str2num( tokenStr{a}{1} ); + maxT = max( [ val, maxT ] ); + end + + preString = sprintf('int sensRhs (int Ns, realtype t, N_Vector y, N_Vector ydot, N_Vector *yS, N_Vector *ySdot, void *user_data, N_Vector tmp1, N_Vector tmp2) {\n\n'); + for a = 1 : maxT + preString = sprintf( '%srealtype t%d;', preString, a ); + end + postString = sprintf( '\nstruct mData *data = ( struct mData * ) user_data;\nrealtype *stateVars;\nstateVars = NV_DATA_S(y);\n\n' ); + sensRHS = sprintf( '%s\n%s\n%s\nreturn 0;\n};\n', preString, postString, fullstring ); + +else + sensRHS = ''; +end + +if ( fJac == 1 ) + %% Analytical Jacobian + disp( 'Generating jacobian ...' ); + %ccode( (dfdy.').', 'file', jacFileName ); + ccode( (dfdy.').', 'file', jacFileName ); + %ccode( (sym(0).').', 'file', jacFileName ); + + disp( 'Reading jacobian C-file' ); + c_file = textread( jacFileName, '%s', 'delimiter', '\n' ); + + disp( 'Replacing state names' ); + c_file = regexprep( c_file, 'MatrixWithNoName\[(\d*)\]', 'DENSE_COL(Jac,$1)' ); + c_file = regexprep( c_file, 'p_(\d*)', 'data->p[$1]' ); + c_file = regexprep( c_file, 'u_(\d*)', 'data->u[$1]' ); + c_file = regexprep( c_file, 'x_(\d*)', 'stateVars[$1]' ); + c_file = regexprep( c_file, '^t0 = ', '' ); + + fullstring = sprintf( '%s\n', c_file{:} ); + + [startIndex, endIndex, tokIndex, matchStr, tokenStr] = regexp( fullstring, 't(\d*)' ); + + maxT = 0; + for a = 1 : length( tokenStr ) + val = str2num( tokenStr{a}{1} ); + maxT = max( [ val, maxT ] ); + end + + preString = sprintf('int fJac (long int N, realtype t, N_Vector y, N_Vector fy, DlsMat Jac, void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) {\n\n'); + for a = 1 : maxT + preString = sprintf( '%srealtype t%d;', preString, a ); + end + postString = sprintf( '\nstruct mData *data = ( struct mData * ) user_data;\nrealtype *stateVars;\nstateVars = NV_DATA_S(y);\n\n' ); + sensRHS = sprintf( '%s%s\n%s\n%s\nreturn 0;\n};\n', sensRHS, preString, postString, fullstring ); +end \ No newline at end of file diff --git a/odemex/Parser/parserDependencies/maximum.m b/odemex/Parser/parserDependencies/maximum.m new file mode 100644 index 0000000..616b877 --- /dev/null +++ b/odemex/Parser/parserDependencies/maximum.m @@ -0,0 +1,29 @@ +function maxi = maximum( a, b ) + maxi = max( a(1), b(1) ); +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Parser/parserDependencies/minimum.m b/odemex/Parser/parserDependencies/minimum.m new file mode 100644 index 0000000..ae4b3ff --- /dev/null +++ b/odemex/Parser/parserDependencies/minimum.m @@ -0,0 +1,29 @@ +function mini = minimum( a, b ) + mini = min( a(1), b(1) ); +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Parser/parserDependencies/pow.m b/odemex/Parser/parserDependencies/pow.m new file mode 100644 index 0000000..8012a5f --- /dev/null +++ b/odemex/Parser/parserDependencies/pow.m @@ -0,0 +1,30 @@ +function y = intPow( double1, double2 ) + y = double1 ^ double2; + +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Parser/parserDependencies/printList.m b/odemex/Parser/parserDependencies/printList.m new file mode 100644 index 0000000..28e9a0d --- /dev/null +++ b/odemex/Parser/parserDependencies/printList.m @@ -0,0 +1,39 @@ +% Print unique members in comma separated value ingoring the ones found in +% invars. + +function l = printList( llist, add ) + + l = sprintf( 'realtype %s ', llist{1} ); + + for b = 2 : length( llist ) + l = sprintf( '%s, %s %s', l, add, llist{b} ); + end + +end +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Parser/parserDependencies/printUniqueList.m b/odemex/Parser/parserDependencies/printUniqueList.m new file mode 100644 index 0000000..dfae851 --- /dev/null +++ b/odemex/Parser/parserDependencies/printUniqueList.m @@ -0,0 +1,60 @@ +% Print unique members in comma separated value ingoring the ones found in +% invars. + +function l = printUniqueList( llist, invars, idtype ) + + llist = unique( llist ); + + if nargin > 1 + for b = 1 : length( invars ) + a = 1; + while( a <= length( llist ) ) + if strcmp( llist(a), invars(b) ) + llist( a ) = []; + else + a = a + 1; + end + end + end + end + + if nargin < 3, idtype = 'realtype'; end + + if ~isempty( llist ) + l = sprintf( '%s %s ', idtype, llist{1} ); + + for b = 2 : length( llist ) + l = sprintf( '%s, %s %s', l, llist{b} ); + end + else + l = ''; + end + +end +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Parser/parserDependencies/replaceStructNames.m b/odemex/Parser/parserDependencies/replaceStructNames.m new file mode 100644 index 0000000..38c04c9 --- /dev/null +++ b/odemex/Parser/parserDependencies/replaceStructNames.m @@ -0,0 +1,35 @@ +% This function seeks patterns of structName.name and replaces them with +% the corresponding indices in the list indices. + +function [ string ] = replaceStructNames( string, names, indices, structName ) + + for a = 1 : length( names ) + string = regexprep( string, sprintf( '\\w*%s[.]%s', structName, names{a} ), num2str( indices{a}(1) ) ); + end +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Parser/parserDependencies/sortList.m b/odemex/Parser/parserDependencies/sortList.m new file mode 100644 index 0000000..bad9274 --- /dev/null +++ b/odemex/Parser/parserDependencies/sortList.m @@ -0,0 +1,40 @@ +function [ outList, M ] = sortList( list ) + for a = 1 : length( list ) + sizes(a) = length( list{a} ); + end + + [N, I] = sort( -sizes ); + + outList(1:length(I)) = list( I ); + + for a = 1 : length( list ) + M(a) = find( I == a ); + end +end +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/Parser/parserDependencies/strtok2.m b/odemex/Parser/parserDependencies/strtok2.m new file mode 100644 index 0000000..57550e9 --- /dev/null +++ b/odemex/Parser/parserDependencies/strtok2.m @@ -0,0 +1,41 @@ +% Function that grabs a token, but shows you which chars were removed + +function [ token, remain, tokensLost ] = strtok2( string, tokens ) + + l = length( string ); + [ token, remain ] = strtok( string, tokens ); + + missing = length( string ) - length( token ) - length( remain ); + + tokensLost = string( 1 : missing ); + + + + +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/SBML Tools/SBMLtoM.m b/odemex/SBML Tools/SBMLtoM.m new file mode 100644 index 0000000..dd3ec59 --- /dev/null +++ b/odemex/SBML Tools/SBMLtoM.m @@ -0,0 +1,260 @@ +% This function converts an SBML file into a MATLAB file, the parser can +% handle. It also returns the initial conditions and all the necessary +% structures to convert to C. +% +% function [ modelStruct, p, x0, u0 ] = SBMLToM( inDir, inFn, outDir, outFn ) +% +% Input Arguments: +% inDir input directory (location of the SBML files) +% inFn input filename +% outDir output directory (where to put the M-file) +% outFn output filename (of the m-file) +% +% Optional: constantList (cell array of parameters that should be treated as +% constants) +% +% Note: SBML toolbox for MATLAB needs to be installed for this to work! +% See http://sbml.org/Software/SBMLToolbox +% +% Authors: J Vanlier, R Oosterhof +function [ modelStruct, p, x0, u0 ] = SBMLToM( inDir, inFn, outDir, outFn, constantList, lumpList ) + + model = translateSBML( [ inDir '/' inFn ] ); + + b = 1; c = 1; u0 = []; + for a = 1 : length( model.species ) + if model.species(a).constant == 0 + x0( c ) = model.species(a).initialConcentration; + eval( sprintf( 'modelStruct.s.%s = %d;', model.species(a).id, c ) ); + c = c + 1; + else + u0( b ) = model.species(a).initialConcentration; + eval( sprintf( 'modelStruct.u.%s = %d;', model.species(a).id, b ) ); + b = b + 1; + end + end + nStates = c; + nInputs = b; + + lumpIDs = zeros( length( lumpList ), 1 ); + + for a = 1 : length( model.compartment ) + eval( sprintf( 'modelStruct.c.%s = %.15f;', model.compartment(1).id, model.compartment(1).size ) ); + end + + c = 1; + for a = 1 : length( model.reaction ) + try + for b = 1 : length( model.reaction(a).kineticLaw.parameter ) + p( c ) = model.reaction(a).kineticLaw.parameter(b).value; + eval( sprintf( 'modelStruct.p.%s = %d;', model.reaction(a).kineticLaw.parameter(b).id, c ) ); + c = c + 1; + end + catch + end + end + + try + for a = 1 : length( model.rule ) + parOmit{a} = model.rule(a).variable; + rulesStr{a} = avoidIntegerDivision( strrep( model.rule(a).formula, 'power', 'pow' ) ); + end + + change = 1; + while( change ) + change = 0; + for a = 1 : length( rulesStr ) + for b = a : length( rulesStr ) + if ~isempty( findstr( rulesStr{a}, parOmit{b} ) ) + disp( 'Switching rules due to interdependency' ); + tmp1 = rulesStr{a}; + tmp2 = parOmit{a}; + rulesStr{a} = rulesStr{b}; + rulesStr{b} = tmp1; + parOmit{a} = parOmit{b}; + parOmit{b} = tmp2; + change = 1; + end + end + end + end + catch + end + + % Added by ir. R. Oosterhof altered by ir J. Vanlier + %if ~isfield( 'modelStruct', 'p' ) + for a = 1 : length( model.parameter ) + scmp = 0; + for b = 1 : length( parOmit ) + scmp = scmp | ( strcmp( model.parameter(a).id, parOmit{b} ) ); + end + + if ~scmp + isconstant = 0; + for d = 1 : length( constantList ) + if findstr( model.parameter(a).id, constantList{d} ) + eval( sprintf( 'modelStruct.c.%s = %.15f;', model.parameter(a).id, model.parameter(a).value ) ); + isconstant = 1; + end + end + + if ~isconstant + % If this is in one of the lump lists then it is a lumped + % parameter + lumped = 0; + for q = 1 : length( lumpList ) + if sum( find( cell2mat( regexp(model.parameter(a).id, lumpList{q} ) ) == 1 ) ) + % First time this lumped group comes around + if lumpIDs(q) == 0 + lumpIDs(q) = c; + + p( c ) = model.parameter(a).value; + c = c + 1; + end + lumped = lumpIDs(q); + end + end + + if lumped == 0 + p( c ) = model.parameter(a).value; + eval( sprintf( 'modelStruct.p.%s = %d;', model.parameter(a).id, c ) ); + c = c + 1; + else + eval( sprintf( 'modelStruct.p.%s = %d;', model.parameter(a).id, lumped ) ); + end + end + end + end + + declarations{ 1 } = sprintf( 'function dx = mymodel2(t, x, p, u, modelStruct)\n' ); + c = 2; + names = fieldnames( modelStruct.s ); + for a = 1 : length( names ) + declarations{ c } = sprintf( '\t%s = x( modelStruct.s.%s );\n', names{ a }, names{ a } ); + c = c + 1; + end + + try + names = fieldnames( modelStruct.u ); + for a = 1 : length( names ) + declarations{ c } = sprintf( '\t%s = u( modelStruct.u.%s );\n', names{ a }, names{ a } ); + c = c + 1; + end + catch + end + + names = fieldnames( modelStruct.c ); + for a = 1 : length( names ) + declarations{ c } = sprintf( '\t%s = modelStruct.c.%s;\n', names{ a }, names{ a } ); + c = c + 1; + end + + names = fieldnames( modelStruct.p ); + for a = 1 : length( names ) + declarations{ c } = sprintf( '\t%s = p( modelStruct.p.%s );\n', names{ a }, names{ a } ); + c = c + 1; + end + + try + for a = 1 : length( rulesStr ) + rules{a} = sprintf( '\t%s = %s;\n', parOmit{a}, rulesStr{a} ); + end + catch + rules = {}; + end + + names = fieldnames( modelStruct.s ); + for a = 1 : nStates - 1 + odes{ a } = sprintf( '\tdx( modelStruct.s.%s ) = ', names{a} ); + end + + for a = 1 : length( model.reaction ) + for b = 1 : length( model.reaction(a).reactant ) + try + speciesID = eval( sprintf( 'modelStruct.s.%s', model.reaction(a).reactant(b).species ) ); + odes{ speciesID } = sprintf( '%s - %d * %s', odes{ speciesID }, model.reaction(a).reactant(b).stoichiometry, model.reaction(a).id ); + catch + end + end + for b = 1 : length( model.reaction(a).product ) + try + speciesID = eval( sprintf( 'modelStruct.s.%s', model.reaction(a).product(b).species ) ); + odes{ speciesID } = sprintf( '%s + %d * %s', odes{ speciesID }, model.reaction(a).product(b).stoichiometry, model.reaction(a).id ); + catch + end + end + end + + for a = 1 : nStates - 1 + % Added by ir. R. Oosterhof + if isspace( odes{ a }(end) ) + odes{ a } = sprintf( '%s0;\n', odes{ a } ); + else + % + odes{ a } = sprintf( '%s;\n', odes{ a } ); + end + end + + for a = 1 : length( model.reaction ) + reactions{a} = sprintf( '\t%s = %s;\n', model.reaction(a).id, model.reaction(a).kineticLaw.math ); + end + + for a = 1 : length( model.functionDefinition ) + [ junk, tok ] = strtok( model.functionDefinition.math, '(' ); + [ toka, rema ] = strtok( tok(2:end-1), '(' ); + commas = findstr( toka, ',' ); + inVars = toka( 1 : commas( end ) - 1 ); + func = [ toka( commas( end ) + 1 : end ) rema ]; + + funcNames{ a } = model.functionDefinition.id; + funcs{ a } = sprintf( 'function returnedValue = %s( %s )\n\n\treturnedValue = %s;', model.functionDefinition.id, inVars, func ); + end + + odefile = [ declarations{:} rules{:} sprintf( '\n\n\t%%%% Flux equations\n' ) reactions{:} sprintf( '\n\n\t%%%% State equations\n' ) odes{:} sprintf( '\n\n\tdx = dx(:);' ) ]; + + try + d = fopen( [ outDir '/' outFn ], 'w' ); + fprintf( d, odefile ); + fclose( d ); + + if exist( 'funcNames' ) ~= 0 + for a = 1 : length( funcNames ) + d = fopen( [ outDir '/' funcNames{ a } '.m' ], 'w' ); + fprintf( d, funcs{ a } ); + fclose( d ); + end + end + catch + disp( 'Error writing file: Correct path?' ); + end + + + + +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/SBML Tools/avoidIntegerDivision.m b/odemex/SBML Tools/avoidIntegerDivision.m new file mode 100644 index 0000000..4f6d3c7 --- /dev/null +++ b/odemex/SBML Tools/avoidIntegerDivision.m @@ -0,0 +1,24 @@ +function str = avoidIntegerDivision( string ) + + expressionTokens = '&()[]/*+-^@ %<>,;={}'; + + str = []; + + [ tok, remainder, z ] = strtok2( string, expressionTokens ); + + while ( ( ~isempty( remainder ) ) || ( ~isempty( tok ) ) ) + + no = str2num( tok ); + if ~isempty( no ) + if round( no ) == no + tok = sprintf( '%d.0', no ); + end + end + + str = [ str, z, tok ]; + + [ tok, remainder, z ] = strtok2( remainder, expressionTokens ); + + end + + str = [ str, z, tok ]; \ No newline at end of file diff --git a/odemex/SBML Tools/strtok2.m b/odemex/SBML Tools/strtok2.m new file mode 100644 index 0000000..44e6f95 --- /dev/null +++ b/odemex/SBML Tools/strtok2.m @@ -0,0 +1,13 @@ +% Function that grabs a token, but shows you which chars were removed + +function [ token, remain, tokensLost ] = strtok2( string, tokens ) + + l = length( string ); + [ token, remain ] = strtok( string, tokens ); + + missing = length( string ) - length( token ) - length( remain ); + + tokensLost = string( 1 : missing ); + + + diff --git a/odemex/SBML_Files/HIF_4.xml b/odemex/SBML_Files/HIF_4.xml new file mode 100644 index 0000000..c4d82f5 --- /dev/null +++ b/odemex/SBML_Files/HIF_4.xml @@ -0,0 +1,226 @@ + + + + + + + + + + + v + v + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + c + + influx + v + + + + + + + + + + + + + + + + + + + + + c + + + + + ARNT_complexation_fwd + HIF_1a + ARNT + + + + ARNT_complexation_bwd + HIF_1a_ARNT + + + + + + + + + + + + + + + + + + + + + + + c + + + + + HRE_complexation_fwd + HRE + HIF_1a_ARNT + + + + HRE_complexation_bwd + HIF_1a_ARNT_HRE + + + + + + + + + + + + + + + + + + + + + + + c + + + + + PHD_complexation_fwd + HIF_1a + PHD + + + + PHD_complexation_bwd + HIF_1a_PHD + + + + + + + + + + + + + + + + + + + + + + + + c + HIF_hydroxylation_fwd + HIF_1a_PHD + O2 + + + + + + + + + + + + + + + + c + HIF_degradation_fwd + HIF_1a_OH + + + + + + + + + + diff --git a/odemex/SBML_Files/model.xml b/odemex/SBML_Files/model.xml new file mode 100644 index 0000000..f9592e5 --- /dev/null +++ b/odemex/SBML_Files/model.xml @@ -0,0 +1,806 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + krbEGF + EGF + freeEGFReceptor + + + + + + + + + + + + + + + + + kruEGF + boundEGFReceptor + + + + + + + + + + + + + + + + + krbNGF + NGF + freeNGFReceptor + + + + + + + + + + + + + + + + + kruNGF + boundNGFReceptor + + + + + + + + + + + + + + + + + + + + + kEGF + boundEGFReceptor + SosInactive + + + + SosInactive + KmEGF + + + + + + + + + + + + + + + + + + + + + + kNGF + boundNGFReceptor + SosInactive + + + + SosInactive + KmNGF + + + + + + + + + + + + + + + + + + + + + + kdSos + P90RskActive + SosActive + + + + SosActive + KmdSos + + + + + + + + + + + + + + + + + + + + + + kSos + SosActive + RasInactive + + + + RasInactive + KmSos + + + + + + + + + + + + + + + + + + + + + + kRasGap + RasGapActive + RasActive + + + + RasActive + KmRasGap + + + + + + + + + + + + + + + + + + + + + + kRasToRaf1 + RasActive + Raf1Inactive + + + + Raf1Inactive + KmRasToRaf1 + + + + + + + + + + + + + + + + + + + + + + kpRaf1 + Raf1Active + MekInactive + + + + MekInactive + KmpRaf1 + + + + + + + + + + + + + + + + + + + + + + kpBRaf + BRafActive + MekInactive + + + + MekInactive + KmpBRaf + + + + + + + + + + + + + + + + + + + + + + kpMekCytoplasmic + MekActive + ErkInactive + + + + ErkInactive + KmpMekCytoplasmic + + + + + + + + + + + + + + + + + + + + + + kdMek + PP2AActive + MekActive + + + + MekActive + KmdMek + + + + + + + + + + + + + + + + + + + + + + kdErk + PP2AActive + ErkActive + + + + ErkActive + KmdErk + + + + + + + + + + + + + + + + + + + + + + kdRaf1 + Raf1PPtase + Raf1Active + + + + Raf1Active + KmdRaf1 + + + + + + + + + + + + + + + + + + + + + + kpP90Rsk + ErkActive + P90RskInactive + + + + P90RskInactive + KmpP90Rsk + + + + + + + + + + + + + + + + + + + + + + kPI3K + boundEGFReceptor + PI3KInactive + + + + PI3KInactive + KmPI3K + + + + + + + + + + + + + + + + + + + + + + kPI3KRas + RasActive + PI3KInactive + + + + PI3KInactive + KmPI3KRas + + + + + + + + + + + + + + + + + + + + + + kAkt + PI3KActive + AktInactive + + + + AktInactive + KmAkt + + + + + + + + + + + + + + + + + + + + + + kdRaf1ByAkt + AktActive + Raf1Active + + + + Raf1Active + KmRaf1ByAkt + + + + + + + + + + + + + + + + + + + + + + kC3GNGF + boundNGFReceptor + C3GInactive + + + + C3GInactive + KmC3GNGF + + + + + + + + + + + + + + + + + + + + + + kC3G + C3GActive + Rap1Inactive + + + + Rap1Inactive + KmC3G + + + + + + + + + + + + + + + + + + + + + + kRapGap + RapGapActive + Rap1Active + + + + Rap1Active + KmRapGap + + + + + + + + + + + + + + + + + + + + + + kRap1ToBRaf + Rap1Active + BRafInactive + + + + BRafInactive + KmRap1ToBRaf + + + + + + + + + + + + + + + + + + + + + + kdBRaf + Raf1PPtase + BRafActive + + + + BRafActive + KmdBRaf + + + + + + + + diff --git a/odemex/addPaths.m b/odemex/addPaths.m new file mode 100644 index 0000000..dc3b18c --- /dev/null +++ b/odemex/addPaths.m @@ -0,0 +1,52 @@ +% List of functions within the toolboxes +% +% Compiling ODE's +% convertToC( mStruct, odeInput, dependencies, options ) +% compileC( outputName ) +% +% Generic Functions +% nJac( func, pars, dx, subVec ) +% +% Monte Carlo Markov Chains +% [ chain, energy, nAcc, nRej ] = mcmcCoV( funVec, parameters, methodOpts, numSteps, (lb), (ub), (Aineq), (Bineq), (burnIn) ) +% [ CoV, scale ] = tuneChain( fun, initPars, CoV, iter, (lb), (ub), (A), (B), (burnIn), (minSteps) ) +% +% Profile Likelihoods +% [ plOut, sse ] = PL( func, initPar, param, outer, thresh, loga, opts, minStep, maxStep, minChange, maxChange ) + +q = dir; +cdir = [ pwd '/' ]; +for a = 1 : length( q ) + if q(a).isdir == 1 + if ( q(a).isdir ~= '.' ) || ( q(a).isdir ~= '..' ) + addpath( [ cdir, q(a).name ] ); + end + end +end +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/observerFunctions/ccode/jac.c b/odemex/observerFunctions/ccode/jac.c new file mode 100644 index 0000000..5822cb9 --- /dev/null +++ b/odemex/observerFunctions/ccode/jac.c @@ -0,0 +1,289 @@ +#include "objfn.h" + + +void jacobian(double *jac, double *s, double *p, double *d, double *u, double *S ) { + jac[(0)*(N_OBS)+(0)] = s[(1-1)*N_STATES+(1-1)]*u[1-1]*(p[N_PARS+1-1]+1.0)+S[(1-1)*SENSDIM+(1-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(0)*(N_OBS)+(1)] = s[(2-1)*N_STATES+(1-1)]*u[1-1]*(p[N_PARS+1-1]+1.0)+S[(2-1)*SENSDIM+(1-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(0)*(N_OBS)+(2)] = s[(3-1)*N_STATES+(1-1)]*u[1-1]*(p[N_PARS+1-1]+1.0)+S[(3-1)*SENSDIM+(1-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(0)*(N_OBS)+(3)] = s[(4-1)*N_STATES+(1-1)]*u[1-1]*(p[N_PARS+1-1]+1.0)+S[(4-1)*SENSDIM+(1-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(0)*(N_OBS)+(4)] = s[(5-1)*N_STATES+(1-1)]*u[1-1]*(p[N_PARS+1-1]+1.0)+S[(5-1)*SENSDIM+(1-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(0)*(N_OBS)+(5)] = s[(6-1)*N_STATES+(1-1)]*u[1-1]*(p[N_PARS+1-1]+1.0)+S[(6-1)*SENSDIM+(1-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(0)*(N_OBS)+(6)] = s[(7-1)*N_STATES+(1-1)]*u[1-1]*(p[N_PARS+1-1]+1.0)+S[(7-1)*SENSDIM+(1-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(0)*(N_OBS)+(7)] = s[(9-1)*N_STATES+(1-1)]*u[1-1]*(p[N_PARS+1-1]+1.0)+S[(9-1)*SENSDIM+(1-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(0)*(N_OBS)+(8)] = s[(11-1)*N_STATES+(1-1)]*u[1-1]*(p[N_PARS+1-1]+1.0)+S[(11-1)*SENSDIM+(1-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(0)*(N_OBS)+(9)] = s[(12-1)*N_STATES+(1-1)]*u[1-1]*(p[N_PARS+1-1]+1.0)+S[(12-1)*SENSDIM+(1-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(0)*(N_OBS)+(10)] = s[(13-1)*N_STATES+(1-1)]*u[1-1]*(p[N_PARS+1-1]+1.0)+S[(13-1)*SENSDIM+(1-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(0)*(N_OBS)+(11)] = (S[(1-1)*SENSDIM+(1-1)]*p[2-1])/(p[N_PARS+2-1]+1.0)+(S[(1-1)*SENSDIM+(2-1)]*p[2-1])/(p[N_PARS+2-1]+1.0); + jac[(0)*(N_OBS)+(12)] = (S[(13-1)*SENSDIM+(1-1)]*p[2-1])/(p[N_PARS+2-1]+1.0)+(S[(13-1)*SENSDIM+(2-1)]*p[2-1])/(p[N_PARS+2-1]+1.0); + jac[(0)*(N_OBS)+(13)] = (S[(23-1)*SENSDIM+(1-1)]*p[2-1])/(p[N_PARS+2-1]+1.0)+(S[(23-1)*SENSDIM+(2-1)]*p[2-1])/(p[N_PARS+2-1]+1.0); + jac[(0)*(N_OBS)+(14)] = (S[(33-1)*SENSDIM+(1-1)]*p[2-1])/(p[N_PARS+2-1]+1.0)+(S[(33-1)*SENSDIM+(2-1)]*p[2-1])/(p[N_PARS+2-1]+1.0); + jac[(0)*(N_OBS)+(15)] = (S[(43-1)*SENSDIM+(1-1)]*p[2-1])/(p[N_PARS+2-1]+1.0)+(S[(43-1)*SENSDIM+(2-1)]*p[2-1])/(p[N_PARS+2-1]+1.0); + jac[(0)*(N_OBS)+(16)] = (S[(1-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(1-1)*N_STATES+(1-1)])-(S[(1-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(1-1)*N_STATES+(1-1)]*s[(1-1)*N_STATES+(1-1)])*s[(1-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(17)] = (S[(2-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(2-1)*N_STATES+(1-1)])-(S[(2-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(2-1)*N_STATES+(1-1)]*s[(2-1)*N_STATES+(1-1)])*s[(2-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(18)] = (S[(3-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(3-1)*N_STATES+(1-1)])-(S[(3-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(3-1)*N_STATES+(1-1)]*s[(3-1)*N_STATES+(1-1)])*s[(3-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(19)] = (S[(4-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(4-1)*N_STATES+(1-1)])-(S[(4-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(4-1)*N_STATES+(1-1)]*s[(4-1)*N_STATES+(1-1)])*s[(4-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(20)] = (S[(5-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(5-1)*N_STATES+(1-1)])-(S[(5-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(5-1)*N_STATES+(1-1)]*s[(5-1)*N_STATES+(1-1)])*s[(5-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(21)] = (S[(6-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(6-1)*N_STATES+(1-1)])-(S[(6-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(6-1)*N_STATES+(1-1)]*s[(6-1)*N_STATES+(1-1)])*s[(6-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(22)] = (S[(8-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(8-1)*N_STATES+(1-1)])-(S[(8-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(8-1)*N_STATES+(1-1)]*s[(8-1)*N_STATES+(1-1)])*s[(8-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(23)] = (S[(10-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(10-1)*N_STATES+(1-1)])-(S[(10-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(10-1)*N_STATES+(1-1)]*s[(10-1)*N_STATES+(1-1)])*s[(10-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(24)] = (S[(11-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(11-1)*N_STATES+(1-1)])-(S[(11-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(11-1)*N_STATES+(1-1)]*s[(11-1)*N_STATES+(1-1)])*s[(11-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(25)] = (S[(12-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(12-1)*N_STATES+(1-1)])-(S[(12-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(12-1)*N_STATES+(1-1)]*s[(12-1)*N_STATES+(1-1)])*s[(12-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(26)] = (S[(13-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(13-1)*N_STATES+(1-1)])-(S[(13-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(13-1)*N_STATES+(1-1)]*s[(13-1)*N_STATES+(1-1)])*s[(13-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(27)] = (S[(14-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(14-1)*N_STATES+(1-1)])-(S[(14-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(14-1)*N_STATES+(1-1)]*s[(14-1)*N_STATES+(1-1)])*s[(14-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(28)] = (S[(15-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(15-1)*N_STATES+(1-1)])-(S[(15-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(15-1)*N_STATES+(1-1)]*s[(15-1)*N_STATES+(1-1)])*s[(15-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(29)] = (S[(16-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(16-1)*N_STATES+(1-1)])-(S[(16-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(16-1)*N_STATES+(1-1)]*s[(16-1)*N_STATES+(1-1)])*s[(16-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(30)] = (S[(17-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(17-1)*N_STATES+(1-1)])-(S[(17-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(17-1)*N_STATES+(1-1)]*s[(17-1)*N_STATES+(1-1)])*s[(17-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(31)] = (S[(18-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(18-1)*N_STATES+(1-1)])-(S[(18-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(18-1)*N_STATES+(1-1)]*s[(18-1)*N_STATES+(1-1)])*s[(18-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(32)] = (S[(19-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(19-1)*N_STATES+(1-1)])-(S[(19-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(19-1)*N_STATES+(1-1)]*s[(19-1)*N_STATES+(1-1)])*s[(19-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(33)] = (S[(20-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(20-1)*N_STATES+(1-1)])-(S[(20-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(20-1)*N_STATES+(1-1)]*s[(20-1)*N_STATES+(1-1)])*s[(20-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(34)] = (S[(21-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(21-1)*N_STATES+(1-1)])-(S[(21-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(21-1)*N_STATES+(1-1)]*s[(21-1)*N_STATES+(1-1)])*s[(21-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(35)] = (S[(22-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(22-1)*N_STATES+(1-1)])-(S[(22-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(22-1)*N_STATES+(1-1)]*s[(22-1)*N_STATES+(1-1)])*s[(22-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(36)] = (S[(23-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(23-1)*N_STATES+(1-1)])-(S[(23-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(23-1)*N_STATES+(1-1)]*s[(23-1)*N_STATES+(1-1)])*s[(23-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(37)] = (S[(24-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(24-1)*N_STATES+(1-1)])-(S[(24-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(24-1)*N_STATES+(1-1)]*s[(24-1)*N_STATES+(1-1)])*s[(24-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(38)] = (S[(25-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(25-1)*N_STATES+(1-1)])-(S[(25-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(25-1)*N_STATES+(1-1)]*s[(25-1)*N_STATES+(1-1)])*s[(25-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(39)] = (S[(26-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(26-1)*N_STATES+(1-1)])-(S[(26-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(26-1)*N_STATES+(1-1)]*s[(26-1)*N_STATES+(1-1)])*s[(26-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(40)] = (S[(27-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(27-1)*N_STATES+(1-1)])-(S[(27-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(27-1)*N_STATES+(1-1)]*s[(27-1)*N_STATES+(1-1)])*s[(27-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(41)] = (S[(28-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(28-1)*N_STATES+(1-1)])-(S[(28-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(28-1)*N_STATES+(1-1)]*s[(28-1)*N_STATES+(1-1)])*s[(28-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(42)] = (S[(29-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(29-1)*N_STATES+(1-1)])-(S[(29-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(29-1)*N_STATES+(1-1)]*s[(29-1)*N_STATES+(1-1)])*s[(29-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(43)] = (S[(30-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(30-1)*N_STATES+(1-1)])-(S[(30-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(30-1)*N_STATES+(1-1)]*s[(30-1)*N_STATES+(1-1)])*s[(30-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(44)] = (S[(31-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(31-1)*N_STATES+(1-1)])-(S[(31-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(31-1)*N_STATES+(1-1)]*s[(31-1)*N_STATES+(1-1)])*s[(31-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(45)] = (S[(32-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(32-1)*N_STATES+(1-1)])-(S[(32-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(32-1)*N_STATES+(1-1)]*s[(32-1)*N_STATES+(1-1)])*s[(32-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(46)] = (S[(33-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(33-1)*N_STATES+(1-1)])-(S[(33-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(33-1)*N_STATES+(1-1)]*s[(33-1)*N_STATES+(1-1)])*s[(33-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(47)] = (S[(34-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(34-1)*N_STATES+(1-1)])-(S[(34-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(34-1)*N_STATES+(1-1)]*s[(34-1)*N_STATES+(1-1)])*s[(34-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(48)] = (S[(35-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(35-1)*N_STATES+(1-1)])-(S[(35-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(35-1)*N_STATES+(1-1)]*s[(35-1)*N_STATES+(1-1)])*s[(35-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(49)] = (S[(36-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(36-1)*N_STATES+(1-1)])-(S[(36-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(36-1)*N_STATES+(1-1)]*s[(36-1)*N_STATES+(1-1)])*s[(36-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(50)] = (S[(37-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(37-1)*N_STATES+(1-1)])-(S[(37-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(37-1)*N_STATES+(1-1)]*s[(37-1)*N_STATES+(1-1)])*s[(37-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(51)] = (S[(38-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(38-1)*N_STATES+(1-1)])-(S[(38-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(38-1)*N_STATES+(1-1)]*s[(38-1)*N_STATES+(1-1)])*s[(38-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(52)] = (S[(39-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(39-1)*N_STATES+(1-1)])-(S[(39-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(39-1)*N_STATES+(1-1)]*s[(39-1)*N_STATES+(1-1)])*s[(39-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(53)] = (S[(40-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(40-1)*N_STATES+(1-1)])-(S[(40-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(40-1)*N_STATES+(1-1)]*s[(40-1)*N_STATES+(1-1)])*s[(40-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(54)] = (S[(41-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(41-1)*N_STATES+(1-1)])-(S[(41-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(41-1)*N_STATES+(1-1)]*s[(41-1)*N_STATES+(1-1)])*s[(41-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(55)] = (S[(42-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(42-1)*N_STATES+(1-1)])-(S[(42-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(42-1)*N_STATES+(1-1)]*s[(42-1)*N_STATES+(1-1)])*s[(42-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(56)] = (S[(43-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(43-1)*N_STATES+(1-1)])-(S[(43-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(43-1)*N_STATES+(1-1)]*s[(43-1)*N_STATES+(1-1)])*s[(43-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(57)] = (S[(44-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(44-1)*N_STATES+(1-1)])-(S[(44-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(44-1)*N_STATES+(1-1)]*s[(44-1)*N_STATES+(1-1)])*s[(44-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(58)] = (S[(45-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(45-1)*N_STATES+(1-1)])-(S[(45-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(45-1)*N_STATES+(1-1)]*s[(45-1)*N_STATES+(1-1)])*s[(45-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(59)] = (S[(46-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(46-1)*N_STATES+(1-1)])-(S[(46-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(46-1)*N_STATES+(1-1)]*s[(46-1)*N_STATES+(1-1)])*s[(46-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(60)] = (S[(47-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(47-1)*N_STATES+(1-1)])-(S[(47-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(47-1)*N_STATES+(1-1)]*s[(47-1)*N_STATES+(1-1)])*s[(47-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(61)] = (S[(48-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(48-1)*N_STATES+(1-1)])-(S[(48-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(48-1)*N_STATES+(1-1)]*s[(48-1)*N_STATES+(1-1)])*s[(48-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(62)] = (S[(49-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(49-1)*N_STATES+(1-1)])-(S[(49-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(49-1)*N_STATES+(1-1)]*s[(49-1)*N_STATES+(1-1)])*s[(49-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(63)] = (S[(50-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(50-1)*N_STATES+(1-1)])-(S[(50-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(50-1)*N_STATES+(1-1)]*s[(50-1)*N_STATES+(1-1)])*s[(50-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(64)] = (S[(51-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(51-1)*N_STATES+(1-1)])-(S[(51-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(51-1)*N_STATES+(1-1)]*s[(51-1)*N_STATES+(1-1)])*s[(51-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(65)] = (S[(52-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(52-1)*N_STATES+(1-1)])-(S[(52-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(52-1)*N_STATES+(1-1)]*s[(52-1)*N_STATES+(1-1)])*s[(52-1)*N_STATES+(2-1)])/p[2-1]; + jac[(0)*(N_OBS)+(66)] = (S[(53-1)*SENSDIM+(2-1)]*p[3-1])/(p[2-1]*s[(53-1)*N_STATES+(1-1)])-(S[(53-1)*SENSDIM+(1-1)]*p[3-1]*1.0/(s[(53-1)*N_STATES+(1-1)]*s[(53-1)*N_STATES+(1-1)])*s[(53-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(0)] = S[(1-1)*SENSDIM+(3-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(1)*(N_OBS)+(1)] = S[(2-1)*SENSDIM+(3-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(1)*(N_OBS)+(2)] = S[(3-1)*SENSDIM+(3-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(1)*(N_OBS)+(3)] = S[(4-1)*SENSDIM+(3-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(1)*(N_OBS)+(4)] = S[(5-1)*SENSDIM+(3-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(1)*(N_OBS)+(5)] = S[(6-1)*SENSDIM+(3-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(1)*(N_OBS)+(6)] = S[(7-1)*SENSDIM+(3-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(1)*(N_OBS)+(7)] = S[(9-1)*SENSDIM+(3-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(1)*(N_OBS)+(8)] = S[(11-1)*SENSDIM+(3-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(1)*(N_OBS)+(9)] = S[(12-1)*SENSDIM+(3-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(1)*(N_OBS)+(10)] = S[(13-1)*SENSDIM+(3-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(1)*(N_OBS)+(11)] = (-d[1-1]+s[(1-1)*N_STATES+(1-1)]+s[(1-1)*N_STATES+(2-1)])/(p[N_PARS+2-1]+1.0)+(S[(1-1)*SENSDIM+(3-1)]*p[2-1])/(p[N_PARS+2-1]+1.0)+(S[(1-1)*SENSDIM+(4-1)]*p[2-1])/(p[N_PARS+2-1]+1.0); + jac[(1)*(N_OBS)+(12)] = (-d[2-1]+s[(13-1)*N_STATES+(1-1)]+s[(13-1)*N_STATES+(2-1)])/(p[N_PARS+2-1]+1.0)+(S[(13-1)*SENSDIM+(3-1)]*p[2-1])/(p[N_PARS+2-1]+1.0)+(S[(13-1)*SENSDIM+(4-1)]*p[2-1])/(p[N_PARS+2-1]+1.0); + jac[(1)*(N_OBS)+(13)] = (-d[3-1]+s[(23-1)*N_STATES+(1-1)]+s[(23-1)*N_STATES+(2-1)])/(p[N_PARS+2-1]+1.0)+(S[(23-1)*SENSDIM+(3-1)]*p[2-1])/(p[N_PARS+2-1]+1.0)+(S[(23-1)*SENSDIM+(4-1)]*p[2-1])/(p[N_PARS+2-1]+1.0); + jac[(1)*(N_OBS)+(14)] = (-d[4-1]+s[(33-1)*N_STATES+(1-1)]+s[(33-1)*N_STATES+(2-1)])/(p[N_PARS+2-1]+1.0)+(S[(33-1)*SENSDIM+(3-1)]*p[2-1])/(p[N_PARS+2-1]+1.0)+(S[(33-1)*SENSDIM+(4-1)]*p[2-1])/(p[N_PARS+2-1]+1.0); + jac[(1)*(N_OBS)+(15)] = (-d[5-1]+s[(43-1)*N_STATES+(1-1)]+s[(43-1)*N_STATES+(2-1)])/(p[N_PARS+2-1]+1.0)+(S[(43-1)*SENSDIM+(3-1)]*p[2-1])/(p[N_PARS+2-1]+1.0)+(S[(43-1)*SENSDIM+(4-1)]*p[2-1])/(p[N_PARS+2-1]+1.0); + jac[(1)*(N_OBS)+(16)] = (S[(1-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(1-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(1-1)*N_STATES+(2-1)])/s[(1-1)*N_STATES+(1-1)]-(S[(1-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(1-1)*N_STATES+(1-1)]*s[(1-1)*N_STATES+(1-1)])*s[(1-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(17)] = (S[(2-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(2-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(2-1)*N_STATES+(2-1)])/s[(2-1)*N_STATES+(1-1)]-(S[(2-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(2-1)*N_STATES+(1-1)]*s[(2-1)*N_STATES+(1-1)])*s[(2-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(18)] = (S[(3-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(3-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(3-1)*N_STATES+(2-1)])/s[(3-1)*N_STATES+(1-1)]-(S[(3-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(3-1)*N_STATES+(1-1)]*s[(3-1)*N_STATES+(1-1)])*s[(3-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(19)] = (S[(4-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(4-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(4-1)*N_STATES+(2-1)])/s[(4-1)*N_STATES+(1-1)]-(S[(4-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(4-1)*N_STATES+(1-1)]*s[(4-1)*N_STATES+(1-1)])*s[(4-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(20)] = (S[(5-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(5-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(5-1)*N_STATES+(2-1)])/s[(5-1)*N_STATES+(1-1)]-(S[(5-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(5-1)*N_STATES+(1-1)]*s[(5-1)*N_STATES+(1-1)])*s[(5-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(21)] = (S[(6-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(6-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(6-1)*N_STATES+(2-1)])/s[(6-1)*N_STATES+(1-1)]-(S[(6-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(6-1)*N_STATES+(1-1)]*s[(6-1)*N_STATES+(1-1)])*s[(6-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(22)] = (S[(8-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(8-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(8-1)*N_STATES+(2-1)])/s[(8-1)*N_STATES+(1-1)]-(S[(8-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(8-1)*N_STATES+(1-1)]*s[(8-1)*N_STATES+(1-1)])*s[(8-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(23)] = (S[(10-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(10-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(10-1)*N_STATES+(2-1)])/s[(10-1)*N_STATES+(1-1)]-(S[(10-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(10-1)*N_STATES+(1-1)]*s[(10-1)*N_STATES+(1-1)])*s[(10-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(24)] = (S[(11-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(11-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(11-1)*N_STATES+(2-1)])/s[(11-1)*N_STATES+(1-1)]-(S[(11-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(11-1)*N_STATES+(1-1)]*s[(11-1)*N_STATES+(1-1)])*s[(11-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(25)] = (S[(12-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(12-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(12-1)*N_STATES+(2-1)])/s[(12-1)*N_STATES+(1-1)]-(S[(12-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(12-1)*N_STATES+(1-1)]*s[(12-1)*N_STATES+(1-1)])*s[(12-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(26)] = (S[(13-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(13-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(13-1)*N_STATES+(2-1)])/s[(13-1)*N_STATES+(1-1)]-(S[(13-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(13-1)*N_STATES+(1-1)]*s[(13-1)*N_STATES+(1-1)])*s[(13-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(27)] = (S[(14-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(14-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(14-1)*N_STATES+(2-1)])/s[(14-1)*N_STATES+(1-1)]-(S[(14-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(14-1)*N_STATES+(1-1)]*s[(14-1)*N_STATES+(1-1)])*s[(14-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(28)] = (S[(15-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(15-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(15-1)*N_STATES+(2-1)])/s[(15-1)*N_STATES+(1-1)]-(S[(15-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(15-1)*N_STATES+(1-1)]*s[(15-1)*N_STATES+(1-1)])*s[(15-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(29)] = (S[(16-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(16-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(16-1)*N_STATES+(2-1)])/s[(16-1)*N_STATES+(1-1)]-(S[(16-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(16-1)*N_STATES+(1-1)]*s[(16-1)*N_STATES+(1-1)])*s[(16-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(30)] = (S[(17-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(17-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(17-1)*N_STATES+(2-1)])/s[(17-1)*N_STATES+(1-1)]-(S[(17-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(17-1)*N_STATES+(1-1)]*s[(17-1)*N_STATES+(1-1)])*s[(17-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(31)] = (S[(18-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(18-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(18-1)*N_STATES+(2-1)])/s[(18-1)*N_STATES+(1-1)]-(S[(18-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(18-1)*N_STATES+(1-1)]*s[(18-1)*N_STATES+(1-1)])*s[(18-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(32)] = (S[(19-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(19-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(19-1)*N_STATES+(2-1)])/s[(19-1)*N_STATES+(1-1)]-(S[(19-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(19-1)*N_STATES+(1-1)]*s[(19-1)*N_STATES+(1-1)])*s[(19-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(33)] = (S[(20-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(20-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(20-1)*N_STATES+(2-1)])/s[(20-1)*N_STATES+(1-1)]-(S[(20-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(20-1)*N_STATES+(1-1)]*s[(20-1)*N_STATES+(1-1)])*s[(20-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(34)] = (S[(21-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(21-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(21-1)*N_STATES+(2-1)])/s[(21-1)*N_STATES+(1-1)]-(S[(21-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(21-1)*N_STATES+(1-1)]*s[(21-1)*N_STATES+(1-1)])*s[(21-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(35)] = (S[(22-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(22-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(22-1)*N_STATES+(2-1)])/s[(22-1)*N_STATES+(1-1)]-(S[(22-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(22-1)*N_STATES+(1-1)]*s[(22-1)*N_STATES+(1-1)])*s[(22-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(36)] = (S[(23-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(23-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(23-1)*N_STATES+(2-1)])/s[(23-1)*N_STATES+(1-1)]-(S[(23-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(23-1)*N_STATES+(1-1)]*s[(23-1)*N_STATES+(1-1)])*s[(23-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(37)] = (S[(24-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(24-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(24-1)*N_STATES+(2-1)])/s[(24-1)*N_STATES+(1-1)]-(S[(24-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(24-1)*N_STATES+(1-1)]*s[(24-1)*N_STATES+(1-1)])*s[(24-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(38)] = (S[(25-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(25-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(25-1)*N_STATES+(2-1)])/s[(25-1)*N_STATES+(1-1)]-(S[(25-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(25-1)*N_STATES+(1-1)]*s[(25-1)*N_STATES+(1-1)])*s[(25-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(39)] = (S[(26-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(26-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(26-1)*N_STATES+(2-1)])/s[(26-1)*N_STATES+(1-1)]-(S[(26-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(26-1)*N_STATES+(1-1)]*s[(26-1)*N_STATES+(1-1)])*s[(26-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(40)] = (S[(27-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(27-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(27-1)*N_STATES+(2-1)])/s[(27-1)*N_STATES+(1-1)]-(S[(27-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(27-1)*N_STATES+(1-1)]*s[(27-1)*N_STATES+(1-1)])*s[(27-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(41)] = (S[(28-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(28-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(28-1)*N_STATES+(2-1)])/s[(28-1)*N_STATES+(1-1)]-(S[(28-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(28-1)*N_STATES+(1-1)]*s[(28-1)*N_STATES+(1-1)])*s[(28-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(42)] = (S[(29-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(29-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(29-1)*N_STATES+(2-1)])/s[(29-1)*N_STATES+(1-1)]-(S[(29-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(29-1)*N_STATES+(1-1)]*s[(29-1)*N_STATES+(1-1)])*s[(29-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(43)] = (S[(30-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(30-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(30-1)*N_STATES+(2-1)])/s[(30-1)*N_STATES+(1-1)]-(S[(30-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(30-1)*N_STATES+(1-1)]*s[(30-1)*N_STATES+(1-1)])*s[(30-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(44)] = (S[(31-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(31-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(31-1)*N_STATES+(2-1)])/s[(31-1)*N_STATES+(1-1)]-(S[(31-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(31-1)*N_STATES+(1-1)]*s[(31-1)*N_STATES+(1-1)])*s[(31-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(45)] = (S[(32-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(32-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(32-1)*N_STATES+(2-1)])/s[(32-1)*N_STATES+(1-1)]-(S[(32-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(32-1)*N_STATES+(1-1)]*s[(32-1)*N_STATES+(1-1)])*s[(32-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(46)] = (S[(33-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(33-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(33-1)*N_STATES+(2-1)])/s[(33-1)*N_STATES+(1-1)]-(S[(33-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(33-1)*N_STATES+(1-1)]*s[(33-1)*N_STATES+(1-1)])*s[(33-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(47)] = (S[(34-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(34-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(34-1)*N_STATES+(2-1)])/s[(34-1)*N_STATES+(1-1)]-(S[(34-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(34-1)*N_STATES+(1-1)]*s[(34-1)*N_STATES+(1-1)])*s[(34-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(48)] = (S[(35-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(35-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(35-1)*N_STATES+(2-1)])/s[(35-1)*N_STATES+(1-1)]-(S[(35-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(35-1)*N_STATES+(1-1)]*s[(35-1)*N_STATES+(1-1)])*s[(35-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(49)] = (S[(36-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(36-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(36-1)*N_STATES+(2-1)])/s[(36-1)*N_STATES+(1-1)]-(S[(36-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(36-1)*N_STATES+(1-1)]*s[(36-1)*N_STATES+(1-1)])*s[(36-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(50)] = (S[(37-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(37-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(37-1)*N_STATES+(2-1)])/s[(37-1)*N_STATES+(1-1)]-(S[(37-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(37-1)*N_STATES+(1-1)]*s[(37-1)*N_STATES+(1-1)])*s[(37-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(51)] = (S[(38-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(38-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(38-1)*N_STATES+(2-1)])/s[(38-1)*N_STATES+(1-1)]-(S[(38-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(38-1)*N_STATES+(1-1)]*s[(38-1)*N_STATES+(1-1)])*s[(38-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(52)] = (S[(39-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(39-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(39-1)*N_STATES+(2-1)])/s[(39-1)*N_STATES+(1-1)]-(S[(39-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(39-1)*N_STATES+(1-1)]*s[(39-1)*N_STATES+(1-1)])*s[(39-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(53)] = (S[(40-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(40-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(40-1)*N_STATES+(2-1)])/s[(40-1)*N_STATES+(1-1)]-(S[(40-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(40-1)*N_STATES+(1-1)]*s[(40-1)*N_STATES+(1-1)])*s[(40-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(54)] = (S[(41-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(41-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(41-1)*N_STATES+(2-1)])/s[(41-1)*N_STATES+(1-1)]-(S[(41-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(41-1)*N_STATES+(1-1)]*s[(41-1)*N_STATES+(1-1)])*s[(41-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(55)] = (S[(42-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(42-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(42-1)*N_STATES+(2-1)])/s[(42-1)*N_STATES+(1-1)]-(S[(42-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(42-1)*N_STATES+(1-1)]*s[(42-1)*N_STATES+(1-1)])*s[(42-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(56)] = (S[(43-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(43-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(43-1)*N_STATES+(2-1)])/s[(43-1)*N_STATES+(1-1)]-(S[(43-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(43-1)*N_STATES+(1-1)]*s[(43-1)*N_STATES+(1-1)])*s[(43-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(57)] = (S[(44-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(44-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(44-1)*N_STATES+(2-1)])/s[(44-1)*N_STATES+(1-1)]-(S[(44-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(44-1)*N_STATES+(1-1)]*s[(44-1)*N_STATES+(1-1)])*s[(44-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(58)] = (S[(45-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(45-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(45-1)*N_STATES+(2-1)])/s[(45-1)*N_STATES+(1-1)]-(S[(45-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(45-1)*N_STATES+(1-1)]*s[(45-1)*N_STATES+(1-1)])*s[(45-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(59)] = (S[(46-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(46-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(46-1)*N_STATES+(2-1)])/s[(46-1)*N_STATES+(1-1)]-(S[(46-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(46-1)*N_STATES+(1-1)]*s[(46-1)*N_STATES+(1-1)])*s[(46-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(60)] = (S[(47-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(47-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(47-1)*N_STATES+(2-1)])/s[(47-1)*N_STATES+(1-1)]-(S[(47-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(47-1)*N_STATES+(1-1)]*s[(47-1)*N_STATES+(1-1)])*s[(47-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(61)] = (S[(48-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(48-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(48-1)*N_STATES+(2-1)])/s[(48-1)*N_STATES+(1-1)]-(S[(48-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(48-1)*N_STATES+(1-1)]*s[(48-1)*N_STATES+(1-1)])*s[(48-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(62)] = (S[(49-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(49-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(49-1)*N_STATES+(2-1)])/s[(49-1)*N_STATES+(1-1)]-(S[(49-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(49-1)*N_STATES+(1-1)]*s[(49-1)*N_STATES+(1-1)])*s[(49-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(63)] = (S[(50-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(50-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(50-1)*N_STATES+(2-1)])/s[(50-1)*N_STATES+(1-1)]-(S[(50-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(50-1)*N_STATES+(1-1)]*s[(50-1)*N_STATES+(1-1)])*s[(50-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(64)] = (S[(51-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(51-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(51-1)*N_STATES+(2-1)])/s[(51-1)*N_STATES+(1-1)]-(S[(51-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(51-1)*N_STATES+(1-1)]*s[(51-1)*N_STATES+(1-1)])*s[(51-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(65)] = (S[(52-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(52-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(52-1)*N_STATES+(2-1)])/s[(52-1)*N_STATES+(1-1)]-(S[(52-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(52-1)*N_STATES+(1-1)]*s[(52-1)*N_STATES+(1-1)])*s[(52-1)*N_STATES+(2-1)])/p[2-1]; + jac[(1)*(N_OBS)+(66)] = (S[(53-1)*SENSDIM+(4-1)]*p[3-1])/(p[2-1]*s[(53-1)*N_STATES+(1-1)])-(1.0/(p[2-1]*p[2-1])*p[3-1]*s[(53-1)*N_STATES+(2-1)])/s[(53-1)*N_STATES+(1-1)]-(S[(53-1)*SENSDIM+(3-1)]*p[3-1]*1.0/(s[(53-1)*N_STATES+(1-1)]*s[(53-1)*N_STATES+(1-1)])*s[(53-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(0)] = S[(1-1)*SENSDIM+(5-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(2)*(N_OBS)+(1)] = S[(2-1)*SENSDIM+(5-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(2)*(N_OBS)+(2)] = S[(3-1)*SENSDIM+(5-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(2)*(N_OBS)+(3)] = S[(4-1)*SENSDIM+(5-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(2)*(N_OBS)+(4)] = S[(5-1)*SENSDIM+(5-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(2)*(N_OBS)+(5)] = S[(6-1)*SENSDIM+(5-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(2)*(N_OBS)+(6)] = S[(7-1)*SENSDIM+(5-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(2)*(N_OBS)+(7)] = S[(9-1)*SENSDIM+(5-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(2)*(N_OBS)+(8)] = S[(11-1)*SENSDIM+(5-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(2)*(N_OBS)+(9)] = S[(12-1)*SENSDIM+(5-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(2)*(N_OBS)+(10)] = S[(13-1)*SENSDIM+(5-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(2)*(N_OBS)+(11)] = (S[(1-1)*SENSDIM+(5-1)]*p[2-1])/(p[N_PARS+2-1]+1.0)+(S[(1-1)*SENSDIM+(6-1)]*p[2-1])/(p[N_PARS+2-1]+1.0); + jac[(2)*(N_OBS)+(12)] = (S[(13-1)*SENSDIM+(5-1)]*p[2-1])/(p[N_PARS+2-1]+1.0)+(S[(13-1)*SENSDIM+(6-1)]*p[2-1])/(p[N_PARS+2-1]+1.0); + jac[(2)*(N_OBS)+(13)] = (S[(23-1)*SENSDIM+(5-1)]*p[2-1])/(p[N_PARS+2-1]+1.0)+(S[(23-1)*SENSDIM+(6-1)]*p[2-1])/(p[N_PARS+2-1]+1.0); + jac[(2)*(N_OBS)+(14)] = (S[(33-1)*SENSDIM+(5-1)]*p[2-1])/(p[N_PARS+2-1]+1.0)+(S[(33-1)*SENSDIM+(6-1)]*p[2-1])/(p[N_PARS+2-1]+1.0); + jac[(2)*(N_OBS)+(15)] = (S[(43-1)*SENSDIM+(5-1)]*p[2-1])/(p[N_PARS+2-1]+1.0)+(S[(43-1)*SENSDIM+(6-1)]*p[2-1])/(p[N_PARS+2-1]+1.0); + jac[(2)*(N_OBS)+(16)] = s[(1-1)*N_STATES+(2-1)]/(p[2-1]*s[(1-1)*N_STATES+(1-1)])+(S[(1-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(1-1)*N_STATES+(1-1)])-(S[(1-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(1-1)*N_STATES+(1-1)]*s[(1-1)*N_STATES+(1-1)])*s[(1-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(17)] = s[(2-1)*N_STATES+(2-1)]/(p[2-1]*s[(2-1)*N_STATES+(1-1)])+(S[(2-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(2-1)*N_STATES+(1-1)])-(S[(2-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(2-1)*N_STATES+(1-1)]*s[(2-1)*N_STATES+(1-1)])*s[(2-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(18)] = s[(3-1)*N_STATES+(2-1)]/(p[2-1]*s[(3-1)*N_STATES+(1-1)])+(S[(3-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(3-1)*N_STATES+(1-1)])-(S[(3-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(3-1)*N_STATES+(1-1)]*s[(3-1)*N_STATES+(1-1)])*s[(3-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(19)] = s[(4-1)*N_STATES+(2-1)]/(p[2-1]*s[(4-1)*N_STATES+(1-1)])+(S[(4-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(4-1)*N_STATES+(1-1)])-(S[(4-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(4-1)*N_STATES+(1-1)]*s[(4-1)*N_STATES+(1-1)])*s[(4-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(20)] = s[(5-1)*N_STATES+(2-1)]/(p[2-1]*s[(5-1)*N_STATES+(1-1)])+(S[(5-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(5-1)*N_STATES+(1-1)])-(S[(5-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(5-1)*N_STATES+(1-1)]*s[(5-1)*N_STATES+(1-1)])*s[(5-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(21)] = s[(6-1)*N_STATES+(2-1)]/(p[2-1]*s[(6-1)*N_STATES+(1-1)])+(S[(6-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(6-1)*N_STATES+(1-1)])-(S[(6-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(6-1)*N_STATES+(1-1)]*s[(6-1)*N_STATES+(1-1)])*s[(6-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(22)] = s[(8-1)*N_STATES+(2-1)]/(p[2-1]*s[(8-1)*N_STATES+(1-1)])+(S[(8-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(8-1)*N_STATES+(1-1)])-(S[(8-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(8-1)*N_STATES+(1-1)]*s[(8-1)*N_STATES+(1-1)])*s[(8-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(23)] = s[(10-1)*N_STATES+(2-1)]/(p[2-1]*s[(10-1)*N_STATES+(1-1)])+(S[(10-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(10-1)*N_STATES+(1-1)])-(S[(10-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(10-1)*N_STATES+(1-1)]*s[(10-1)*N_STATES+(1-1)])*s[(10-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(24)] = s[(11-1)*N_STATES+(2-1)]/(p[2-1]*s[(11-1)*N_STATES+(1-1)])+(S[(11-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(11-1)*N_STATES+(1-1)])-(S[(11-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(11-1)*N_STATES+(1-1)]*s[(11-1)*N_STATES+(1-1)])*s[(11-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(25)] = s[(12-1)*N_STATES+(2-1)]/(p[2-1]*s[(12-1)*N_STATES+(1-1)])+(S[(12-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(12-1)*N_STATES+(1-1)])-(S[(12-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(12-1)*N_STATES+(1-1)]*s[(12-1)*N_STATES+(1-1)])*s[(12-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(26)] = s[(13-1)*N_STATES+(2-1)]/(p[2-1]*s[(13-1)*N_STATES+(1-1)])+(S[(13-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(13-1)*N_STATES+(1-1)])-(S[(13-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(13-1)*N_STATES+(1-1)]*s[(13-1)*N_STATES+(1-1)])*s[(13-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(27)] = s[(14-1)*N_STATES+(2-1)]/(p[2-1]*s[(14-1)*N_STATES+(1-1)])+(S[(14-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(14-1)*N_STATES+(1-1)])-(S[(14-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(14-1)*N_STATES+(1-1)]*s[(14-1)*N_STATES+(1-1)])*s[(14-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(28)] = s[(15-1)*N_STATES+(2-1)]/(p[2-1]*s[(15-1)*N_STATES+(1-1)])+(S[(15-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(15-1)*N_STATES+(1-1)])-(S[(15-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(15-1)*N_STATES+(1-1)]*s[(15-1)*N_STATES+(1-1)])*s[(15-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(29)] = s[(16-1)*N_STATES+(2-1)]/(p[2-1]*s[(16-1)*N_STATES+(1-1)])+(S[(16-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(16-1)*N_STATES+(1-1)])-(S[(16-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(16-1)*N_STATES+(1-1)]*s[(16-1)*N_STATES+(1-1)])*s[(16-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(30)] = s[(17-1)*N_STATES+(2-1)]/(p[2-1]*s[(17-1)*N_STATES+(1-1)])+(S[(17-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(17-1)*N_STATES+(1-1)])-(S[(17-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(17-1)*N_STATES+(1-1)]*s[(17-1)*N_STATES+(1-1)])*s[(17-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(31)] = s[(18-1)*N_STATES+(2-1)]/(p[2-1]*s[(18-1)*N_STATES+(1-1)])+(S[(18-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(18-1)*N_STATES+(1-1)])-(S[(18-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(18-1)*N_STATES+(1-1)]*s[(18-1)*N_STATES+(1-1)])*s[(18-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(32)] = s[(19-1)*N_STATES+(2-1)]/(p[2-1]*s[(19-1)*N_STATES+(1-1)])+(S[(19-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(19-1)*N_STATES+(1-1)])-(S[(19-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(19-1)*N_STATES+(1-1)]*s[(19-1)*N_STATES+(1-1)])*s[(19-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(33)] = s[(20-1)*N_STATES+(2-1)]/(p[2-1]*s[(20-1)*N_STATES+(1-1)])+(S[(20-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(20-1)*N_STATES+(1-1)])-(S[(20-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(20-1)*N_STATES+(1-1)]*s[(20-1)*N_STATES+(1-1)])*s[(20-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(34)] = s[(21-1)*N_STATES+(2-1)]/(p[2-1]*s[(21-1)*N_STATES+(1-1)])+(S[(21-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(21-1)*N_STATES+(1-1)])-(S[(21-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(21-1)*N_STATES+(1-1)]*s[(21-1)*N_STATES+(1-1)])*s[(21-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(35)] = s[(22-1)*N_STATES+(2-1)]/(p[2-1]*s[(22-1)*N_STATES+(1-1)])+(S[(22-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(22-1)*N_STATES+(1-1)])-(S[(22-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(22-1)*N_STATES+(1-1)]*s[(22-1)*N_STATES+(1-1)])*s[(22-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(36)] = s[(23-1)*N_STATES+(2-1)]/(p[2-1]*s[(23-1)*N_STATES+(1-1)])+(S[(23-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(23-1)*N_STATES+(1-1)])-(S[(23-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(23-1)*N_STATES+(1-1)]*s[(23-1)*N_STATES+(1-1)])*s[(23-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(37)] = s[(24-1)*N_STATES+(2-1)]/(p[2-1]*s[(24-1)*N_STATES+(1-1)])+(S[(24-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(24-1)*N_STATES+(1-1)])-(S[(24-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(24-1)*N_STATES+(1-1)]*s[(24-1)*N_STATES+(1-1)])*s[(24-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(38)] = s[(25-1)*N_STATES+(2-1)]/(p[2-1]*s[(25-1)*N_STATES+(1-1)])+(S[(25-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(25-1)*N_STATES+(1-1)])-(S[(25-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(25-1)*N_STATES+(1-1)]*s[(25-1)*N_STATES+(1-1)])*s[(25-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(39)] = s[(26-1)*N_STATES+(2-1)]/(p[2-1]*s[(26-1)*N_STATES+(1-1)])+(S[(26-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(26-1)*N_STATES+(1-1)])-(S[(26-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(26-1)*N_STATES+(1-1)]*s[(26-1)*N_STATES+(1-1)])*s[(26-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(40)] = s[(27-1)*N_STATES+(2-1)]/(p[2-1]*s[(27-1)*N_STATES+(1-1)])+(S[(27-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(27-1)*N_STATES+(1-1)])-(S[(27-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(27-1)*N_STATES+(1-1)]*s[(27-1)*N_STATES+(1-1)])*s[(27-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(41)] = s[(28-1)*N_STATES+(2-1)]/(p[2-1]*s[(28-1)*N_STATES+(1-1)])+(S[(28-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(28-1)*N_STATES+(1-1)])-(S[(28-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(28-1)*N_STATES+(1-1)]*s[(28-1)*N_STATES+(1-1)])*s[(28-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(42)] = s[(29-1)*N_STATES+(2-1)]/(p[2-1]*s[(29-1)*N_STATES+(1-1)])+(S[(29-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(29-1)*N_STATES+(1-1)])-(S[(29-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(29-1)*N_STATES+(1-1)]*s[(29-1)*N_STATES+(1-1)])*s[(29-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(43)] = s[(30-1)*N_STATES+(2-1)]/(p[2-1]*s[(30-1)*N_STATES+(1-1)])+(S[(30-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(30-1)*N_STATES+(1-1)])-(S[(30-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(30-1)*N_STATES+(1-1)]*s[(30-1)*N_STATES+(1-1)])*s[(30-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(44)] = s[(31-1)*N_STATES+(2-1)]/(p[2-1]*s[(31-1)*N_STATES+(1-1)])+(S[(31-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(31-1)*N_STATES+(1-1)])-(S[(31-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(31-1)*N_STATES+(1-1)]*s[(31-1)*N_STATES+(1-1)])*s[(31-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(45)] = s[(32-1)*N_STATES+(2-1)]/(p[2-1]*s[(32-1)*N_STATES+(1-1)])+(S[(32-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(32-1)*N_STATES+(1-1)])-(S[(32-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(32-1)*N_STATES+(1-1)]*s[(32-1)*N_STATES+(1-1)])*s[(32-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(46)] = s[(33-1)*N_STATES+(2-1)]/(p[2-1]*s[(33-1)*N_STATES+(1-1)])+(S[(33-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(33-1)*N_STATES+(1-1)])-(S[(33-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(33-1)*N_STATES+(1-1)]*s[(33-1)*N_STATES+(1-1)])*s[(33-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(47)] = s[(34-1)*N_STATES+(2-1)]/(p[2-1]*s[(34-1)*N_STATES+(1-1)])+(S[(34-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(34-1)*N_STATES+(1-1)])-(S[(34-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(34-1)*N_STATES+(1-1)]*s[(34-1)*N_STATES+(1-1)])*s[(34-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(48)] = s[(35-1)*N_STATES+(2-1)]/(p[2-1]*s[(35-1)*N_STATES+(1-1)])+(S[(35-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(35-1)*N_STATES+(1-1)])-(S[(35-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(35-1)*N_STATES+(1-1)]*s[(35-1)*N_STATES+(1-1)])*s[(35-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(49)] = s[(36-1)*N_STATES+(2-1)]/(p[2-1]*s[(36-1)*N_STATES+(1-1)])+(S[(36-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(36-1)*N_STATES+(1-1)])-(S[(36-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(36-1)*N_STATES+(1-1)]*s[(36-1)*N_STATES+(1-1)])*s[(36-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(50)] = s[(37-1)*N_STATES+(2-1)]/(p[2-1]*s[(37-1)*N_STATES+(1-1)])+(S[(37-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(37-1)*N_STATES+(1-1)])-(S[(37-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(37-1)*N_STATES+(1-1)]*s[(37-1)*N_STATES+(1-1)])*s[(37-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(51)] = s[(38-1)*N_STATES+(2-1)]/(p[2-1]*s[(38-1)*N_STATES+(1-1)])+(S[(38-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(38-1)*N_STATES+(1-1)])-(S[(38-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(38-1)*N_STATES+(1-1)]*s[(38-1)*N_STATES+(1-1)])*s[(38-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(52)] = s[(39-1)*N_STATES+(2-1)]/(p[2-1]*s[(39-1)*N_STATES+(1-1)])+(S[(39-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(39-1)*N_STATES+(1-1)])-(S[(39-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(39-1)*N_STATES+(1-1)]*s[(39-1)*N_STATES+(1-1)])*s[(39-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(53)] = s[(40-1)*N_STATES+(2-1)]/(p[2-1]*s[(40-1)*N_STATES+(1-1)])+(S[(40-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(40-1)*N_STATES+(1-1)])-(S[(40-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(40-1)*N_STATES+(1-1)]*s[(40-1)*N_STATES+(1-1)])*s[(40-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(54)] = s[(41-1)*N_STATES+(2-1)]/(p[2-1]*s[(41-1)*N_STATES+(1-1)])+(S[(41-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(41-1)*N_STATES+(1-1)])-(S[(41-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(41-1)*N_STATES+(1-1)]*s[(41-1)*N_STATES+(1-1)])*s[(41-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(55)] = s[(42-1)*N_STATES+(2-1)]/(p[2-1]*s[(42-1)*N_STATES+(1-1)])+(S[(42-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(42-1)*N_STATES+(1-1)])-(S[(42-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(42-1)*N_STATES+(1-1)]*s[(42-1)*N_STATES+(1-1)])*s[(42-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(56)] = s[(43-1)*N_STATES+(2-1)]/(p[2-1]*s[(43-1)*N_STATES+(1-1)])+(S[(43-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(43-1)*N_STATES+(1-1)])-(S[(43-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(43-1)*N_STATES+(1-1)]*s[(43-1)*N_STATES+(1-1)])*s[(43-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(57)] = s[(44-1)*N_STATES+(2-1)]/(p[2-1]*s[(44-1)*N_STATES+(1-1)])+(S[(44-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(44-1)*N_STATES+(1-1)])-(S[(44-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(44-1)*N_STATES+(1-1)]*s[(44-1)*N_STATES+(1-1)])*s[(44-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(58)] = s[(45-1)*N_STATES+(2-1)]/(p[2-1]*s[(45-1)*N_STATES+(1-1)])+(S[(45-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(45-1)*N_STATES+(1-1)])-(S[(45-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(45-1)*N_STATES+(1-1)]*s[(45-1)*N_STATES+(1-1)])*s[(45-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(59)] = s[(46-1)*N_STATES+(2-1)]/(p[2-1]*s[(46-1)*N_STATES+(1-1)])+(S[(46-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(46-1)*N_STATES+(1-1)])-(S[(46-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(46-1)*N_STATES+(1-1)]*s[(46-1)*N_STATES+(1-1)])*s[(46-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(60)] = s[(47-1)*N_STATES+(2-1)]/(p[2-1]*s[(47-1)*N_STATES+(1-1)])+(S[(47-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(47-1)*N_STATES+(1-1)])-(S[(47-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(47-1)*N_STATES+(1-1)]*s[(47-1)*N_STATES+(1-1)])*s[(47-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(61)] = s[(48-1)*N_STATES+(2-1)]/(p[2-1]*s[(48-1)*N_STATES+(1-1)])+(S[(48-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(48-1)*N_STATES+(1-1)])-(S[(48-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(48-1)*N_STATES+(1-1)]*s[(48-1)*N_STATES+(1-1)])*s[(48-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(62)] = s[(49-1)*N_STATES+(2-1)]/(p[2-1]*s[(49-1)*N_STATES+(1-1)])+(S[(49-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(49-1)*N_STATES+(1-1)])-(S[(49-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(49-1)*N_STATES+(1-1)]*s[(49-1)*N_STATES+(1-1)])*s[(49-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(63)] = s[(50-1)*N_STATES+(2-1)]/(p[2-1]*s[(50-1)*N_STATES+(1-1)])+(S[(50-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(50-1)*N_STATES+(1-1)])-(S[(50-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(50-1)*N_STATES+(1-1)]*s[(50-1)*N_STATES+(1-1)])*s[(50-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(64)] = s[(51-1)*N_STATES+(2-1)]/(p[2-1]*s[(51-1)*N_STATES+(1-1)])+(S[(51-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(51-1)*N_STATES+(1-1)])-(S[(51-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(51-1)*N_STATES+(1-1)]*s[(51-1)*N_STATES+(1-1)])*s[(51-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(65)] = s[(52-1)*N_STATES+(2-1)]/(p[2-1]*s[(52-1)*N_STATES+(1-1)])+(S[(52-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(52-1)*N_STATES+(1-1)])-(S[(52-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(52-1)*N_STATES+(1-1)]*s[(52-1)*N_STATES+(1-1)])*s[(52-1)*N_STATES+(2-1)])/p[2-1]; + jac[(2)*(N_OBS)+(66)] = s[(53-1)*N_STATES+(2-1)]/(p[2-1]*s[(53-1)*N_STATES+(1-1)])+(S[(53-1)*SENSDIM+(6-1)]*p[3-1])/(p[2-1]*s[(53-1)*N_STATES+(1-1)])-(S[(53-1)*SENSDIM+(5-1)]*p[3-1]*1.0/(s[(53-1)*N_STATES+(1-1)]*s[(53-1)*N_STATES+(1-1)])*s[(53-1)*N_STATES+(2-1)])/p[2-1]; + jac[(3)*(N_OBS)+(0)] = p[1-1]*s[(1-1)*N_STATES+(1-1)]*u[1-1]; + jac[(3)*(N_OBS)+(1)] = p[1-1]*s[(2-1)*N_STATES+(1-1)]*u[1-1]; + jac[(3)*(N_OBS)+(2)] = p[1-1]*s[(3-1)*N_STATES+(1-1)]*u[1-1]; + jac[(3)*(N_OBS)+(3)] = p[1-1]*s[(4-1)*N_STATES+(1-1)]*u[1-1]; + jac[(3)*(N_OBS)+(4)] = p[1-1]*s[(5-1)*N_STATES+(1-1)]*u[1-1]; + jac[(3)*(N_OBS)+(5)] = p[1-1]*s[(6-1)*N_STATES+(1-1)]*u[1-1]; + jac[(3)*(N_OBS)+(6)] = p[1-1]*s[(7-1)*N_STATES+(1-1)]*u[1-1]; + jac[(3)*(N_OBS)+(7)] = p[1-1]*s[(9-1)*N_STATES+(1-1)]*u[1-1]; + jac[(3)*(N_OBS)+(8)] = p[1-1]*s[(11-1)*N_STATES+(1-1)]*u[1-1]; + jac[(3)*(N_OBS)+(9)] = p[1-1]*s[(12-1)*N_STATES+(1-1)]*u[1-1]; + jac[(3)*(N_OBS)+(10)] = p[1-1]*s[(13-1)*N_STATES+(1-1)]*u[1-1]; + jac[(4)*(N_OBS)+(11)] = -p[2-1]*1.0/pow(p[N_PARS+2-1]+1.0,2.0)*(-d[1-1]+s[(1-1)*N_STATES+(1-1)]+s[(1-1)*N_STATES+(2-1)]); + jac[(4)*(N_OBS)+(12)] = -p[2-1]*1.0/pow(p[N_PARS+2-1]+1.0,2.0)*(-d[2-1]+s[(13-1)*N_STATES+(1-1)]+s[(13-1)*N_STATES+(2-1)]); + jac[(4)*(N_OBS)+(13)] = -p[2-1]*1.0/pow(p[N_PARS+2-1]+1.0,2.0)*(-d[3-1]+s[(23-1)*N_STATES+(1-1)]+s[(23-1)*N_STATES+(2-1)]); + jac[(4)*(N_OBS)+(14)] = -p[2-1]*1.0/pow(p[N_PARS+2-1]+1.0,2.0)*(-d[4-1]+s[(33-1)*N_STATES+(1-1)]+s[(33-1)*N_STATES+(2-1)]); + jac[(4)*(N_OBS)+(15)] = -p[2-1]*1.0/pow(p[N_PARS+2-1]+1.0,2.0)*(-d[5-1]+s[(43-1)*N_STATES+(1-1)]+s[(43-1)*N_STATES+(2-1)]); + jac[(5)*(N_OBS)+(0)] = S[(1-1)*SENSDIM+(9-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(5)*(N_OBS)+(1)] = S[(2-1)*SENSDIM+(9-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(5)*(N_OBS)+(2)] = S[(3-1)*SENSDIM+(9-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(5)*(N_OBS)+(3)] = S[(4-1)*SENSDIM+(9-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(5)*(N_OBS)+(4)] = S[(5-1)*SENSDIM+(9-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(5)*(N_OBS)+(5)] = S[(6-1)*SENSDIM+(9-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(5)*(N_OBS)+(6)] = S[(7-1)*SENSDIM+(9-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(5)*(N_OBS)+(7)] = S[(9-1)*SENSDIM+(9-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(5)*(N_OBS)+(8)] = S[(11-1)*SENSDIM+(9-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(5)*(N_OBS)+(9)] = S[(12-1)*SENSDIM+(9-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(5)*(N_OBS)+(10)] = S[(13-1)*SENSDIM+(9-1)]*p[1-1]*u[1-1]*(p[N_PARS+1-1]+1.0); + jac[(5)*(N_OBS)+(11)] = (S[(1-1)*SENSDIM+(10-1)]*p[2-1])/(p[N_PARS+2-1]+1.0)+(S[(1-1)*SENSDIM+(9-1)]*p[2-1])/(p[N_PARS+2-1]+1.0); + jac[(5)*(N_OBS)+(12)] = (S[(13-1)*SENSDIM+(10-1)]*p[2-1])/(p[N_PARS+2-1]+1.0)+(S[(13-1)*SENSDIM+(9-1)]*p[2-1])/(p[N_PARS+2-1]+1.0); + jac[(5)*(N_OBS)+(13)] = (S[(23-1)*SENSDIM+(10-1)]*p[2-1])/(p[N_PARS+2-1]+1.0)+(S[(23-1)*SENSDIM+(9-1)]*p[2-1])/(p[N_PARS+2-1]+1.0); + jac[(5)*(N_OBS)+(14)] = (S[(33-1)*SENSDIM+(10-1)]*p[2-1])/(p[N_PARS+2-1]+1.0)+(S[(33-1)*SENSDIM+(9-1)]*p[2-1])/(p[N_PARS+2-1]+1.0); + jac[(5)*(N_OBS)+(15)] = (S[(43-1)*SENSDIM+(10-1)]*p[2-1])/(p[N_PARS+2-1]+1.0)+(S[(43-1)*SENSDIM+(9-1)]*p[2-1])/(p[N_PARS+2-1]+1.0); + jac[(5)*(N_OBS)+(16)] = (S[(1-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(1-1)*N_STATES+(1-1)])-(S[(1-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(1-1)*N_STATES+(1-1)]*s[(1-1)*N_STATES+(1-1)])*s[(1-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(17)] = (S[(2-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(2-1)*N_STATES+(1-1)])-(S[(2-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(2-1)*N_STATES+(1-1)]*s[(2-1)*N_STATES+(1-1)])*s[(2-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(18)] = (S[(3-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(3-1)*N_STATES+(1-1)])-(S[(3-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(3-1)*N_STATES+(1-1)]*s[(3-1)*N_STATES+(1-1)])*s[(3-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(19)] = (S[(4-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(4-1)*N_STATES+(1-1)])-(S[(4-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(4-1)*N_STATES+(1-1)]*s[(4-1)*N_STATES+(1-1)])*s[(4-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(20)] = (S[(5-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(5-1)*N_STATES+(1-1)])-(S[(5-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(5-1)*N_STATES+(1-1)]*s[(5-1)*N_STATES+(1-1)])*s[(5-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(21)] = (S[(6-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(6-1)*N_STATES+(1-1)])-(S[(6-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(6-1)*N_STATES+(1-1)]*s[(6-1)*N_STATES+(1-1)])*s[(6-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(22)] = (S[(8-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(8-1)*N_STATES+(1-1)])-(S[(8-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(8-1)*N_STATES+(1-1)]*s[(8-1)*N_STATES+(1-1)])*s[(8-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(23)] = (S[(10-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(10-1)*N_STATES+(1-1)])-(S[(10-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(10-1)*N_STATES+(1-1)]*s[(10-1)*N_STATES+(1-1)])*s[(10-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(24)] = (S[(11-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(11-1)*N_STATES+(1-1)])-(S[(11-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(11-1)*N_STATES+(1-1)]*s[(11-1)*N_STATES+(1-1)])*s[(11-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(25)] = (S[(12-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(12-1)*N_STATES+(1-1)])-(S[(12-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(12-1)*N_STATES+(1-1)]*s[(12-1)*N_STATES+(1-1)])*s[(12-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(26)] = (S[(13-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(13-1)*N_STATES+(1-1)])-(S[(13-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(13-1)*N_STATES+(1-1)]*s[(13-1)*N_STATES+(1-1)])*s[(13-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(27)] = (S[(14-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(14-1)*N_STATES+(1-1)])-(S[(14-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(14-1)*N_STATES+(1-1)]*s[(14-1)*N_STATES+(1-1)])*s[(14-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(28)] = (S[(15-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(15-1)*N_STATES+(1-1)])-(S[(15-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(15-1)*N_STATES+(1-1)]*s[(15-1)*N_STATES+(1-1)])*s[(15-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(29)] = (S[(16-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(16-1)*N_STATES+(1-1)])-(S[(16-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(16-1)*N_STATES+(1-1)]*s[(16-1)*N_STATES+(1-1)])*s[(16-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(30)] = (S[(17-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(17-1)*N_STATES+(1-1)])-(S[(17-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(17-1)*N_STATES+(1-1)]*s[(17-1)*N_STATES+(1-1)])*s[(17-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(31)] = (S[(18-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(18-1)*N_STATES+(1-1)])-(S[(18-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(18-1)*N_STATES+(1-1)]*s[(18-1)*N_STATES+(1-1)])*s[(18-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(32)] = (S[(19-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(19-1)*N_STATES+(1-1)])-(S[(19-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(19-1)*N_STATES+(1-1)]*s[(19-1)*N_STATES+(1-1)])*s[(19-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(33)] = (S[(20-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(20-1)*N_STATES+(1-1)])-(S[(20-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(20-1)*N_STATES+(1-1)]*s[(20-1)*N_STATES+(1-1)])*s[(20-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(34)] = (S[(21-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(21-1)*N_STATES+(1-1)])-(S[(21-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(21-1)*N_STATES+(1-1)]*s[(21-1)*N_STATES+(1-1)])*s[(21-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(35)] = (S[(22-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(22-1)*N_STATES+(1-1)])-(S[(22-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(22-1)*N_STATES+(1-1)]*s[(22-1)*N_STATES+(1-1)])*s[(22-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(36)] = (S[(23-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(23-1)*N_STATES+(1-1)])-(S[(23-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(23-1)*N_STATES+(1-1)]*s[(23-1)*N_STATES+(1-1)])*s[(23-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(37)] = (S[(24-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(24-1)*N_STATES+(1-1)])-(S[(24-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(24-1)*N_STATES+(1-1)]*s[(24-1)*N_STATES+(1-1)])*s[(24-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(38)] = (S[(25-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(25-1)*N_STATES+(1-1)])-(S[(25-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(25-1)*N_STATES+(1-1)]*s[(25-1)*N_STATES+(1-1)])*s[(25-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(39)] = (S[(26-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(26-1)*N_STATES+(1-1)])-(S[(26-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(26-1)*N_STATES+(1-1)]*s[(26-1)*N_STATES+(1-1)])*s[(26-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(40)] = (S[(27-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(27-1)*N_STATES+(1-1)])-(S[(27-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(27-1)*N_STATES+(1-1)]*s[(27-1)*N_STATES+(1-1)])*s[(27-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(41)] = (S[(28-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(28-1)*N_STATES+(1-1)])-(S[(28-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(28-1)*N_STATES+(1-1)]*s[(28-1)*N_STATES+(1-1)])*s[(28-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(42)] = (S[(29-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(29-1)*N_STATES+(1-1)])-(S[(29-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(29-1)*N_STATES+(1-1)]*s[(29-1)*N_STATES+(1-1)])*s[(29-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(43)] = (S[(30-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(30-1)*N_STATES+(1-1)])-(S[(30-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(30-1)*N_STATES+(1-1)]*s[(30-1)*N_STATES+(1-1)])*s[(30-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(44)] = (S[(31-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(31-1)*N_STATES+(1-1)])-(S[(31-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(31-1)*N_STATES+(1-1)]*s[(31-1)*N_STATES+(1-1)])*s[(31-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(45)] = (S[(32-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(32-1)*N_STATES+(1-1)])-(S[(32-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(32-1)*N_STATES+(1-1)]*s[(32-1)*N_STATES+(1-1)])*s[(32-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(46)] = (S[(33-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(33-1)*N_STATES+(1-1)])-(S[(33-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(33-1)*N_STATES+(1-1)]*s[(33-1)*N_STATES+(1-1)])*s[(33-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(47)] = (S[(34-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(34-1)*N_STATES+(1-1)])-(S[(34-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(34-1)*N_STATES+(1-1)]*s[(34-1)*N_STATES+(1-1)])*s[(34-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(48)] = (S[(35-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(35-1)*N_STATES+(1-1)])-(S[(35-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(35-1)*N_STATES+(1-1)]*s[(35-1)*N_STATES+(1-1)])*s[(35-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(49)] = (S[(36-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(36-1)*N_STATES+(1-1)])-(S[(36-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(36-1)*N_STATES+(1-1)]*s[(36-1)*N_STATES+(1-1)])*s[(36-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(50)] = (S[(37-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(37-1)*N_STATES+(1-1)])-(S[(37-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(37-1)*N_STATES+(1-1)]*s[(37-1)*N_STATES+(1-1)])*s[(37-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(51)] = (S[(38-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(38-1)*N_STATES+(1-1)])-(S[(38-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(38-1)*N_STATES+(1-1)]*s[(38-1)*N_STATES+(1-1)])*s[(38-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(52)] = (S[(39-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(39-1)*N_STATES+(1-1)])-(S[(39-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(39-1)*N_STATES+(1-1)]*s[(39-1)*N_STATES+(1-1)])*s[(39-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(53)] = (S[(40-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(40-1)*N_STATES+(1-1)])-(S[(40-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(40-1)*N_STATES+(1-1)]*s[(40-1)*N_STATES+(1-1)])*s[(40-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(54)] = (S[(41-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(41-1)*N_STATES+(1-1)])-(S[(41-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(41-1)*N_STATES+(1-1)]*s[(41-1)*N_STATES+(1-1)])*s[(41-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(55)] = (S[(42-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(42-1)*N_STATES+(1-1)])-(S[(42-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(42-1)*N_STATES+(1-1)]*s[(42-1)*N_STATES+(1-1)])*s[(42-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(56)] = (S[(43-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(43-1)*N_STATES+(1-1)])-(S[(43-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(43-1)*N_STATES+(1-1)]*s[(43-1)*N_STATES+(1-1)])*s[(43-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(57)] = (S[(44-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(44-1)*N_STATES+(1-1)])-(S[(44-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(44-1)*N_STATES+(1-1)]*s[(44-1)*N_STATES+(1-1)])*s[(44-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(58)] = (S[(45-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(45-1)*N_STATES+(1-1)])-(S[(45-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(45-1)*N_STATES+(1-1)]*s[(45-1)*N_STATES+(1-1)])*s[(45-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(59)] = (S[(46-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(46-1)*N_STATES+(1-1)])-(S[(46-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(46-1)*N_STATES+(1-1)]*s[(46-1)*N_STATES+(1-1)])*s[(46-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(60)] = (S[(47-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(47-1)*N_STATES+(1-1)])-(S[(47-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(47-1)*N_STATES+(1-1)]*s[(47-1)*N_STATES+(1-1)])*s[(47-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(61)] = (S[(48-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(48-1)*N_STATES+(1-1)])-(S[(48-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(48-1)*N_STATES+(1-1)]*s[(48-1)*N_STATES+(1-1)])*s[(48-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(62)] = (S[(49-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(49-1)*N_STATES+(1-1)])-(S[(49-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(49-1)*N_STATES+(1-1)]*s[(49-1)*N_STATES+(1-1)])*s[(49-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(63)] = (S[(50-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(50-1)*N_STATES+(1-1)])-(S[(50-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(50-1)*N_STATES+(1-1)]*s[(50-1)*N_STATES+(1-1)])*s[(50-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(64)] = (S[(51-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(51-1)*N_STATES+(1-1)])-(S[(51-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(51-1)*N_STATES+(1-1)]*s[(51-1)*N_STATES+(1-1)])*s[(51-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(65)] = (S[(52-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(52-1)*N_STATES+(1-1)])-(S[(52-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(52-1)*N_STATES+(1-1)]*s[(52-1)*N_STATES+(1-1)])*s[(52-1)*N_STATES+(2-1)])/p[2-1]; + jac[(5)*(N_OBS)+(66)] = (S[(53-1)*SENSDIM+(10-1)]*p[3-1])/(p[2-1]*s[(53-1)*N_STATES+(1-1)])-(S[(53-1)*SENSDIM+(9-1)]*p[3-1]*1.0/(s[(53-1)*N_STATES+(1-1)]*s[(53-1)*N_STATES+(1-1)])*s[(53-1)*N_STATES+(2-1)])/p[2-1]; +} diff --git a/odemex/observerFunctions/ccode/jac.h b/odemex/observerFunctions/ccode/jac.h new file mode 100644 index 0000000..940c2e2 --- /dev/null +++ b/odemex/observerFunctions/ccode/jac.h @@ -0,0 +1,4 @@ +#define CJAC + +void jacobian(double *obj, double *s, double *p, double *d, double *u, double *S ); + diff --git a/odemex/observerFunctions/ccode/objfn.c b/odemex/observerFunctions/ccode/objfn.c new file mode 100644 index 0000000..7434101 --- /dev/null +++ b/odemex/observerFunctions/ccode/objfn.c @@ -0,0 +1,72 @@ +#include "objfn.h" + + +void objectiveFn(double *obs, double *s, double *p, double *d, double *u ) { + obs[0] = p[1-1]*s[(1-1)*N_STATES+(1-1)]*u[1-1]*(p[N_PARS+1-1]+1.0); + obs[1] = p[1-1]*s[(2-1)*N_STATES+(1-1)]*u[1-1]*(p[N_PARS+1-1]+1.0); + obs[2] = p[1-1]*s[(3-1)*N_STATES+(1-1)]*u[1-1]*(p[N_PARS+1-1]+1.0); + obs[3] = p[1-1]*s[(4-1)*N_STATES+(1-1)]*u[1-1]*(p[N_PARS+1-1]+1.0); + obs[4] = p[1-1]*s[(5-1)*N_STATES+(1-1)]*u[1-1]*(p[N_PARS+1-1]+1.0); + obs[5] = p[1-1]*s[(6-1)*N_STATES+(1-1)]*u[1-1]*(p[N_PARS+1-1]+1.0); + obs[6] = p[1-1]*s[(7-1)*N_STATES+(1-1)]*u[1-1]*(p[N_PARS+1-1]+1.0); + obs[7] = p[1-1]*s[(9-1)*N_STATES+(1-1)]*u[1-1]*(p[N_PARS+1-1]+1.0); + obs[8] = p[1-1]*s[(11-1)*N_STATES+(1-1)]*u[1-1]*(p[N_PARS+1-1]+1.0); + obs[9] = p[1-1]*s[(12-1)*N_STATES+(1-1)]*u[1-1]*(p[N_PARS+1-1]+1.0); + obs[10] = p[1-1]*s[(13-1)*N_STATES+(1-1)]*u[1-1]*(p[N_PARS+1-1]+1.0); + obs[11] = (p[2-1]*(-d[1-1]+s[(1-1)*N_STATES+(1-1)]+s[(1-1)*N_STATES+(2-1)]))/(p[N_PARS+2-1]+1.0); + obs[12] = (p[2-1]*(-d[2-1]+s[(13-1)*N_STATES+(1-1)]+s[(13-1)*N_STATES+(2-1)]))/(p[N_PARS+2-1]+1.0); + obs[13] = (p[2-1]*(-d[3-1]+s[(23-1)*N_STATES+(1-1)]+s[(23-1)*N_STATES+(2-1)]))/(p[N_PARS+2-1]+1.0); + obs[14] = (p[2-1]*(-d[4-1]+s[(33-1)*N_STATES+(1-1)]+s[(33-1)*N_STATES+(2-1)]))/(p[N_PARS+2-1]+1.0); + obs[15] = (p[2-1]*(-d[5-1]+s[(43-1)*N_STATES+(1-1)]+s[(43-1)*N_STATES+(2-1)]))/(p[N_PARS+2-1]+1.0); + obs[16] = (p[3-1]*s[(1-1)*N_STATES+(2-1)])/(p[2-1]*s[(1-1)*N_STATES+(1-1)]); + obs[17] = (p[3-1]*s[(2-1)*N_STATES+(2-1)])/(p[2-1]*s[(2-1)*N_STATES+(1-1)]); + obs[18] = (p[3-1]*s[(3-1)*N_STATES+(2-1)])/(p[2-1]*s[(3-1)*N_STATES+(1-1)]); + obs[19] = (p[3-1]*s[(4-1)*N_STATES+(2-1)])/(p[2-1]*s[(4-1)*N_STATES+(1-1)]); + obs[20] = (p[3-1]*s[(5-1)*N_STATES+(2-1)])/(p[2-1]*s[(5-1)*N_STATES+(1-1)]); + obs[21] = (p[3-1]*s[(6-1)*N_STATES+(2-1)])/(p[2-1]*s[(6-1)*N_STATES+(1-1)]); + obs[22] = (p[3-1]*s[(8-1)*N_STATES+(2-1)])/(p[2-1]*s[(8-1)*N_STATES+(1-1)]); + obs[23] = (p[3-1]*s[(10-1)*N_STATES+(2-1)])/(p[2-1]*s[(10-1)*N_STATES+(1-1)]); + obs[24] = (p[3-1]*s[(11-1)*N_STATES+(2-1)])/(p[2-1]*s[(11-1)*N_STATES+(1-1)]); + obs[25] = (p[3-1]*s[(12-1)*N_STATES+(2-1)])/(p[2-1]*s[(12-1)*N_STATES+(1-1)]); + obs[26] = (p[3-1]*s[(13-1)*N_STATES+(2-1)])/(p[2-1]*s[(13-1)*N_STATES+(1-1)]); + obs[27] = (p[3-1]*s[(14-1)*N_STATES+(2-1)])/(p[2-1]*s[(14-1)*N_STATES+(1-1)]); + obs[28] = (p[3-1]*s[(15-1)*N_STATES+(2-1)])/(p[2-1]*s[(15-1)*N_STATES+(1-1)]); + obs[29] = (p[3-1]*s[(16-1)*N_STATES+(2-1)])/(p[2-1]*s[(16-1)*N_STATES+(1-1)]); + obs[30] = (p[3-1]*s[(17-1)*N_STATES+(2-1)])/(p[2-1]*s[(17-1)*N_STATES+(1-1)]); + obs[31] = (p[3-1]*s[(18-1)*N_STATES+(2-1)])/(p[2-1]*s[(18-1)*N_STATES+(1-1)]); + obs[32] = (p[3-1]*s[(19-1)*N_STATES+(2-1)])/(p[2-1]*s[(19-1)*N_STATES+(1-1)]); + obs[33] = (p[3-1]*s[(20-1)*N_STATES+(2-1)])/(p[2-1]*s[(20-1)*N_STATES+(1-1)]); + obs[34] = (p[3-1]*s[(21-1)*N_STATES+(2-1)])/(p[2-1]*s[(21-1)*N_STATES+(1-1)]); + obs[35] = (p[3-1]*s[(22-1)*N_STATES+(2-1)])/(p[2-1]*s[(22-1)*N_STATES+(1-1)]); + obs[36] = (p[3-1]*s[(23-1)*N_STATES+(2-1)])/(p[2-1]*s[(23-1)*N_STATES+(1-1)]); + obs[37] = (p[3-1]*s[(24-1)*N_STATES+(2-1)])/(p[2-1]*s[(24-1)*N_STATES+(1-1)]); + obs[38] = (p[3-1]*s[(25-1)*N_STATES+(2-1)])/(p[2-1]*s[(25-1)*N_STATES+(1-1)]); + obs[39] = (p[3-1]*s[(26-1)*N_STATES+(2-1)])/(p[2-1]*s[(26-1)*N_STATES+(1-1)]); + obs[40] = (p[3-1]*s[(27-1)*N_STATES+(2-1)])/(p[2-1]*s[(27-1)*N_STATES+(1-1)]); + obs[41] = (p[3-1]*s[(28-1)*N_STATES+(2-1)])/(p[2-1]*s[(28-1)*N_STATES+(1-1)]); + obs[42] = (p[3-1]*s[(29-1)*N_STATES+(2-1)])/(p[2-1]*s[(29-1)*N_STATES+(1-1)]); + obs[43] = (p[3-1]*s[(30-1)*N_STATES+(2-1)])/(p[2-1]*s[(30-1)*N_STATES+(1-1)]); + obs[44] = (p[3-1]*s[(31-1)*N_STATES+(2-1)])/(p[2-1]*s[(31-1)*N_STATES+(1-1)]); + obs[45] = (p[3-1]*s[(32-1)*N_STATES+(2-1)])/(p[2-1]*s[(32-1)*N_STATES+(1-1)]); + obs[46] = (p[3-1]*s[(33-1)*N_STATES+(2-1)])/(p[2-1]*s[(33-1)*N_STATES+(1-1)]); + obs[47] = (p[3-1]*s[(34-1)*N_STATES+(2-1)])/(p[2-1]*s[(34-1)*N_STATES+(1-1)]); + obs[48] = (p[3-1]*s[(35-1)*N_STATES+(2-1)])/(p[2-1]*s[(35-1)*N_STATES+(1-1)]); + obs[49] = (p[3-1]*s[(36-1)*N_STATES+(2-1)])/(p[2-1]*s[(36-1)*N_STATES+(1-1)]); + obs[50] = (p[3-1]*s[(37-1)*N_STATES+(2-1)])/(p[2-1]*s[(37-1)*N_STATES+(1-1)]); + obs[51] = (p[3-1]*s[(38-1)*N_STATES+(2-1)])/(p[2-1]*s[(38-1)*N_STATES+(1-1)]); + obs[52] = (p[3-1]*s[(39-1)*N_STATES+(2-1)])/(p[2-1]*s[(39-1)*N_STATES+(1-1)]); + obs[53] = (p[3-1]*s[(40-1)*N_STATES+(2-1)])/(p[2-1]*s[(40-1)*N_STATES+(1-1)]); + obs[54] = (p[3-1]*s[(41-1)*N_STATES+(2-1)])/(p[2-1]*s[(41-1)*N_STATES+(1-1)]); + obs[55] = (p[3-1]*s[(42-1)*N_STATES+(2-1)])/(p[2-1]*s[(42-1)*N_STATES+(1-1)]); + obs[56] = (p[3-1]*s[(43-1)*N_STATES+(2-1)])/(p[2-1]*s[(43-1)*N_STATES+(1-1)]); + obs[57] = (p[3-1]*s[(44-1)*N_STATES+(2-1)])/(p[2-1]*s[(44-1)*N_STATES+(1-1)]); + obs[58] = (p[3-1]*s[(45-1)*N_STATES+(2-1)])/(p[2-1]*s[(45-1)*N_STATES+(1-1)]); + obs[59] = (p[3-1]*s[(46-1)*N_STATES+(2-1)])/(p[2-1]*s[(46-1)*N_STATES+(1-1)]); + obs[60] = (p[3-1]*s[(47-1)*N_STATES+(2-1)])/(p[2-1]*s[(47-1)*N_STATES+(1-1)]); + obs[61] = (p[3-1]*s[(48-1)*N_STATES+(2-1)])/(p[2-1]*s[(48-1)*N_STATES+(1-1)]); + obs[62] = (p[3-1]*s[(49-1)*N_STATES+(2-1)])/(p[2-1]*s[(49-1)*N_STATES+(1-1)]); + obs[63] = (p[3-1]*s[(50-1)*N_STATES+(2-1)])/(p[2-1]*s[(50-1)*N_STATES+(1-1)]); + obs[64] = (p[3-1]*s[(51-1)*N_STATES+(2-1)])/(p[2-1]*s[(51-1)*N_STATES+(1-1)]); + obs[65] = (p[3-1]*s[(52-1)*N_STATES+(2-1)])/(p[2-1]*s[(52-1)*N_STATES+(1-1)]); + obs[66] = (p[3-1]*s[(53-1)*N_STATES+(2-1)])/(p[2-1]*s[(53-1)*N_STATES+(1-1)]); +} diff --git a/odemex/observerFunctions/ccode/objfn.h b/odemex/observerFunctions/ccode/objfn.h new file mode 100644 index 0000000..5dd5ab7 --- /dev/null +++ b/odemex/observerFunctions/ccode/objfn.h @@ -0,0 +1,15 @@ + +#include "mex.h" + +#define N_DATA 5 +#define N_INPUT 1 +#define N_PARS 3 +#define N_STATES 2 +#define N_OBSPARS 2 +#define N_ICPARS 1 +#define N_OBS 67 +#define N_TIME 53 +#define SENSDIM 10 + +void objectiveFn(double *obj, double *s, double *p, double *d, double *u ); + diff --git a/odemex/observerFunctions/ccode/wrap.c b/odemex/observerFunctions/ccode/wrap.c new file mode 100644 index 0000000..dfc9343 --- /dev/null +++ b/odemex/observerFunctions/ccode/wrap.c @@ -0,0 +1,74 @@ + +#include "jac.h" +#include "objfn.h" +//#include "time.h" +//%#include "string.h" + +int sensitivities; + +void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { + + sensitivities = 0; + + if (nrhs == 0) { + //printf( "Call function as:\ny = funcName(x0)\n", N_STATES, N_PARAMS, N_INPUTS ); + return; + } + + if ( nrhs < 4 ) mexErrMsgTxt( "ERROR: Incorrect number of input arguments\nFormat should be: (x, p, data, u, S*)\n* are optional" ); + + /* Check input dimensions */ + if ( ( mxGetM( prhs[0] ) != N_STATES ) && ( mxGetN( prhs[0] ) != N_TIME ) ) + { + printf( "ERROR: State matrix has incorrect dimensions! Expected %d by %d, found %d by %d", N_STATES, N_TIME, mxGetM( prhs[0] ), mxGetN( prhs[0] ) ); + mexErrMsgTxt( "" ); + } + + if ( mxGetN( prhs[1] ) != ( N_PARS + N_OBSPARS + N_ICPARS ) ) + { + printf( "ERROR: Parameter vector has incorrect dimensions! Expected %d, found %d", N_PARS+N_OBSPARS+N_ICPARS, mxGetN( prhs[1] ) ); + mexErrMsgTxt( "" ); + } + + if ( mxGetN( prhs[2] ) != ( N_DATA ) ) + { + printf( "ERROR: Data vector has incorrect dimensions! Expected %d, found %d", N_DATA, mxGetN( prhs[2] ) ); + mexErrMsgTxt( "" ); + } + + if ( mxGetN( prhs[3] ) != ( N_INPUT ) ) + { + printf( "ERROR: Input vector has incorrect dimensions! Expected %d, found %d", N_INPUT, mxGetN( prhs[3] ) ); + mexErrMsgTxt( "" ); + } + + if ( nlhs > 1 ) + { + if ( nrhs < 5 ) mexErrMsgTxt( "ERROR: Sensitivity outputs require a valid sensitivity matrix" ); + if ( mxGetM( prhs[4] ) != ( N_STATES * ( N_STATES + N_PARS ) ) && ( mxGetN( prhs[4] ) != N_TIME ) ) + { + printf( "ERROR: Sensitivity matrix has incorrect dimensions! Expected %d by %d, found %d by %d", N_STATES * ( N_STATES + N_PARS ), N_TIME, mxGetM( prhs[4] ), mxGetN( prhs[4] ) ); + mexErrMsgTxt( "" ); + } else { + #ifdef CJAC + sensitivities = 1; + #endif + } + } + + plhs[0] = mxCreateDoubleMatrix( N_OBS, 1, mxREAL ); + + objectiveFn( mxGetPr( plhs[0] ), mxGetPr( prhs[0] ), mxGetPr( prhs[1] ), mxGetPr( prhs[2] ), mxGetPr( prhs[3] ) ); + + #ifdef CJAC + if ( sensitivities == 1 ) + { + plhs[1] = mxCreateDoubleMatrix( N_OBS, N_OBSPARS + N_PARS + N_ICPARS, mxREAL ); + jacobian( mxGetPr( plhs[1] ), mxGetPr( prhs[0] ), mxGetPr( prhs[1] ), mxGetPr( prhs[2] ), mxGetPr( prhs[3] ), mxGetPr( prhs[4] ) ); + } + #endif + +} + + + diff --git a/odemex/observerFunctions/compileObjective.m b/odemex/observerFunctions/compileObjective.m new file mode 100644 index 0000000..5811e28 --- /dev/null +++ b/odemex/observerFunctions/compileObjective.m @@ -0,0 +1,36 @@ + +function compileObjective( outputFileName, jac, observPath ) + if jac == 1 + eval( sprintf( 'mex -output %s %sccode/wrap.c %sccode/objfn.c %sccode/jac.c', outputFileName, observPath, observPath, observPath ) ); + else + eval( sprintf( 'mex -output %s %sccode/wrap.c %sccode/objfn.c', outputFileName, observPath, observPath ) ); + end + +% +% Joep Vanlier, 2012 +% +% Licensing: +% Copyright (C) 2009-2012 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% + \ No newline at end of file diff --git a/odemex/observerFunctions/grabNextBracket.m b/odemex/observerFunctions/grabNextBracket.m new file mode 100644 index 0000000..80e5c4f --- /dev/null +++ b/odemex/observerFunctions/grabNextBracket.m @@ -0,0 +1,59 @@ +function [ before, values, remainder ] = grabNextBracket( l ) + + before = ''; + values = []; + remainder = ''; + + pos = 1; + + while ( pos < length( l ) & ( l(pos) ~= '[' ) ) + pos = pos + 1; + end + + if l(pos) == '[' + + before = l( 1 : pos ); + pos1 = pos; + depth = 1; + + while ( ( pos <= length( l ) ) & ( depth > 0 ) ) + if l(pos) == ']' + depth = depth - 1; + end + pos = pos + 1; + end + values = eval( l( pos1 : pos - 1 ) ); + + remainder = l( pos-1:end ); + else + before = l; + end + + +% +% Joep Vanlier, 2012 +% +% Licensing: +% Copyright (C) 2009-2012 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/observerFunctions/grabNextDataBracket.m b/odemex/observerFunctions/grabNextDataBracket.m new file mode 100644 index 0000000..72cfe20 --- /dev/null +++ b/odemex/observerFunctions/grabNextDataBracket.m @@ -0,0 +1,59 @@ +function [ before, values, remainder ] = grabNextDataBracket( l ); + + before = ''; + values = []; + remainder = ''; + + pos = 1; + + while ( pos < length( l ) & ( l(pos) ~= '{' ) ) + pos = pos + 1; + end + + if l(pos) == '{' + + before = [ l( 1 : pos - 1 ) '[' ]; + pos1 = pos; + depth = 1; + + while ( ( pos <= length( l ) ) & ( depth > 0 ) ) + if l(pos) == '}' + depth = depth - 1; + end + pos = pos + 1; + end + values = eval( [ '[' l( pos1 + 1: pos - 2 ) ']' ] ); + + remainder = [ ']' l( pos:end ) ]; + else + before = l; + end + + +% +% Joep Vanlier, 2012 +% +% Licensing: +% Copyright (C) 2009-2012 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/observerFunctions/nJac.m b/odemex/observerFunctions/nJac.m new file mode 100644 index 0000000..b9db964 --- /dev/null +++ b/odemex/observerFunctions/nJac.m @@ -0,0 +1,40 @@ + +function jac = nJac( func, pars, dx, subVec ) + + JacDiffs = dx * eye( length( pars ) ); + + if nargin < 4 + subVec = 1 : length( pars ); + end + + for a = subVec + jac(:,a) = ( feval( func, pars + JacDiffs(a,:) ) - feval( func, pars ) ) / dx; + end + +end% +% Joep Vanlier, 2012 +% +% Licensing: +% Copyright (C) 2009-2012 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/observerFunctions/observerFunctions.m b/odemex/observerFunctions/observerFunctions.m new file mode 100644 index 0000000..0a4ca74 --- /dev/null +++ b/odemex/observerFunctions/observerFunctions.m @@ -0,0 +1,344 @@ +function [ timePts, parIndices, obsIndices, icIndices ] = observerFunctions( obsName, obs, mStruct, cjac ) + +observPath = [ fileparts( mfilename( 'fullpath' ) ) '/' ]; + +nStates = max( structIndices( mStruct.s ) ); +nPars = max( structIndices( mStruct.p ) ); +try + nInput = max( structIndices( mStruct.u ) ); +catch + nInput = 0 ; +end +parIndices = 1 : nPars; + +allNames = []; types = []; +try allNames = [ allNames ; fieldnames( mStruct.c ); ]; types = [ types ; ones( length( fieldnames( mStruct.c ) ), 1 ) ]; catch; end; +try allNames = [ allNames ; fieldnames( mStruct.p ); ]; types = [ types ; 2*ones( length( fieldnames( mStruct.p ) ), 1 ) ]; catch; end; +try allNames = [ allNames ; fieldnames( mStruct.s ); ]; types = [ types ; 3*ones( length( fieldnames( mStruct.s ) ), 1 ) ]; catch; end; +try allNames = [ allNames ; fieldnames( mStruct.i ); ]; types = [ types ; 4*ones( length( fieldnames( mStruct.i ) ), 1 ) ]; catch; end; +try allNames = [ allNames ; fieldnames( mStruct.o ); ]; types = [ types ; 5*ones( length( fieldnames( mStruct.o ) ), 1 ) ]; catch; end; +try allNames = [ allNames ; fieldnames( mStruct.u ); ]; types = [ types ; 6*ones( length( fieldnames( mStruct.u ) ), 1 ) ]; catch; end; + +try + nObsPars = max( structIndices( mStruct.o ) ); + obsIndices = [ 1 : nObsPars ] + nPars; +catch + nObsPars = 0; + obsIndices = []; +end + +icIndices = zeros( nStates, 1 ); +try + icPars = structIndices( mStruct.i ); + nIcPars = length( icPars ); + + icIndices( icPars ) = [1:nIcPars]+nObsPars+nPars; +catch + nIcPars = 0; +end + +% Grab all the time points that need to be simulated for the objective +% function +disp( 'Fetching timepoints' ); +timePts = []; +for a = 1 : length( obs ) + [ before, values, remainder ] = grabNextBracket( obs{a} ); + timePts = [timePts, values]; + while length( remainder ) > 1 + [ before, values, remainder ] = grabNextBracket( remainder ); + timePts = [timePts, values]; + end +end +timePts = unique( timePts ); + +% If the zeroth timepoint isn't in the list, add it, because otherwise the +% simulation will have problems +if max(timePts==0) ~= 1 + timePts = [0 timePts]; +end +nTime = length(timePts); + +disp( 'Replacing timepoints with their indices' ); +% Replace the time points by their indices +for a = 1 : length( obs ) + [ before, values, remainder ] = grabNextBracket( obs{a} ); + obsB{a} = [ before replaceWithIndex( values, timePts ) ]; + while length( remainder ) > 1 + [ before, values, remainder ] = grabNextBracket( remainder ); + obsB{a} = [ obsB{a} before replaceWithIndex( values, timePts ) ]; + end + obsB{a} = [ obsB{a} remainder ]; +end + +% Grab all the data points +disp( 'Fetching datapoints' ); +dataPts = []; +for a = 1 : length( obs ) + [ before, values, remainder ] = grabNextDataBracket( obsB{a} ); + obsB{a} = [ before printAsString( values ) ]; + dataPts = [dataPts, values]; + while length( remainder ) > 1 + [ before, values, remainder ] = grabNextDataBracket( remainder ); + obsB{a} = [ obsB{a} before printAsString( values ) ]; + dataPts = [dataPts, values]; + end +end +obsB{a} = [ obsB{a} remainder ]; +dataPts = unique( dataPts ); +nData = length( dataPts ); + +disp( 'Generating syms for the datapoints' ); +for it1 = 1 : length( dataPts ) + data(it1) = sym( sprintf( 'data_%d', it1 ) ); +end + + + +% Generate all required state syms +disp( 'Generating syms for the states' ); + +fields = fieldnames( mStruct.s ); +for it1 = 1 : length( fields ) + for it2 = 1 : length( timePts ) + syms( sprintf( 's%d_%d', getfield( mStruct.s, fields{it1} ), it2 ) ); + eval( sprintf( 's%d(%d) = s%d_%d;', getfield( mStruct.s, fields{it1} ), it2, getfield( mStruct.s, fields{it1} ), it2 ) ); + end +end + +% Process the model parameters +disp( 'Generating syms for the model parameters' ); +names = fieldnames( mStruct.p ); +for it2 = 1 : length( names ) + parNo = getfield( mStruct.p, names{it2}); + p(parNo) = sym( sprintf( 'p%d', parNo ) ); +end + +% Process the observable parameters +disp( 'Generating syms for the observational parameters' ); +try + names = fieldnames( mStruct.o ); + for it2 = 1 : length( names ) + parNo = getfield( mStruct.o, names{it2} ); + eval( sprintf( 'syms o%d;', parNo ) ); + eval( sprintf( 'o(%d) = o%d;', parNo, parNo ) ); + end +catch +end + +% Process the initial condition parameters +disp( 'Generating syms for the initial condition parameters' ); +try + names = fieldnames( mStruct.i ); + for it2 = 1 : length( names ) + parNo = getfield( mStruct.i, names{it2} ); + eval( sprintf( 'syms i%d;', parNo ) ); + eval( sprintf( 'i(%d) = i%d;', parNo, parNo ) ); + end +catch +end + +% Process the inputs +disp( 'Generating syms for the inputs' ); +try + names = fieldnames( mStruct.u ); + for it2 = 1 : length( names ) + parNo = getfield( mStruct.u, names{it2} ); + eval( sprintf( 'syms u%d;', parNo ) ); + eval( sprintf( 'u(%d) = u%d;', parNo, parNo ) ); + end +catch +end + +% Replace identifiers by their respective indices +disp( 'Parsing the objective function cell array' ); +expressionTokens = '&()[]/*+-^@ %<>,;={}|'; +for c = 1 : length( obs ) + output = ''; + + remain = obsB{c}; + while length( remain ) > 0 + [ token, remain, tokensLost ] = strtok2( remain, expressionTokens ); + + for q = 1 : length( allNames ) + if strcmp( token, allNames(q) ) == 1 + switch types( q ) + case 1 + token = num2str( getfield( mStruct.c, allNames{q} ) ); + case 2 + token = sprintf( 'p(%d)', getfield( mStruct.p, allNames{q} ) ); + case 3 + token = sprintf( 's%d', getfield( mStruct.s, allNames{q} ) ); + case 4 + token = sprintf( 'i(%d)', getfield( mStruct.i, allNames{q} ) ); + case 5 + token = sprintf( 'o(%d)', getfield( mStruct.o, allNames{q} ) ); + case 6 + token = sprintf( 'u(%d)', getfield( mStruct.u, allNames{q} ) ); + end + end + end + output = [ output tokensLost token ]; + end + obsB{c} = output; +end + +% Construct objective function +obj = []; +for a = 1 : length( obsB ); + try + obj = [ obj, eval( obsB{a} ) ]; + catch ME + a + obsB{a} + disp( '>>> ERROR: Undeclared variable in objective function(s)' ); + rethrow(ME) + end +end + +c_code = ccode( obj ); +c_code = strrep( c_code, 'obj[0]', 'obs' ); +c_code = regexprep( c_code, 's(\d+)_(\d+)', 's[($2-1)*N_STATES+($1-1)]' ); +c_code = regexprep( c_code, 'p(\d+)', 'p[$1-1]' ); +c_code = regexprep( c_code, 'u(\d+)', 'u[$1-1]' ); +c_code = regexprep( c_code, 'o(\d+)', 'p[N_PARS+$1-1]' ); +c_code = regexprep( c_code, 'i(\d+)', 'p[N_PARS+N_OBSPARS+$1-1]' ); +c_code = regexprep( c_code, 'data_(\d+)', 'd[$1-1]' ); + +% Set up the header file +nObs = length( obj ); +nStates = length( fieldnames( mStruct.s ) ); +nPars = length( fieldnames( mStruct.p ) ); +nObsPars = length( fieldnames( mStruct.o ) ); + +disp( 'Writing C file for the objective function' ) +fid = fopen( [observPath 'ccode/objfn.c'], 'w' ); +fprintf( fid, '#include "objfn.h"\n\n\nvoid objectiveFn(double *obs, double *s, double *p, double *d, double *u ) {\n%s\n}\n', c_code ); +fid = fclose( fid ); + +fid = fopen( [observPath 'ccode/objfn.h'], 'w' ); +fprintf( fid, '\n#include "mex.h"\n\n#define N_DATA %d\n#define N_INPUT %d\n#define N_PARS %d\n#define N_STATES %d\n#define N_OBSPARS %d\n#define N_ICPARS %d\n#define N_OBS %d\n#define N_TIME %d\n#define SENSDIM %d\n\nvoid objectiveFn(double *obj, double *s, double *p, double *d, double *u );\n\n', nData, nInput, nPars, nStates, nObsPars, nIcPars, nObs, nTime, nStates * ( nStates + nPars ) ); +fid = fclose(fid); + +if cjac == 1 + + % Now that the objective function is computed, we can process the + % derivatives + % + % dy1 dp1 + % dy2 dp1 + % dy1 dp2 + % dy2 dp2 + % Compute all the derivatives + disp( 'Generating syms for all state derivatives output' ); + S = sym( zeros( nStates * (nPars+nStates), length( timePts ) ) ); + for a = 1 : length( timePts ) + for b = 1 : nStates * ( nPars + nStates ) + S( b, a ) = sym( sprintf( 'S_%d_%d', b, a ) ); + end + end + + disp( 'Constructing the Jacobian (model parameters)' ); + jac = sym( zeros( length( obj ), nPars + nObsPars + nIcPars ) ); + for a = 1 : length( obj ) + disp( sprintf( 'Observable %d/%d', a, length(obj) ) ); + for b = 1 : nPars + index = length( obj ) * (b-1) + a; + + % Process all partial derivatives with respect to the observables + % do/dx dx/dp (based on model sensitivities) + for c = 1 : nStates + index = ( nStates * (b-1) ) + c; + curJac = eval(sprintf( 'jacobian(obj(%d),s%d)', a, c ) ); + jac( a, b ) = jac( a, b ) + curJac * S(index,:).'; + end + + % Process partial derivatives directly with respect to the + % parameters + % do/dp + curJac = eval( sprintf( 'diff(obj(%d),p(%d))', a, b ) ); + jac(a,b) = jac(a,b) + curJac; + end + + % Objective function parameters (metapars) + for b = 1 : nObsPars + % Process derivatives w.r.t. parameters + curJac = eval( sprintf( 'diff(obj(%d),o(%d))', a, b ) ); + jac(a,b+nPars) = jac(a,b+nPars) + curJac; + end + + % Initial condition parameters + for b = 1 : nIcPars + % Process all partial derivatives with respect to the observables + % do/dx dx/dp (based on model sensitivities) + for c = 1 : nStates + index = ( nStates * (nPars+icPars(b)-1) ) + c; + curJac = eval(sprintf( 'jacobian(obj(%d),s%d)', a, c ) ); + jac( a, b+nPars+nObsPars ) = jac( a, b+nPars+nObsPars ) + curJac * S(index,:).'; + end + + % Process derivatives w.r.t. parameters + % curJac = eval( sprintf( 'diff(obj(%d),i(%d))', a, icPars(b) ) ); + % jac(a,b+nPars+nObsPars) = jac(a,b+nPars+nObsPars) + curJac; + end + end + + + disp( 'Writing C file for the jacobian' ) + jac = jac.'; + c_code = ccode( jac ); + %c_code = regexprep( c_code, 'jac\[(\d+)\]\[(\d+)\]', 'jac[($1)*(N_PARS+N_OBSPARS+N_ICPARS)+($2)]' ); + c_code = regexprep( c_code, 'jac\[(\d+)\]\[(\d+)\]', 'jac[($1)*(N_OBS)+($2)]' ); + c_code = regexprep( c_code, 's(\d+)_(\d+)', 's[($2-1)*N_STATES+($1-1)]' ); + c_code = regexprep( c_code, 'S_(\d+)_(\d+)', 'S[($2-1)*SENSDIM+($1-1)]' ); + c_code = regexprep( c_code, 'p(\d+)', 'p[$1-1]' ); + c_code = regexprep( c_code, 'u(\d+)', 'u[$1-1]' ); + c_code = regexprep( c_code, 'o(\d+)', 'p[N_PARS+$1-1]' ); + c_code = regexprep( c_code, 'i(\d+)', 'p[N_PARS+N_OBSPARS+$1-1]' ); + c_code = regexprep( c_code, 'data_(\d+)', 'd[$1-1]' ); + + fid = fopen( [observPath 'ccode/jac.c' ], 'w' ); + fprintf( fid, '#include "objfn.h"\n\n\nvoid jacobian(double *jac, double *s, double *p, double *d, double *u, double *S ) {\n%s\n}\n', c_code ); + fid = fclose( fid ); + + fid = fopen( [observPath 'ccode/jac.h'], 'w' ); + fprintf( fid, '#define CJAC\n\nvoid jacobian(double *obj, double *s, double *p, double *d, double *u, double *S );\n\n', nData, nPars, nStates, nObsPars, nObs, nTime ); + fid = fclose(fid); +else + fid = fopen( [observPath 'ccode/jac.h'], 'w' ); + fprintf( fid, '\n\n', nData, nPars, nStates, nObsPars, nObs, nTime ); + fid = fclose(fid); +end + +% Compiling C function(s) +disp( 'Compiling C functions' ); +compileObjective( obsName, cjac, observPath ); + +disp( 'Done!' ); + +% +% Joep Vanlier, 2012 +% +% Licensing: +% Copyright (C) 2009-2012 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/observerFunctions/printAsString.m b/odemex/observerFunctions/printAsString.m new file mode 100644 index 0000000..7845b72 --- /dev/null +++ b/odemex/observerFunctions/printAsString.m @@ -0,0 +1,37 @@ +function s = printAsString( list ) + + s = ''; + if ~isempty( list ) + s = sprintf( '%d', list(1) ); + for a = 2 : length( list ) + s = sprintf( '%s, %d', s, list(a) ); + end + end + +% +% Joep Vanlier, 2012 +% +% Licensing: +% Copyright (C) 2009-2012 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/observerFunctions/replaceWithIndex.m b/odemex/observerFunctions/replaceWithIndex.m new file mode 100644 index 0000000..0661a34 --- /dev/null +++ b/odemex/observerFunctions/replaceWithIndex.m @@ -0,0 +1,45 @@ +function s = replaceWithIndex( list, allpoints ) + + s = ''; + indices = []; + for a = 1 : length( list ) + for b = 1 : length( allpoints ) + if ( list(a) == allpoints(b) ) + indices(a) = b; + end + end + end + if ~isempty( indices ) + s = sprintf( '%d', indices(1) ); + for a = 2 : length( indices ) + s = sprintf( '%s, %d', s, indices(a) ); + end + end + +% +% Joep Vanlier, 2012 +% +% Licensing: +% Copyright (C) 2009-2012 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/observerFunctions/strtok2.m b/odemex/observerFunctions/strtok2.m new file mode 100644 index 0000000..57550e9 --- /dev/null +++ b/odemex/observerFunctions/strtok2.m @@ -0,0 +1,41 @@ +% Function that grabs a token, but shows you which chars were removed + +function [ token, remain, tokensLost ] = strtok2( string, tokens ) + + l = length( string ); + [ token, remain ] = strtok( string, tokens ); + + missing = length( string ) - length( token ) - length( remain ); + + tokensLost = string( 1 : missing ); + + + + +% +% Joep Vanlier, 2011 +% +% Licensing: +% Copyright (C) 2009-2011 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/observerFunctions/structIndices.m b/odemex/observerFunctions/structIndices.m new file mode 100644 index 0000000..7e58072 --- /dev/null +++ b/odemex/observerFunctions/structIndices.m @@ -0,0 +1,34 @@ +function [ indices ] = structIndices( struct ) + + names = fieldnames( struct ); + for a = 1 : length( names ) + indices(a) = getfield( struct, names{a} ); + end +end +% +% Joep Vanlier, 2012 +% +% Licensing: +% Copyright (C) 2009-2012 Joep Vanlier. All rights +% reserved. +% +% Contact:joep.vanlier@gmail.com +% +% This file is part of the puaMAT. +% +% puaMAT is free software: you can redistribute it +% and/or modify it under the terms of the GNU General +% Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at +% your option) any later version. +% +% puaMAT is distributed in the hope that it will be +% useful, but WITHOUT ANY WARRANTY; without even the +% implied warranty of MERCHANTABILITY or FITNESS FOR A +% PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General +% Public License along with puaMAT. If not, see +% http://www.gnu.org/licenses/ +% diff --git a/odemex/observerFunctions/useObserver.m b/odemex/observerFunctions/useObserver.m new file mode 100644 index 0000000..aabefcc --- /dev/null +++ b/odemex/observerFunctions/useObserver.m @@ -0,0 +1,9 @@ +function [f,J] = useObserver( obsFunc, simFunc, pars ) + +if nargout == 1 + [f] = feval( simFunc, pars ); + f = obsFunc( f, pars ); +else + [~, f, J] = feval( simFunc, pars ); + [f, J] = obsFunc( f, pars, J ); +end diff --git a/setup.m b/setup.m new file mode 100644 index 0000000..a36e582 --- /dev/null +++ b/setup.m @@ -0,0 +1,11 @@ +function setup() + +addpath(genpath('.')); + +disp('Added the AMF core folder and subfolders to path.'); + +try + matlabpool +catch err + fprintf('No parallel pool available.'); +end \ No newline at end of file diff --git a/temp/C_tiemannModel_ODE.m b/temp/C_tiemannModel_ODE.m new file mode 100644 index 0000000..f4e373b --- /dev/null +++ b/temp/C_tiemannModel_ODE.m @@ -0,0 +1,129 @@ +function dxdt = C_tiemannModel_ODE(t,x,p,u,m) + + +mwTG = m.c.mwTG; +mvTG = m.c.mvTG; +mwCE = m.c.mwCE; +mvCE = m.c.mvCE; +mwFC = m.c.mwFC; +mvFC = m.c.mvFC; +mwPL = m.c.mwPL; +mvPL = m.c.mvPL; +mwApoB = m.c.mwApoB; +navg = m.c.navg; +uH = m.c.uH; +plasma_volume = m.c.plasma_volume; +rs = m.c.rs; +npi = m.c.npi; + +hep_FC = x(m.s.hep_FC); +hep_CE = x(m.s.hep_CE); +hep_CE_ER = x(m.s.hep_CE_ER); +hep_TG = x(m.s.hep_TG); +hep_TG_ER = x(m.s.hep_TG_ER); +hep_TG_DNL = x(m.s.hep_TG_DNL); +hep_TG_ER_DNL = x(m.s.hep_TG_ER_DNL); +plasma_TG = x(m.s.plasma_TG); +plasma_C = x(m.s.plasma_C); +plasma_C_HDL = x(m.s.plasma_C_HDL); +plasma_FFA = x(m.s.plasma_FFA); + +Vm_FC_prod = p(m.p.Vm_FC_prod); +Vm_FC_met = p(m.p.Vm_FC_met); +Vm_CE_for = p(m.p.Vm_CE_for); +Vm_CE_def = p(m.p.Vm_CE_def); +Vm_CE_ER_for = p(m.p.Vm_CE_ER_for); +Vm_CE_ER_def = p(m.p.Vm_CE_ER_def); +Vm_TG_prod = p(m.p.Vm_TG_prod); +Vm_TG_met = p(m.p.Vm_TG_met); +Vm_TG_for = p(m.p.Vm_TG_for); +Vm_TG_ER_prod = p(m.p.Vm_TG_ER_prod); +Vm_TG_ER_for = p(m.p.Vm_TG_ER_for); +Vm_FFA_upt = p(m.p.Vm_FFA_upt); +Vm_FFA_prod = p(m.p.Vm_FFA_prod); +Vm_VLDL_TG = p(m.p.Vm_VLDL_TG); +Vm_VLDL_CE = p(m.p.Vm_VLDL_CE); +Vm_TG_CE_upt = p(m.p.Vm_TG_CE_upt); +Vm_TG_CE_upt_ph = p(m.p.Vm_TG_CE_upt_ph); +Vm_TG_hyd = p(m.p.Vm_TG_hyd); +Vm_TG_hyd_ph = p(m.p.Vm_TG_hyd_ph); +Vm_HDL_CE_for = p(m.p.Vm_HDL_CE_for); +Vm_HDL_CE_upt = p(m.p.Vm_HDL_CE_upt); +Vm_ApoB_prod = p(m.p.Vm_ApoB_prod); +Vm_TG_CE_upt_0 = p(m.p.Vm_TG_CE_upt_0); +Vm_TG_CE_upt_ph_0 = p(m.p.Vm_TG_CE_upt_ph_0); + +J_FC_production = Vm_FC_prod; +J_FC_metabolism = Vm_FC_met * hep_FC; +J_CE_formation = Vm_CE_for * hep_FC; +J_CE_deformation = Vm_CE_def * hep_CE; +J_CE_ER_formation = Vm_CE_ER_for * hep_FC; +J_CE_ER_deformation = Vm_CE_ER_def * hep_CE_ER; +J_TG_production = Vm_TG_prod; +J_TG_metabolism = Vm_TG_met * hep_TG; +J_TG_metabolism_DNL = Vm_TG_met * hep_TG_DNL; +J_TG_formation = Vm_TG_for * hep_TG_ER; +J_TG_formation_DNL = Vm_TG_for * hep_TG_ER_DNL; +J_TG_ER_production = Vm_TG_ER_prod; +J_TG_ER_formation = Vm_TG_ER_for * hep_TG; +J_TG_ER_formation_DNL = Vm_TG_ER_for * hep_TG_DNL; +J_FFA_upt_1 = Vm_FFA_upt * plasma_FFA; +J_FFA_upt_2 = Vm_FFA_upt * plasma_FFA * plasma_volume; +J_FFA_prod = Vm_FFA_prod; +J_VLDL_TG_1 = Vm_VLDL_TG * hep_TG_ER; +J_VLDL_TG_DNL_1 = Vm_VLDL_TG * hep_TG_ER_DNL; +J_VLDL_CE_1 = Vm_VLDL_CE * hep_CE_ER; +J_VLDL_TG_2 = Vm_VLDL_TG * hep_TG_ER / plasma_volume; +J_VLDL_TG_DNL_2 = Vm_VLDL_TG * hep_TG_ER_DNL / plasma_volume; +J_VLDL_CE_2 = Vm_VLDL_CE * hep_CE_ER / plasma_volume; +J_TG_upt_1 = Vm_TG_CE_upt * plasma_TG; +J_CE_upt_1 = Vm_TG_CE_upt * plasma_C; +J_TG_upt_ph = Vm_TG_CE_upt_ph * plasma_TG; +J_CE_upt_ph = Vm_TG_CE_upt_ph * plasma_C; +J_CE_HDL_for = Vm_HDL_CE_for; +J_CE_HDL_upt_1 = Vm_HDL_CE_upt * plasma_C_HDL; +J_TG_hyd_1 = Vm_TG_hyd * plasma_TG; +J_TG_hyd_ph = Vm_TG_hyd_ph * plasma_TG; +J_TG_upt_2 = Vm_TG_CE_upt * plasma_TG * plasma_volume; +J_CE_upt_2 = Vm_TG_CE_upt * plasma_C * plasma_volume; +J_CE_HDL_upt_2 = Vm_HDL_CE_upt * plasma_C_HDL * plasma_volume; +J_TG_hyd_2 = Vm_TG_hyd * plasma_TG * plasma_volume; +J_VLDL_TG = Vm_VLDL_TG * (hep_TG_ER + hep_TG_ER_DNL); +J_VLDL_CE = Vm_VLDL_CE * hep_CE_ER; +J_ApoB_prod = Vm_ApoB_prod; +ApoB_count = J_ApoB_prod * navg * 10^23 * 10^-6; +TG_count = J_VLDL_TG * navg * 10^23 * 10^-6 / ApoB_count; +CE_count = J_VLDL_CE * navg * 10^23 * 10^-6 / ApoB_count; +DNL = (hep_TG_DNL + hep_TG_ER_DNL) / (hep_TG + hep_TG_ER + hep_TG_DNL + hep_TG_ER_DNL); +lipo_vc = ( (TG_count * mvTG) + (CE_count * mvCE) ) * (pow(10,21) / (navg * 10^23)); +lipo_rc = pow((3 * lipo_vc) / (4 * npi), 1/3); +VLDL_diameter = (lipo_vc + lipo_rc) * 2; +VLDL_clearance = (Vm_TG_CE_upt + Vm_TG_CE_upt_ph) / (Vm_TG_CE_upt_0 + Vm_TG_CE_upt_ph_0); +J_CE_HDL_upt = Vm_HDL_CE_upt * plasma_C_HDL; +dhep_TG_abs = hep_TG + hep_TG_ER + hep_TG_DNL + hep_TG_ER_DNL; +dhep_CE_abs = hep_CE + hep_CE_ER; +dhep_FC_abs = hep_FC; +dplasma_C = plasma_C + plasma_C_HDL; +dplasma_TG = plasma_TG; +dVLDL_TG_C_ratio = TG_count / CE_count; +dVLDL_diameter = VLDL_diameter; +dVLDL_production = J_VLDL_TG; +dVLDL_clearance = VLDL_clearance; +dDNL = DNL; +dFFA = plasma_FFA; +dplasma_C_HDL = plasma_C_HDL; +dhep_HDL_CE_upt = J_CE_HDL_upt * plasma_volume; + +dxdt(1) = J_FC_production - J_FC_metabolism - J_CE_formation + J_CE_deformation - J_CE_ER_formation + J_CE_ER_deformation; +dxdt(2) = J_CE_formation - J_CE_deformation + J_CE_upt_2 + J_CE_HDL_upt_2; +dxdt(3) = J_CE_ER_formation - J_CE_ER_deformation - J_VLDL_CE_1; +dxdt(4) = - J_TG_metabolism + J_TG_formation - J_TG_ER_formation + (J_FFA_upt_2/3.0) + J_TG_upt_2 + J_TG_hyd_2; +dxdt(5) = - J_TG_formation + J_TG_ER_formation - J_VLDL_TG_1; +dxdt(6) = J_TG_production - J_TG_metabolism_DNL + J_TG_formation_DNL - J_TG_ER_formation_DNL; +dxdt(7) = J_TG_ER_production - J_TG_formation_DNL + J_TG_ER_formation_DNL - J_VLDL_TG_DNL_1; +dxdt(8) = J_VLDL_TG_2 + J_VLDL_TG_DNL_2 - J_TG_upt_1 - J_TG_upt_ph - J_TG_hyd_1 - J_TG_hyd_ph; +dxdt(9) = J_VLDL_CE_2 - J_CE_upt_1 - J_CE_upt_ph; +dxdt(10) = J_CE_HDL_for - J_CE_HDL_upt_1; +dxdt(11) = J_FFA_prod - J_FFA_upt_1; + +dxdt = dxdt(:); \ No newline at end of file diff --git a/temp/C_tiemannModel_ODEC.mexw64 b/temp/C_tiemannModel_ODEC.mexw64 new file mode 100644 index 0000000000000000000000000000000000000000..3daa2a792e29e4bff4ea122aa80623b93737d393 GIT binary patch literal 103424 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

*VG7uH)T^A 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

Hnd+k; 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 nv%f>CJRI+>gDxt-;3*y61k$RX(!C2g&lGuylJ= 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ⅈeuC8)L>B*= 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

y0{n=tBhMxifGpn?c_ftp@#MVWwKD|h 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

m$cDcC> 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�hn4G(=A2L-Pjk2^XeMZr%= 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

|;LUe%e5CCEl$?UR&tJ{m}iUXcx_Xa&~aN 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 (Yo4r?#F|VXcIpK+zP$sS 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

igUYA2M5&0rqFqs-+FIt*ykF+C4GVn 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 Q}j86Y|UHM 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

3DsTc>7ZbPLhBGw^m&mk?dtn56!8 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 OFu%^B);|EByfGa86s=eQ literal 0 HcmV?d00001 diff --git a/AMF/models/dietModel/runDiet.m b/AMF/models/dietModel/runDiet.m new file mode 100644 index 0000000..50245b0 --- /dev/null +++ b/AMF/models/dietModel/runDiet.m @@ -0,0 +1,37 @@ +%% initialize + +import AMF.* + +model = Model('Model_Diets_YP'); +data = DataSet('dietData'); + +loadGroup(data, 'diets'); +initiateExperiment(model, data); + +%% config + +model.options.useMex = 1; +model.options.savePrefix = ''; +model.options.odeTol = [1e-12 1e-12 100]; +model.options.numIter = 10; +model.options.numTimeSteps = 50; +model.options.parScale = [2 -2]; +model.options.seed = 1; +model.options.SSTime = 1000; +model.options.lab1 = .1; + +parseAll(model); +compileAll(model); + +%% run + +result = runADAPT(model); + + +%% plot + +% plotAll(result, 'parameters', 'traj'); +plotAll(result, 'states', 'mad'); +plotAll(result, 'reactions', 'mad'); + +% random change \ No newline at end of file diff --git a/AMF/models/dietModel/temp/C_Model_Diets_YP_ODE.m b/AMF/models/dietModel/temp/C_Model_Diets_YP_ODE.m new file mode 100644 index 0000000..1cabf2f --- /dev/null +++ b/AMF/models/dietModel/temp/C_Model_Diets_YP_ODE.m @@ -0,0 +1,102 @@ +function dxdt = C_Model_Diets_YP_ODE(t,x,p,u,m) + + + +hep_AcoA = x(m.s.hep_AcoA); +hep_TG = x(m.s.hep_TG); +hep_C = x(m.s.hep_C); +hep_BA = x(m.s.hep_BA); +pl_FFA = x(m.s.pl_FFA); +pl_VLDL_TG = x(m.s.pl_VLDL_TG); +pl_VLDL_C = x(m.s.pl_VLDL_C); +pl_HDL_C = x(m.s.pl_HDL_C); +per_AcoA = x(m.s.per_AcoA); +per_TG = x(m.s.per_TG); +per_C = x(m.s.per_C); +pl_HDL_TG = x(m.s.pl_HDL_TG); + +k1 = p(m.p.k1); +k2 = p(m.p.k2); +k3 = p(m.p.k3); +k4 = p(m.p.k4); +k5 = p(m.p.k5); +k6 = p(m.p.k6); +k7 = p(m.p.k7); +k8 = p(m.p.k8); +k9 = p(m.p.k9); +k10 = p(m.p.k10); +k11 = p(m.p.k11); +k12 = p(m.p.k12); +k13 = p(m.p.k13); +k14 = p(m.p.k14); +k15 = p(m.p.k15); +k16 = p(m.p.k16); +k17 = p(m.p.k17); +k18 = p(m.p.k18); +k19 = p(m.p.k19); +k20 = p(m.p.k20); +k21 = p(m.p.k21); +k22 = p(m.p.k22); +k23 = p(m.p.k23); +k24 = p(m.p.k24); +k25 = p(m.p.k25); +k26 = p(m.p.k26); +k27 = p(m.p.k27); +k28 = p(m.p.k28); +k29 = p(m.p.k29); +k30 = p(m.p.k30); +k31 = p(m.p.k31); +k32 = p(m.p.k32); + +v1 = k1; +v2 = k2; +v3 = k3; +v4 = k4; +v5 = k5 * hep_AcoA; +v6 = k6 * hep_AcoA; +v7 = k7 * hep_TG; +v8 = k8 * hep_C; +v9 = k9 * hep_BA; +v10 = k10 * hep_BA; +v11 = k11 * hep_C; +v12 = k12 * hep_TG; +v13 = k13 * hep_C; +v14 = k14 * pl_FFA; +v15 = k15 * pl_VLDL_C; +v16 = k16 * pl_HDL_C; +v17 = k17 * pl_HDL_TG; +v18 = k18 * (pl_HDL_C / (pl_HDL_TG + pl_HDL_C) - pl_VLDL_C / (pl_VLDL_C + pl_VLDL_TG)); +v19 = k19 * per_TG; +v20 = k20 * pl_VLDL_TG; +v21 = k21 * pl_VLDL_C; +v22 = k22 * pl_VLDL_C; +v23 = k23; +v24 = k24; +v25 = k25; +v26 = k26; +v27 = k27 * per_AcoA; +v28 = k28 * per_AcoA; +v29 = k29 * per_TG; +v30 = k30 * per_C; +v31 = k31 * (pl_VLDL_TG / (pl_VLDL_TG + pl_VLDL_C) - pl_HDL_TG / (pl_HDL_TG + pl_HDL_C)); +v32 = k32; +pl_TC = pl_VLDL_C + pl_HDL_C; +fat_intk = v1 + v2 + v23 + v24; +gluc_intk = v3 + v4 + v25 + v26; +fat_ox = v1 + v24 + v7 + v29; +gluc_ox = v3 + v25; + +dxdt(1) = 3*v4 - v5 - v6; +dxdt(2) = v2 + v5/26 + v14/3 - v7 - v12 + v17; +dxdt(3) = v6/13 + v15 + v16 - v8 - v11 - v13 + v32; +dxdt(4) = v8 - v9; +dxdt(5) = 3*v19 - v14; +dxdt(6) = v12 - v20 - v31; +dxdt(7) = v13 - v15 - v21 - v22 + v18; +dxdt(8) = v30 - v16 - v18; +dxdt(9) = 3*v26 - v27 - v28; +dxdt(10) = v20 + v23 + v27/26 - v19 - v29; +dxdt(11) = v21 + v28/13 - v30; +dxdt(12) = v31 - v17; + +dxdt = dxdt(:); \ No newline at end of file diff --git a/AMF/models/dietModel/temp/C_Model_Diets_YP_ODEC.mexw64 b/AMF/models/dietModel/temp/C_Model_Diets_YP_ODEC.mexw64 new file mode 100644 index 0000000000000000000000000000000000000000..a613c8c074a75c9280414be2be910c3bb9714018 GIT binary patch literal 103424 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 z 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 WbKmA)%=LjsNAj!X Date: Wed, 21 Jan 2015 12:15:05 +0100 Subject: [PATCH 6/6] uh --- README.md | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 707bd3d..1ed55a8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,22 @@ -ADAPT -===== +** Read the manual (manual.pdf) for a complete overview of how to install and use the AMF package. -ADAPT toolbox for Matlab - Analysis of Dynamic Adaptations in Parameter Trajectories +Install the ADAPT Modeling Framework (AMF) by running + +setup + +in the AMF root directory. This will add all subdirectories to the MATLAB path and will attempt to start a parralel pool. +To run the examples, please make sure the ODEMEX toolbox is configured properly (Instructions.pdf located in the odemex folder). + +The following example run files are included: + +runToy + +-> runs ADAPT on the toy model (Natal van Riel et al) to compute parameter trajectories + +runMinGluc + +-> fits the minimal glucose model (Dalla man et al) to post-bariatric surgery insulin data + +runMinCPep + +-> fits the minimal c-peptide model (Dalla man et al) to post-bariatric surgery glucose data \ No newline at end of file

}FVq9`5Xg_Fq^BOWu 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�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 O6!6q?>F@tx3;Yw7DBhz0 literal 0 HcmV?d00001 diff --git a/temp/C_tiemannModel_ODEMEX.m b/temp/C_tiemannModel_ODEMEX.m new file mode 100644 index 0000000..e2ac3f1 --- /dev/null +++ b/temp/C_tiemannModel_ODEMEX.m @@ -0,0 +1,129 @@ +function dxdt = C_tiemannModel_ODEMEX(t,x,p,u,m) + + +mwTG = m.c.mwTG; +mvTG = m.c.mvTG; +mwCE = m.c.mwCE; +mvCE = m.c.mvCE; +mwFC = m.c.mwFC; +mvFC = m.c.mvFC; +mwPL = m.c.mwPL; +mvPL = m.c.mvPL; +mwApoB = m.c.mwApoB; +navg = m.c.navg; +uH = m.c.uH; +plasma_volume = m.c.plasma_volume; +rs = m.c.rs; +npi = m.c.npi; + +hep_FC = x(m.s.hep_FC); +hep_CE = x(m.s.hep_CE); +hep_CE_ER = x(m.s.hep_CE_ER); +hep_TG = x(m.s.hep_TG); +hep_TG_ER = x(m.s.hep_TG_ER); +hep_TG_DNL = x(m.s.hep_TG_DNL); +hep_TG_ER_DNL = x(m.s.hep_TG_ER_DNL); +plasma_TG = x(m.s.plasma_TG); +plasma_C = x(m.s.plasma_C); +plasma_C_HDL = x(m.s.plasma_C_HDL); +plasma_FFA = x(m.s.plasma_FFA); + +Vm_FC_prod = p(m.p.Vm_FC_prod); +Vm_FC_met = p(m.p.Vm_FC_met); +Vm_CE_for = p(m.p.Vm_CE_for); +Vm_CE_def = p(m.p.Vm_CE_def); +Vm_CE_ER_for = p(m.p.Vm_CE_ER_for); +Vm_CE_ER_def = p(m.p.Vm_CE_ER_def); +Vm_TG_prod = p(m.p.Vm_TG_prod); +Vm_TG_met = p(m.p.Vm_TG_met); +Vm_TG_for = p(m.p.Vm_TG_for); +Vm_TG_ER_prod = p(m.p.Vm_TG_ER_prod); +Vm_TG_ER_for = p(m.p.Vm_TG_ER_for); +Vm_FFA_upt = p(m.p.Vm_FFA_upt); +Vm_FFA_prod = p(m.p.Vm_FFA_prod); +Vm_VLDL_TG = p(m.p.Vm_VLDL_TG); +Vm_VLDL_CE = p(m.p.Vm_VLDL_CE); +Vm_TG_CE_upt = p(m.p.Vm_TG_CE_upt); +Vm_TG_CE_upt_ph = p(m.p.Vm_TG_CE_upt_ph); +Vm_TG_hyd = p(m.p.Vm_TG_hyd); +Vm_TG_hyd_ph = p(m.p.Vm_TG_hyd_ph); +Vm_HDL_CE_for = p(m.p.Vm_HDL_CE_for); +Vm_HDL_CE_upt = p(m.p.Vm_HDL_CE_upt); +Vm_ApoB_prod = p(m.p.Vm_ApoB_prod); +Vm_TG_CE_upt_0 = p(m.p.Vm_TG_CE_upt_0); +Vm_TG_CE_upt_ph_0 = p(m.p.Vm_TG_CE_upt_ph_0); + +J_FC_production = Vm_FC_prod; +J_FC_metabolism = Vm_FC_met * hep_FC; +J_CE_formation = Vm_CE_for * hep_FC; +J_CE_deformation = Vm_CE_def * hep_CE; +J_CE_ER_formation = Vm_CE_ER_for * hep_FC; +J_CE_ER_deformation = Vm_CE_ER_def * hep_CE_ER; +J_TG_production = Vm_TG_prod; +J_TG_metabolism = Vm_TG_met * hep_TG; +J_TG_metabolism_DNL = Vm_TG_met * hep_TG_DNL; +J_TG_formation = Vm_TG_for * hep_TG_ER; +J_TG_formation_DNL = Vm_TG_for * hep_TG_ER_DNL; +J_TG_ER_production = Vm_TG_ER_prod; +J_TG_ER_formation = Vm_TG_ER_for * hep_TG; +J_TG_ER_formation_DNL = Vm_TG_ER_for * hep_TG_DNL; +J_FFA_upt_1 = Vm_FFA_upt * plasma_FFA; +J_FFA_upt_2 = Vm_FFA_upt * plasma_FFA * plasma_volume; +J_FFA_prod = Vm_FFA_prod; +J_VLDL_TG_1 = Vm_VLDL_TG * hep_TG_ER; +J_VLDL_TG_DNL_1 = Vm_VLDL_TG * hep_TG_ER_DNL; +J_VLDL_CE_1 = Vm_VLDL_CE * hep_CE_ER; +J_VLDL_TG_2 = Vm_VLDL_TG * hep_TG_ER / plasma_volume; +J_VLDL_TG_DNL_2 = Vm_VLDL_TG * hep_TG_ER_DNL / plasma_volume; +J_VLDL_CE_2 = Vm_VLDL_CE * hep_CE_ER / plasma_volume; +J_TG_upt_1 = Vm_TG_CE_upt * plasma_TG; +J_CE_upt_1 = Vm_TG_CE_upt * plasma_C; +J_TG_upt_ph = Vm_TG_CE_upt_ph * plasma_TG; +J_CE_upt_ph = Vm_TG_CE_upt_ph * plasma_C; +J_CE_HDL_for = Vm_HDL_CE_for; +J_CE_HDL_upt_1 = Vm_HDL_CE_upt * plasma_C_HDL; +J_TG_hyd_1 = Vm_TG_hyd * plasma_TG; +J_TG_hyd_ph = Vm_TG_hyd_ph * plasma_TG; +J_TG_upt_2 = Vm_TG_CE_upt * plasma_TG * plasma_volume; +J_CE_upt_2 = Vm_TG_CE_upt * plasma_C * plasma_volume; +J_CE_HDL_upt_2 = Vm_HDL_CE_upt * plasma_C_HDL * plasma_volume; +J_TG_hyd_2 = Vm_TG_hyd * plasma_TG * plasma_volume; +J_VLDL_TG = Vm_VLDL_TG * (hep_TG_ER + hep_TG_ER_DNL); +J_VLDL_CE = Vm_VLDL_CE * hep_CE_ER; +J_ApoB_prod = Vm_ApoB_prod; +ApoB_count = J_ApoB_prod * navg * pow(10,23) * pow(10,-6); +TG_count = J_VLDL_TG * navg * pow(10,23) * pow(10,-6) / ApoB_count; +CE_count = J_VLDL_CE * navg * pow(10,23) * pow(10,-6) / ApoB_count; +DNL = (hep_TG_DNL + hep_TG_ER_DNL) / (hep_TG + hep_TG_ER + hep_TG_DNL + hep_TG_ER_DNL); +lipo_vc = ( (TG_count * mvTG) + (CE_count * mvCE) ) * (pow(10,21) / (navg * pow(10,23))); +lipo_rc = pow((3 * lipo_vc) / (4 * npi), 1/3); +VLDL_diameter = (lipo_vc + lipo_rc) * 2; +VLDL_clearance = (Vm_TG_CE_upt + Vm_TG_CE_upt_ph) / (Vm_TG_CE_upt_0 + Vm_TG_CE_upt_ph_0); +J_CE_HDL_upt = Vm_HDL_CE_upt * plasma_C_HDL; +dhep_TG_abs = hep_TG + hep_TG_ER + hep_TG_DNL + hep_TG_ER_DNL; +dhep_CE_abs = hep_CE + hep_CE_ER; +dhep_FC_abs = hep_FC; +dplasma_C = plasma_C + plasma_C_HDL; +dplasma_TG = plasma_TG; +dVLDL_TG_C_ratio = TG_count / CE_count; +dVLDL_diameter = VLDL_diameter; +dVLDL_production = J_VLDL_TG; +dVLDL_clearance = VLDL_clearance; +dDNL = DNL; +dFFA = plasma_FFA; +dplasma_C_HDL = plasma_C_HDL; +dhep_HDL_CE_upt = J_CE_HDL_upt * plasma_volume; + +dxdt(1) = J_FC_production - J_FC_metabolism - J_CE_formation + J_CE_deformation - J_CE_ER_formation + J_CE_ER_deformation; +dxdt(2) = J_CE_formation - J_CE_deformation + J_CE_upt_2 + J_CE_HDL_upt_2; +dxdt(3) = J_CE_ER_formation - J_CE_ER_deformation - J_VLDL_CE_1; +dxdt(4) = - J_TG_metabolism + J_TG_formation - J_TG_ER_formation + (J_FFA_upt_2/3.0) + J_TG_upt_2 + J_TG_hyd_2; +dxdt(5) = - J_TG_formation + J_TG_ER_formation - J_VLDL_TG_1; +dxdt(6) = J_TG_production - J_TG_metabolism_DNL + J_TG_formation_DNL - J_TG_ER_formation_DNL; +dxdt(7) = J_TG_ER_production - J_TG_formation_DNL + J_TG_ER_formation_DNL - J_VLDL_TG_DNL_1; +dxdt(8) = J_VLDL_TG_2 + J_VLDL_TG_DNL_2 - J_TG_upt_1 - J_TG_upt_ph - J_TG_hyd_1 - J_TG_hyd_ph; +dxdt(9) = J_VLDL_CE_2 - J_CE_upt_1 - J_CE_upt_ph; +dxdt(10) = J_CE_HDL_for - J_CE_HDL_upt_1; +dxdt(11) = J_FFA_prod - J_FFA_upt_1; + +dxdt = dxdt(:); \ No newline at end of file diff --git a/temp/C_tiemannModel_REACTIONS.m b/temp/C_tiemannModel_REACTIONS.m new file mode 100644 index 0000000..58b73b1 --- /dev/null +++ b/temp/C_tiemannModel_REACTIONS.m @@ -0,0 +1,176 @@ +function v = C_tiemannModel_REACTIONS(t,x,p,u,m) + + +mwTG = m.c.mwTG; +mvTG = m.c.mvTG; +mwCE = m.c.mwCE; +mvCE = m.c.mvCE; +mwFC = m.c.mwFC; +mvFC = m.c.mvFC; +mwPL = m.c.mwPL; +mvPL = m.c.mvPL; +mwApoB = m.c.mwApoB; +navg = m.c.navg; +uH = m.c.uH; +plasma_volume = m.c.plasma_volume; +rs = m.c.rs; +npi = m.c.npi; + +hep_FC = x(m.s.hep_FC); +hep_CE = x(m.s.hep_CE); +hep_CE_ER = x(m.s.hep_CE_ER); +hep_TG = x(m.s.hep_TG); +hep_TG_ER = x(m.s.hep_TG_ER); +hep_TG_DNL = x(m.s.hep_TG_DNL); +hep_TG_ER_DNL = x(m.s.hep_TG_ER_DNL); +plasma_TG = x(m.s.plasma_TG); +plasma_C = x(m.s.plasma_C); +plasma_C_HDL = x(m.s.plasma_C_HDL); +plasma_FFA = x(m.s.plasma_FFA); + +Vm_FC_prod = p(m.p.Vm_FC_prod); +Vm_FC_met = p(m.p.Vm_FC_met); +Vm_CE_for = p(m.p.Vm_CE_for); +Vm_CE_def = p(m.p.Vm_CE_def); +Vm_CE_ER_for = p(m.p.Vm_CE_ER_for); +Vm_CE_ER_def = p(m.p.Vm_CE_ER_def); +Vm_TG_prod = p(m.p.Vm_TG_prod); +Vm_TG_met = p(m.p.Vm_TG_met); +Vm_TG_for = p(m.p.Vm_TG_for); +Vm_TG_ER_prod = p(m.p.Vm_TG_ER_prod); +Vm_TG_ER_for = p(m.p.Vm_TG_ER_for); +Vm_FFA_upt = p(m.p.Vm_FFA_upt); +Vm_FFA_prod = p(m.p.Vm_FFA_prod); +Vm_VLDL_TG = p(m.p.Vm_VLDL_TG); +Vm_VLDL_CE = p(m.p.Vm_VLDL_CE); +Vm_TG_CE_upt = p(m.p.Vm_TG_CE_upt); +Vm_TG_CE_upt_ph = p(m.p.Vm_TG_CE_upt_ph); +Vm_TG_hyd = p(m.p.Vm_TG_hyd); +Vm_TG_hyd_ph = p(m.p.Vm_TG_hyd_ph); +Vm_HDL_CE_for = p(m.p.Vm_HDL_CE_for); +Vm_HDL_CE_upt = p(m.p.Vm_HDL_CE_upt); +Vm_ApoB_prod = p(m.p.Vm_ApoB_prod); +Vm_TG_CE_upt_0 = p(m.p.Vm_TG_CE_upt_0); +Vm_TG_CE_upt_ph_0 = p(m.p.Vm_TG_CE_upt_ph_0); + +J_FC_production = Vm_FC_prod; +J_FC_metabolism = Vm_FC_met * hep_FC; +J_CE_formation = Vm_CE_for * hep_FC; +J_CE_deformation = Vm_CE_def * hep_CE; +J_CE_ER_formation = Vm_CE_ER_for * hep_FC; +J_CE_ER_deformation = Vm_CE_ER_def * hep_CE_ER; +J_TG_production = Vm_TG_prod; +J_TG_metabolism = Vm_TG_met * hep_TG; +J_TG_metabolism_DNL = Vm_TG_met * hep_TG_DNL; +J_TG_formation = Vm_TG_for * hep_TG_ER; +J_TG_formation_DNL = Vm_TG_for * hep_TG_ER_DNL; +J_TG_ER_production = Vm_TG_ER_prod; +J_TG_ER_formation = Vm_TG_ER_for * hep_TG; +J_TG_ER_formation_DNL = Vm_TG_ER_for * hep_TG_DNL; +J_FFA_upt_1 = Vm_FFA_upt * plasma_FFA; +J_FFA_upt_2 = Vm_FFA_upt * plasma_FFA * plasma_volume; +J_FFA_prod = Vm_FFA_prod; +J_VLDL_TG_1 = Vm_VLDL_TG * hep_TG_ER; +J_VLDL_TG_DNL_1 = Vm_VLDL_TG * hep_TG_ER_DNL; +J_VLDL_CE_1 = Vm_VLDL_CE * hep_CE_ER; +J_VLDL_TG_2 = Vm_VLDL_TG * hep_TG_ER / plasma_volume; +J_VLDL_TG_DNL_2 = Vm_VLDL_TG * hep_TG_ER_DNL / plasma_volume; +J_VLDL_CE_2 = Vm_VLDL_CE * hep_CE_ER / plasma_volume; +J_TG_upt_1 = Vm_TG_CE_upt * plasma_TG; +J_CE_upt_1 = Vm_TG_CE_upt * plasma_C; +J_TG_upt_ph = Vm_TG_CE_upt_ph * plasma_TG; +J_CE_upt_ph = Vm_TG_CE_upt_ph * plasma_C; +J_CE_HDL_for = Vm_HDL_CE_for; +J_CE_HDL_upt_1 = Vm_HDL_CE_upt * plasma_C_HDL; +J_TG_hyd_1 = Vm_TG_hyd * plasma_TG; +J_TG_hyd_ph = Vm_TG_hyd_ph * plasma_TG; +J_TG_upt_2 = Vm_TG_CE_upt * plasma_TG * plasma_volume; +J_CE_upt_2 = Vm_TG_CE_upt * plasma_C * plasma_volume; +J_CE_HDL_upt_2 = Vm_HDL_CE_upt * plasma_C_HDL * plasma_volume; +J_TG_hyd_2 = Vm_TG_hyd * plasma_TG * plasma_volume; +J_VLDL_TG = Vm_VLDL_TG * (hep_TG_ER + hep_TG_ER_DNL); +J_VLDL_CE = Vm_VLDL_CE * hep_CE_ER; +J_ApoB_prod = Vm_ApoB_prod; +ApoB_count = J_ApoB_prod * navg * pow(10,23) * pow(10,-6); +TG_count = J_VLDL_TG * navg * pow(10,23) * pow(10,-6) / ApoB_count; +CE_count = J_VLDL_CE * navg * pow(10,23) * pow(10,-6) / ApoB_count; +DNL = (hep_TG_DNL + hep_TG_ER_DNL) / (hep_TG + hep_TG_ER + hep_TG_DNL + hep_TG_ER_DNL); +lipo_vc = ( (TG_count * mvTG) + (CE_count * mvCE) ) * (pow(10,21) / (navg * pow(10,23))); +lipo_rc = pow((3 * lipo_vc) / (4 * npi), 1/3); +VLDL_diameter = (lipo_vc + lipo_rc) * 2; +VLDL_clearance = (Vm_TG_CE_upt + Vm_TG_CE_upt_ph) / (Vm_TG_CE_upt_0 + Vm_TG_CE_upt_ph_0); +J_CE_HDL_upt = Vm_HDL_CE_upt * plasma_C_HDL; +dhep_TG_abs = hep_TG + hep_TG_ER + hep_TG_DNL + hep_TG_ER_DNL; +dhep_CE_abs = hep_CE + hep_CE_ER; +dhep_FC_abs = hep_FC; +dplasma_C = plasma_C + plasma_C_HDL; +dplasma_TG = plasma_TG; +dVLDL_TG_C_ratio = TG_count / CE_count; +dVLDL_diameter = VLDL_diameter; +dVLDL_production = J_VLDL_TG; +dVLDL_clearance = VLDL_clearance; +dDNL = DNL; +dFFA = plasma_FFA; +dplasma_C_HDL = plasma_C_HDL; +dhep_HDL_CE_upt = J_CE_HDL_upt * plasma_volume; + +v(1) = J_FC_production; +v(2) = J_FC_metabolism; +v(3) = J_CE_formation; +v(4) = J_CE_deformation; +v(5) = J_CE_ER_formation; +v(6) = J_CE_ER_deformation; +v(7) = J_TG_production; +v(8) = J_TG_metabolism; +v(9) = J_TG_metabolism_DNL; +v(10) = J_TG_formation; +v(11) = J_TG_formation_DNL; +v(12) = J_TG_ER_production; +v(13) = J_TG_ER_formation; +v(14) = J_TG_ER_formation_DNL; +v(15) = J_FFA_upt_1; +v(16) = J_FFA_upt_2; +v(17) = J_FFA_prod; +v(18) = J_VLDL_TG_1; +v(19) = J_VLDL_TG_DNL_1; +v(20) = J_VLDL_CE_1; +v(21) = J_VLDL_TG_2; +v(22) = J_VLDL_TG_DNL_2; +v(23) = J_VLDL_CE_2; +v(24) = J_TG_upt_1; +v(25) = J_CE_upt_1; +v(26) = J_TG_upt_ph; +v(27) = J_CE_upt_ph; +v(28) = J_CE_HDL_for; +v(29) = J_CE_HDL_upt_1; +v(30) = J_TG_hyd_1; +v(31) = J_TG_hyd_ph; +v(32) = J_TG_upt_2; +v(33) = J_CE_upt_2; +v(34) = J_CE_HDL_upt_2; +v(35) = J_TG_hyd_2; +v(36) = J_VLDL_TG; +v(37) = J_VLDL_CE; +v(38) = J_ApoB_prod; +v(39) = ApoB_count; +v(40) = TG_count; +v(41) = CE_count; +v(42) = DNL; +v(43) = lipo_vc; +v(44) = lipo_rc; +v(45) = VLDL_diameter; +v(46) = VLDL_clearance; +v(47) = J_CE_HDL_upt; +v(48) = dhep_TG_abs; +v(49) = dhep_CE_abs; +v(50) = dhep_FC_abs; +v(51) = dplasma_C; +v(52) = dplasma_TG; +v(53) = dVLDL_TG_C_ratio; +v(54) = dVLDL_diameter; +v(55) = dVLDL_production; +v(56) = dVLDL_clearance; +v(57) = dDNL; +v(58) = dFFA; +v(59) = dplasma_C_HDL; +v(60) = dhep_HDL_CE_upt; From 0e27cb9abecae2148fcd7b04e69d53f842d617d5 Mon Sep 17 00:00:00 2001 From: Yared888 Date: Wed, 21 Jan 2015 12:09:25 +0100 Subject: [PATCH 5/6] one more model --- AMF/models/dietModel/Hall/BW.emf | Bin 0 -> 11296 bytes AMF/models/dietModel/Hall/Hall.emf | Bin 0 -> 17552 bytes AMF/models/dietModel/Hall/Hall.m | 9 ++ AMF/models/dietModel/Hall/Hall1.emf | Bin 0 -> 17632 bytes AMF/models/dietModel/Hall/bw_fit.m | 21 +++ AMF/models/dietModel/Hall/hall_plot.m | 11 ++ AMF/models/dietModel/Model_Diets_YP.m | 108 +++++++++++++ AMF/models/dietModel/dietData.m | 30 ++++ AMF/models/dietModel/dietData.mat | Bin 0 -> 1705 bytes AMF/models/dietModel/loadData.m | 153 ++++++++++++++++++ .../results/_Model_Diets_YP_diets__10_50.mat | Bin 0 -> 1147793 bytes AMF/models/dietModel/runDiet.m | 37 +++++ .../dietModel/temp/C_Model_Diets_YP_ODE.m | 102 ++++++++++++ .../temp/C_Model_Diets_YP_ODEC.mexw64 | Bin 0 -> 103424 bytes .../dietModel/temp/C_Model_Diets_YP_ODEMEX.m | 102 ++++++++++++ .../temp/C_Model_Diets_YP_REACTIONS.m | 125 ++++++++++++++ 16 files changed, 698 insertions(+) create mode 100644 AMF/models/dietModel/Hall/BW.emf create mode 100644 AMF/models/dietModel/Hall/Hall.emf create mode 100644 AMF/models/dietModel/Hall/Hall.m create mode 100644 AMF/models/dietModel/Hall/Hall1.emf create mode 100644 AMF/models/dietModel/Hall/bw_fit.m create mode 100644 AMF/models/dietModel/Hall/hall_plot.m create mode 100644 AMF/models/dietModel/Model_Diets_YP.m create mode 100644 AMF/models/dietModel/dietData.m create mode 100644 AMF/models/dietModel/dietData.mat create mode 100644 AMF/models/dietModel/loadData.m create mode 100644 AMF/models/dietModel/results/_Model_Diets_YP_diets__10_50.mat create mode 100644 AMF/models/dietModel/runDiet.m create mode 100644 AMF/models/dietModel/temp/C_Model_Diets_YP_ODE.m create mode 100644 AMF/models/dietModel/temp/C_Model_Diets_YP_ODEC.mexw64 create mode 100644 AMF/models/dietModel/temp/C_Model_Diets_YP_ODEMEX.m create mode 100644 AMF/models/dietModel/temp/C_Model_Diets_YP_REACTIONS.m diff --git a/AMF/models/dietModel/Hall/BW.emf b/AMF/models/dietModel/Hall/BW.emf new file mode 100644 index 0000000000000000000000000000000000000000..5e27a8c04385862103eec7f35836b19c658666b2 GIT binary patch literal 11296 zcmeI2dyE#<8OGlOZUuDZT8q)fPofko#$AdCRB&0j3Z!U3pkfQMl#4)7U^s48Wcv&pGe8}v0ac&?R4&M-hqlj~2_8IOOTj1_tG)G{9#yxswGo42bTvDC z*rI=j>8q}ex+c&J4gw0T6&wL4u+v7zpa5z>9heOkfwiCrnm{u+2o8f*a0HwH^xd!R z1oR`&TcIC@eh_*y^d{&<=xd=bf<7C19rPOL1?c@mH|Pf4pc{09ZqN<7K{x0I-JlzE zgKp3bxT2<;_em68m)7dc(D)V`$ z#)V-gQaPvU!qdt=A_Fxuqoo8ilTm{f!8JN`gmo_$LTRe9phCx9^78s2aR_$P`|Ey zU($nOd6GSxoAkxYyE+!Wi4NV++AAAmb848IH{%AmD5sZ@Jh5Cf}uQGiXYd~^K{>3EicAqcWEhG z((*Ep)Y9vy%G~3l?WO*eXt@$Yd9)NiuBGSmXt@lV-KC{$Nz2tBsioIZm8qqk#g%CJ zIEM0QDSli_&*#zd05-cr%lSAVThj6;AgQI->HLxP?5XAHBP}b@)6XydoPpDEzQROD zI_+65eq2w_!|n1u{}(p9OHbL7o&nL4dU{=XJx89Q=l|oJ#4EOFt@}C2^LezL0Qs}% zkv89*IVZ{18f;A>zEc_#`#H($RF<_?YwX!$m8?^pVLy(sG{3z(ZJkOx@#9)5Pw4VG z)fnex_|#b~XJAWOE+Cd`aV=G+vMeq2QlU~UYcb}Ub#~87OY!4cDo@CzWdAo{&q+ff+t^R?D-oB`x1iEZ5>%s!nBD zT8^f^(sg;9wt2J^Kdzr%p4&j0?_Qpzr}%L_l_%uV zb2|pS@4R~6g)Qm110?lSU3oo6opJ8W(z5}ZX})`TmY(9r^;DjaOV8yP@V@ivxe!~E zz)FzRQ+4I_9Nj5B>#>>UyO(F_DSli}2%G@kZ)g4a58OvU zz?UE9uu~6T@7S*=-j~D9cKG^jWDl|Kvt1q6zu}LC-$pz!!%n&NmR#$}y!#iQZ|yz( zM)@#(tG(`TTK6+S1L^6gG|Q%h8>~LuWaGmpY;5?XT@{w_m+msVBCN9EVJ&Zq*IOZM zvWvoIyC8glRkO|dhwWA!nyh#DvQ>qzGHYMAQ`Tbtwf%O|zQ;-b5mv+F_PYJZ{$@|w zpZQMaHO{VouwU8l?OA)-p0gM1MXs;d@9dBEYx|QuV}GH=>-IFvr?Bv(y=6bPckBtQ zKSnQ)(%S($FFa%e!hZWe_?BH5n(gB74ZAcvV8ifYMA(bxdl*5JjSD+%0$$dKdu(dh zYBRzY**8U-6YgT)+-bKkqQzmOEe#uNWmv~Mowc?utl_@0%03rXS}`oQE#cF4Z)mWc z;a1xn7TG@3c_1vbZ-$%g+hKt{80MkvT>E~QV^4$|?NFF)Plb=!&rtQ5Fw=e$uD4cx znSLQmwU@&bdo@h9qv1L`7V7QqVWJ%m*V-Flf}ITGnU`zIt}(rTE4NN)5(WQ$E1CCo zQpvl#qmcKpR-BWzr)5j`Cf$1pnZGsuf(A!{_Sa%?AK-t--`8F@h_aa=9{jh)^%TzG z>!sDU)C%?)Tf=o4-_T7WF7OLFv&z5QY@H2{KGu$v4)dtQR`4^R;nxQ&^lFG<5OQ+4#V2h^4rsD pa~>EKO6OpmtrU<^*GLVe-c8?i>g;j^v})MkAZP|npa`VZ{{TdYuSfs@ literal 0 HcmV?d00001 diff --git a/AMF/models/dietModel/Hall/Hall.emf b/AMF/models/dietModel/Hall/Hall.emf new file mode 100644 index 0000000000000000000000000000000000000000..88d01e04b882cac2d34ce6fd7a05a9adaa66d122 GIT binary patch literal 17552 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 Ji6fe;{{m75CZPZT literal 0 HcmV?d00001 diff --git a/AMF/models/dietModel/Hall/bw_fit.m b/AMF/models/dietModel/Hall/bw_fit.m new file mode 100644 index 0000000..7a0d333 --- /dev/null +++ b/AMF/models/dietModel/Hall/bw_fit.m @@ -0,0 +1,21 @@ +% Fit body weight data + +time = diets.t3/(24*7); % weeks HFD +TG = diets.perTG_m*853/1e6; % g TG + +% fit to polynomial +p = polyfit(time, TG, 2); % -0.0649*x^2 + 2.0961*x + 2.5263 + +% plot polynomial and data +x1 = linspace(0, 12, 100); +y1 = polyval(p,x1); + +figure(1);hold on; +plot(time, TG, 'ok', x1, y1, '-k', 'LineWidth', 2); +xlabel('Time on HFD (weeks)'); +ylabel('Body TG (g)'); +saveas(1, 'BW.emf'); + +% slope at t= 3 = 1.7067 g TG/week +% slope at t=10 = 0.7981 g TG/week + diff --git a/AMF/models/dietModel/Hall/hall_plot.m b/AMF/models/dietModel/Hall/hall_plot.m new file mode 100644 index 0000000..e8502a1 --- /dev/null +++ b/AMF/models/dietModel/Hall/hall_plot.m @@ -0,0 +1,11 @@ +% Hall +t = linspace(0,16,100); +t1 = [3 10]; +x1 = [11.3+1.35 12.9+1.35]; +ee3 = Hall(t, 3); +ee2 = Hall(t, 2); +ee4 = Hall(t, 4); +ee909 = Hall(t, 0.909); +plot(t,ee2, '--k', t, ee3, '-k', t, ee4, '--k',t, ee909, '--b', t1, x1, 'or', 'LineWidth', 2); +xlabel('Time on HFD (weeks)') +ylabel('Energy Expenditure (kcal/day)') \ No newline at end of file diff --git a/AMF/models/dietModel/Model_Diets_YP.m b/AMF/models/dietModel/Model_Diets_YP.m new file mode 100644 index 0000000..8954a88 --- /dev/null +++ b/AMF/models/dietModel/Model_Diets_YP.m @@ -0,0 +1,108 @@ +function MODEL = Model_Diets_YP() + +MODEL.DESCRIPTION = 'Model to explore glucose lipid interactions in the diet selection experiment.'; + +MODEL.PREDICTOR = { + 't' [0 24*7*12] {'time' 'hours' 'Time'} +}; + +MODEL.CONSTANTS = { +}; + +MODEL.PARAMETERS = { +% name fit init_value bnd meta-data + 'k1' 1 1 [] {} + 'k2' 1 1 [] {} + 'k3' 1 1 [] {} + 'k4' 1 1 [] {} + 'k5' 1 1 [] {} + 'k6' 1 1 [] {} + 'k7' 1 1 [] {} + 'k8' 1 1 [] {} + 'k9' 1 1 [] {} + 'k10' 1 1 [] {} + 'k11' 1 1 [] {} + 'k12' 1 1 [] {} + 'k13' 1 1 [] {} + 'k14' 1 1 [] {} + 'k15' 1 1 [] {} + 'k16' 1 1 [] {} + 'k17' 1 1 [] {} + 'k18' 1 1 [] {} + 'k19' 1 1 [] {} + 'k20' 1 1 [] {} + 'k21' 1 1 [] {} + 'k22' 1 1 [] {} + 'k23' 1 1 [] {} + 'k24' 1 1 [] {} + 'k25' 1 1 [] {} + 'k26' 1 1 [] {} + 'k27' 1 1 [] {} + 'k28' 1 1 [] {} + 'k29' 1 1 [] {} + 'k30' 1 1 [] {} + 'k31' 1 1 [] {} + 'k32' 1 1 [] {} +}; + +MODEL.STATES = { + 'hep_AcoA' 1 '3*v4 - v5 - v6' {} + 'hep_TG' 2 'v2 + v5/26 + v14/3 - v7 - v12 + v17' {} + 'hep_C' 1 'v6/13 + v15 + v16 - v8 - v11 - v13 + v32' {} + 'hep_BA' 0 'v8 - v9' {} + 'pl_FFA' 1 '3*v19 - v14' {} + 'pl_VLDL_TG' 1 'v12 - v20 - v31' {} + 'pl_VLDL_C' 1 'v13 - v15 - v21 - v22 + v18' {} + 'pl_HDL_C' 1 'v30 - v16 - v18' {} + 'per_AcoA' 1 '3*v26 - v27 - v28' {} + 'per_TG' 1 'v20 + v23 + v27/26 - v19 - v29' {} + 'per_C' 1 'v21 + v28/13 - v30' {} + 'pl_HDL_TG' 1 'v31 - v17' {} +}; + +MODEL.REACTIONS = { + % name reaction meta + 'v1' 'k1' {} + 'v2' 'k2' {} + 'v3' 'k3' {} + 'v4' 'k4' {} + 'v5' 'k5 * hep_AcoA' {} + 'v6' 'k6 * hep_AcoA' {} + 'v7' 'k7 * hep_TG' {} + 'v8' 'k8 * hep_C' {} + 'v9' 'k9 * hep_BA' {} + 'v10' 'k10 * hep_BA' {} + 'v11' 'k11 * hep_C' {} + 'v12' 'k12 * hep_TG' {} + 'v13' 'k13 * hep_C' {} + 'v14' 'k14 * pl_FFA' {} + 'v15' 'k15 * pl_VLDL_C' {} + 'v16' 'k16 * pl_HDL_C' {} + 'v17' 'k17 * pl_HDL_TG' {} + 'v18' 'k18 * (pl_HDL_C / (pl_HDL_TG + pl_HDL_C) - pl_VLDL_C / (pl_VLDL_C + pl_VLDL_TG))' {} % HDL_C -> VLDL_C + 'v19' 'k19 * per_TG' {} + 'v20' 'k20 * pl_VLDL_TG' {} + 'v21' 'k21 * pl_VLDL_C' {} + 'v22' 'k22 * pl_VLDL_C' {} + 'v23' 'k23' {} + 'v24' 'k24' {} + 'v25' 'k25' {} + 'v26' 'k26' {} + 'v27' 'k27 * per_AcoA' {} + 'v28' 'k28 * per_AcoA' {} + 'v29' 'k29 * per_TG' {} + 'v30' 'k30 * per_C' {} + 'v31' 'k31 * (pl_VLDL_TG / (pl_VLDL_TG + pl_VLDL_C) - pl_HDL_TG / (pl_HDL_TG + pl_HDL_C))' {} % VLDL_TG -> HDL_TG + 'v32' 'k32' {} % cholesterol from diet to liver + + % helper functions + 'pl_TC' 'pl_VLDL_C + pl_HDL_C' {} + 'fat_intk' 'v1 + v2 + v23 + v24' {} + 'gluc_intk' 'v3 + v4 + v25 + v26' {} + 'fat_ox' 'v1 + v24 + v7 + v29' {} + 'gluc_ox' 'v3 + v25' {} +% 'chol_exc' 'v42 - v41 + v11' {} + + +}; + diff --git a/AMF/models/dietModel/dietData.m b/AMF/models/dietModel/dietData.m new file mode 100644 index 0000000..96efbfa --- /dev/null +++ b/AMF/models/dietModel/dietData.m @@ -0,0 +1,30 @@ +function DATASET = dietData() + +DATASET.DESCRIPTION = 'Diet data.'; + +DATASET.FILE = 'dietData'; + +DATASET.GROUPS = { + 'diets' +% 'diets_R' +% 'diets_NAMR' +}; + +DATASET.FIELDS = { + %name %obs %t %mean % stand dev % unit conv + 'hep_TG' 1 't1' 'hep_TG_m' 'hep_TG_std' 1 [] + 'hep_C' 1 't1' 'hep_C_m' 'hep_C_std' 1 [] + 'pl_VLDL_TG' 1 't2' 'pl_VLDL_TG_m' 'pl_VLDL_TG_std' 1 [] + 'pl_HDL_C' 1 't2' 'pl_HDL_C_m' 'pl_HDL_C_std' 1 [] + 'pl_FFA' 1 't2' 'pl_FFA_m' 'pl_FFA_std' 1 [] + 'per_TG' 1 't3' 'perTG_m' 'perTG_std' 1 [] + 'pl_TC' 1 't2' 'pl_TC_m' 'pl_TC_std' 1 [] + 'fat_intk' 1 't2' 'FatInt_m' 'FatInt_std' 1 [] + 'gluc_intk' 1 't2' 'GlucInt_m' 'GlucInt_std' 1 [] + 'fat_ox' 1 't4' 'fat_ox_m' 'fat_ox_std' 1 [] + 'gluc_ox' 1 't4' 'gluc_ox_m' 'gluc_ox_std' 1 [] +% 'chol_intk' 0 't2' 'chol_intk_m' 'chol_intk_std' 1 [] +}; + +DATASET.FUNCTIONS = { +}; \ No newline at end of file diff --git a/AMF/models/dietModel/dietData.mat b/AMF/models/dietModel/dietData.mat new file mode 100644 index 0000000000000000000000000000000000000000..2420587bc7031f1a918285e25f2890e515e9d0e2 GIT binary patch literal 1705 zcmV;a23Gk^K~zjZLLfCRFd$7qR4ry{Y-KDUP;6mzW^ZzBIv`L(S4mDbG%O%Pa%Ew3 zWn>_4ZaN@WWn>^qVQwHYF(5H8IxsjoF*G1DFflbCARr(hARr(hARr(hARr(hARr(h zARr(hARr(hARr(hARr(hARr(B00000000000ZB~{0000X1^@tfoTXQ5Y*bYczWZ#u z(C4>w)LM6OZTKeRr_ul!=+1(}ua=Goz>^EoTJ9FmDnLQh$D9VmRMR95} zQhTimKMr6^$gAs?tymtYG(OvvSm>iQr$DX}`ULXAp(h+p4uj>(D}2RX-@0(<4~Lb3 zWfIPkwt)U{C~TFARlb6Pd}$5n4~N29gD(_5S13XWf&Or)J7};tBn*cBa2OiKY|T~J zOXv@WY+qIy@cBzCD+Sf^bs@KYVXRp%nE?g!8yZ!}uz)fyB}RL5lwe&sp%1MqE2RF|wLe8^jnMt3Kg7=-=Er(P z*=;2U`_n`GBL?`#7@xjW`Yf|;AKR~JEau|xv+Qu{el-v9b1A{|q(4#GyFhzA`m^X2 zD$}2FKKi6id-_YrFrxV^l>##CZh0BkybL?|IZH5JOplU>(D?N@;zS&tbSnC2^tP%6 z>rC?)an)T_tLJ~QrYnCbnavCH0eM$pmi zxo>Cfne~`?Iit??*1k9D^<0Ce!t&s}*az^C25u~DO5Jq*o?4`fgOOBhB% z)z2$txK4j|MdkVW)wMdT=vKEM?jB#Vy+?hjME}&M>ek-29@TJfx~ytOn&ox%M2r5k ztD|&v>R+lMHeHgE`CGyJx7w`J9uC^|=&-vL^S4R8;AOw_i2HX{)ClN|wyxpdG zIq#Az%A9+tEUQZnC?xSAp63;da`&FK$3%CRO z+J$|;Dffr-(y#LQxrKe|#dr_&y{L~~_;;ZmI^_O|{S6#P?(^~q#*KRG@p^4=};#`%ph%`5WG@gB!Mv_d*f_Y=-j z6meZgA#c%$-v((xev(iR38*7cPm$=ecH(_bggzemj7Og1z#mIoH*Vs6PXKR{ll z>eGonI0SwU)Qt`GV8=cUMSTVR*e-&^_bjjbF8bqL)87vwU(D~2>k|FXEHAJ7H2PB; z`pQ}4x7~>MHS2@xBw_$>j#b2K!+s7W(XYk#JnL`B`VikAjHBSE@O{>E2X&JQoCY}@ zGJ-_E6?qmstWU$dBQTx zepA3R1$I+0uLpK{@S8kf{fNhd`}t+eS2#`bu$*SpZ}~&&cVM0AzZ0u!H=J)c@+s99 z&x@`5zKN=Ttp2t0{lm2Phw@?9ijULLlkTGj-#tkiFI_yhJLMG3J+q zpRd{a0k!1+^z4Bx4fNu;Eqfa3z9HYDt;tyz8Y!)QdTsO01C;f1eQo2C@968~vki;a ze{1@Dt{qe8oxXPt4JOUzt^Gy0<G&!sr-)u^+@G4UV4i87BYT<_ZtcjRs#i~I|8Dvpbg(jJquEwn literal 0 HcmV?d00001 diff --git a/AMF/models/dietModel/loadData.m b/AMF/models/dietModel/loadData.m new file mode 100644 index 0000000..7d2dddb --- /dev/null +++ b/AMF/models/dietModel/loadData.m @@ -0,0 +1,153 @@ +data.diets.t1 = [0 12]*7*24; +data.diets.t2 = [0 4 8 12]*7*24; +data.diets.t3 = [0 1 3 5 7 9 12]*7*24; +data.diets.t4 = [3 10]*7*24; + + +% liver weights (g) +liver_weights = [ 2.85 + 3.40 + 3.39 + 1.88 + 1.74 + 1.43 + 3.02 + 3.96 + 4.28 + 3.54 ]; + +% nmol/mg tissue (mumol/g tissue) +data.diets.hep_TG_r = [ 109.3 + 124.6 + 115.9 + 62.5 + 44.0 + 47.9 + 106.0 + 111.9 + 112.1 + 83.8 ]; +data.diets.hep_TG_m = nanmean(data.diets.hep_TG_r .* liver_weights); +data.diets.hep_TG_std = nanstd(data.diets.hep_TG_r .* liver_weights); +% Wielinga et al. 9.1 (0.8) mumol TG/liver +data.diets.hep_TG_m = [9.1 data.diets.hep_TG_m]; % mumol / liver +data.diets.hep_TG_std = [0.8 data.diets.hep_TG_std]; % mumol / liver +% data.diets.hep_TG_m = [8.1 91.79]; + +% nmol/mg tissue (mumol/g tissue) +data.diets.hep_C_r = [ 16.6 + 12.3 + 14.7 + 8.8 + 9.5 + 10.2 + 13.5 + 15.7 + 13.3 + 13.2 ]; +data.diets.hep_C_m = nanmean(data.diets.hep_C_r .* liver_weights); +data.diets.hep_C_std = nanstd(data.diets.hep_C_r .* liver_weights); +% Wielinga et al. 6.8 (0.4) mumol C/liver +data.diets.hep_C_m = [6.8 data.diets.hep_C_m]; % mumol / liver +data.diets.hep_C_std = [0.4 data.diets.hep_C_std]; % mumol / liver +% data.diets.hep_C_m = [6.1 12.79]; +% data.diets.hep_C_std = [0.35 2.61]; + +% mM (mumol, assuming plasma volume = 1ml) +data.diets.pl_FFA_r = [ 1.87 0.71 0.53 1.40 + 1.27 0.87 0.55 1.51 + 1.52 0.65 0.61 1.64 + 0.99 0.66 0.65 1.04 + 0.77 0.61 0.46 1.19 + 1.60 0.61 0.38 1.07 + 1.34 0.52 0.80 1.13 + 1.41 0.92 0.59 1.17 + 1.51 0.68 0.46 1.53 + 1.43 0.61 0.56 1.48 ]; +data.diets.pl_FFA_m = [ 1.37 0.68 0.56 1.32]; % mumol / plasma +data.diets.pl_FFA_std = [0.31 0.12 0.12 0.22]; % mumol / plasma + +% mM +data.diets.pl_VLDL_TG_r = [ 2.27 1.58 1.45 2.00 + 2.7 1.25 1.47 2.39 + 2.78 1.08 1.31 2.42 + 2.07 1.30 1.10 0.77 + 1.88 1.06 1.17 0.79 + 5.72 1.64 1.13 0.82 + 4.23 1.57 1.34 2.16 + 1.89 1.20 2.30 7.97 + 2.57 1.44 2.48 7.50 + 1.89 1.39 2.02 5.57] ; + +data.diets.pl_VLDL_TG_m = [2.80 1.35 1.58 3.24]; % mumol / plasma +data.diets.pl_VLDL_TG_std = [1.25 0.21 0.50 2.75]; % mumol / plasma + +% mM +data.diets.pl_TC_r = [ 3.17 5.01 4.94 5.79 + 3.22 4.39 4.92 7.07 + 3.67 4.32 4.94 6.86 + 2.45 4.22 4.26 5.25 + 2.20 3.92 3.96 5.13 + 5.25 4.95 3.37 4.52 + 4.56 4.74 4.64 7.09 + 2.82 5.31 6.21 15.45 + 3.07 5.31 6.06 14.58 + 2.55 4.89 5.44 15.22] ; +data.diets.pl_TC_m = [ 3.30 4.70 4.87 8.69]; % mumol / plasma +data.diets.pl_TC_std = [0.96 0.47 0.88 4.50]; % mumol / plasma + +% mM +data.diets.pl_HDL_C_r = [ 1.69 3.03 3.21 2.64 + 1.29 3.03 3.44 2.47 + 1.06 3.35 3.25 2.51 + 0.61 3.09 3.64 3.56 + 0.82 2.69 2.83 2.73 + 1.79 1.82 NaN 2.86 + 1.10 1.91 3.91 2.97 + 1.31 2.56 2.63 1.41 + 1.15 3.03 2.86 1.81 + 1.20 NaN 3.49 1.80]; +data.diets.pl_HDL_C_m = [1.20 2.72 3.25 2.48]; % mumol / plasma +data.diets.pl_HDL_C_std = [0.36 0.54 0.42 0.64]; % mumol / plasma + + +% TG = (fat mass (g)) / 853 (g/mol) = TG (mol) ; + +data.diets.fat_mass = [ 2.4 7.6 11.3 14.4 14.4 18.1 19.0 + 3.6 8.1 10.2 13.8 15.7 18.4 18.6 + 2.3 6.3 10.1 13.7 15.8 19.4 20.8 + 0.8 2.9 5.0 8.4 10.0 13.4 13.8 + 0.9 2.8 3.9 7.2 8.4 10.7 11.7 + 1.1 1.8 1.6 3.4 4.5 6.7 9.6 + 1.3 3.2 4.7 9.3 11.9 15.3 19.9 + 3.2 8.2 11.8 14.7 16.7 21.1 23.3 + 2.1 6.9 10.8 14.7 17.5 21.3 22.4 + 1.7 6.2 11.6 15.4 18.3 22.4 23.4]; + +data.diets.perTG_m = nanmean(data.diets.fat_mass*(1e6/853)); +data.diets.perTG_std = nanstd(data.diets.fat_mass*(1e6/853)); + +% energy intake in TG equivalents +% TG = 9.2 kcal/g +% fat intake +data.diets.FatInt_m = [3.1 3.1 3.1 3.1]*0.60*(5.2/9.2)*1*(1e6/853)/24; +data.diets.FatInt_std = [0.3 0.3 0.3 0.3]*0.60*(5.2/9.2)*1*(1e6/853)/24; + +% gluc = 4.2 kcal/g --> gluc / TG = 0.46; 4/9 = 0.44; +% glucose intake +data.diets.GlucInt_m = [3.1 3.1 3.1 3.1]*0.20*(5.2/4.2)*1*(1e6/180)/24; +data.diets.GlucInt_std = [0.3 0.3 0.3 0.3]*0.20*(5.2/4.2)*1*(1e6/180)/24; + +% chol intake %% is there a TG equivalent of cholesterol? +data.diets.chol_intk_m = [3.1 3.1 3.1 3.1]*0.01; +data.diets.chol_intk_std = [0.3 0.3 0.3 0.3]*0.01; + +% fat oxidation (kcal/h) +data.diets.fat_ox_m = [6.98 8.79]*(1e6/853)/9.2/24; +data.diets.fat_ox_std = [0.81 0.78]*(1e6/853)/9.2/24; + +% glucose oxidation (kcal/h) +data.diets.gluc_ox_m = [1.32 1.10]*(1e6/180)/4.2/24; +data.diets.gluc_ox_std = [0.19 0.09]*(1e6/180)/4.2/24; + +save('dietData.mat', '-struct', 'data'); \ No newline at end of file diff --git a/AMF/models/dietModel/results/_Model_Diets_YP_diets__10_50.mat b/AMF/models/dietModel/results/_Model_Diets_YP_diets__10_50.mat new file mode 100644 index 0000000000000000000000000000000000000000..6503f867a7df8e73576101209ca2527e106aaf5d GIT binary patch literal 1147793 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 ?E)9=< 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