From ee71546a78661f2f7027edac6950d62004fe0093 Mon Sep 17 00:00:00 2001 From: Carter Mak Date: Thu, 17 Sep 2020 23:10:26 -0600 Subject: [PATCH] Add completed version --- .gitignore | 1 + README.md | 8 +++- generalMethod.m | 110 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 generalMethod.m diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9f68a3a --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.asv diff --git a/README.md b/README.md index f2fc480..04296c2 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,8 @@ -# MATLAB-General-Method +# MATLAB Error Analysis: General Method + Implementation of the "general method" of error analysis based on partial derivatives. The function reads in an anonymous function handle and input values with uncertainties and returns output values with uncertainties. + +--- + +*Source:* +*An Introduction to Error Analysis: the Study of the Uncertainties in Physical Measurements*, by John Robert. Taylor, 2nd ed., University Science Books, 1997, pp. 73–76. diff --git a/generalMethod.m b/generalMethod.m new file mode 100644 index 0000000..839db2b --- /dev/null +++ b/generalMethod.m @@ -0,0 +1,110 @@ +function [val,err] = generalMethod(f,inVals,inErrs) +% function [val,err] = generalMethod(f,inVals,inErrs) +% ------------------------------------------------------------------------- +% Carter Mak +% ------------------------------------------------------------------------- +% Description: +% Pass an anonymous function handle and cell arrays of input values with +% errors. Returns output value with error estimated using the general +% method based on partial derivatives. +% ------------------------------------------------------------------------- +% Inputs: +% f: function handle +% inVals: cell array of input values to f, in order +% inErrs: Cell array of uncertainties associated with each input value, +% in order. If no uncertainty, use 0. +% +% Outputs: +% val: Vector of output values +% err: Vector of uncertainties in output values +% ------------------------------------------------------------------------- + +%% Initialization +% Convert f to a symbolic function +g = sym(f); + +% Get list of input variables +symVars = symvar(g); + +% Number of input variables +nVars = length(symVars); + +% Check for correct number of input variables and errors +if (nVars ~= length(inVals) || nVars ~= length(inErrs)) + error('Incorrect number of input values and/or errors.') +end + +% Number of samples is length of longest input variable list +nSamples = 0; +for i = 1:length(inVals) + if length(inVals{i})>nSamples + nSamples = length(inVals{i}); + end +end + +% Check that all variables and errors have the same length. Inputs should +% either have length Nsamples or 1 (implies same value for all samples) +for i = 1:length(inVals) + + % Check all variables. Extend if necessary. + if length(inVals{i})==1 + inVals{i} = repmat(inVals{i},nSamples); + end + + % Check all error values. Extend if necessary. + if length(inErrs{i})==1 + inErrs{i} = repmat(inErrs{i},nSamples); + end + + % If the length of any inputs or error values isn't gucci, throw error + if nSamples~=length(inVals{i}) || nSamples~=length(inErrs{i}) + error('Inconsistent number of samples') + end + +end + +% Preallocate outputs +val = zeros(nSamples,1); +err = val; + +%% Calculus + +% Preallocate (ish. They're cell arrays. It doesn't really matter.) +derivs = cell(nVars,1); +derivInputs = derivs; + +% Calculate all partials +for i = 1:nVars + currVar = symVars(i); + currDiff = diff(g,currVar); + derivs{i} = matlabFunction(currDiff); + [~,derivInputs{i}] = intersect(symVars,symvar(currDiff),'stable'); +end + +%% Calculations + +% Preallocate array of intermediate error terms +intermedErrs = zeros(nVars,1); +sampleVals = zeros(nVars,1); + +% Loop over samples +for i = 1:nSamples + + % Store input variables to a temporary vector, sampleVals + for j = 1:nVars + sampleVals(j) = inVals{j}(i); + end + + % Calculate output value for sample i + tmpCell = num2cell(sampleVals); + val(i) = f(tmpCell{:}); + + % Loop over input variables for error calculation + for j = 1:nVars + currInputs = sampleVals(derivInputs{j}); + tmpCell = num2cell(currInputs); + currFunc = derivs{j}; + intermedErrs(j) = currFunc(tmpCell{:})*inErrs{j}(i); + end + err(i) = sqrt(sum(intermedErrs.^2,'omitnan')); +end \ No newline at end of file