Commit 07145799 authored by Jakob Gabriel's avatar Jakob Gabriel
Browse files

simplified solveAlgebraic and invert to the actually implemented cases.

parent d0479022
......@@ -810,48 +810,36 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete ...
end
end % blkdiag()
function solution = solveAlgebraic(obj, rhs, domainName, objLimit)
%% this method solves
% obj(gridName) == rhs
% for the variable specified by gridName.
% rhs must be of apropriate size and gridName must
% be an gridName of obj. If the result is constant (i.e., if
% obj only depends on variable, then a double array is
% returned. Else the solution is of the type as obj.
% Yet, this is only implemented for obj with one variable
% (grid) (see quantity.invert-method).
% The input objLimit specifies minimum and maximum of the
function solution = solveAlgebraic(obj, rhs, findBetween)
% solveAlgebraic solves
% obj( x ) == rhs
% for the variable specified x.
% Both x and rhs must be scalars.
% The input parameter findBetween specifies minimum and maximum of the
% values of obj, between which the solution should be searched.
arguments
obj (1, 1);
rhs (1, 1) double;
domainName (1, 1) string = obj.domain(1).name;
objLimit = [];
findBetween double = [];
end
assert(obj(1).nargin == 1, "only implemented for quantites on 1 domain");
assert(all(strcmp([obj(1).domain.name], domainName)), ...
"quantity does not depend on variable");
if ~isempty(objLimit)
assert(numel(objLimit)==2, "a lower and upper limit must be specified (or neither)");
if nargin > 2
assert(numel(findBetween)==2, "a lower and upper limit must be specified (or neither)");
objValueTemp = obj.on();
gridSelector = (objValueTemp >= objLimit(1)) & (objValueTemp <= objLimit(2));
gridSelector = (objValueTemp >= findBetween(1)) & (objValueTemp <= findBetween(2));
gridSelector([max(1, find(gridSelector, 1, 'first')-1), ...
min(find(gridSelector, 1, 'last')+1, numel(gridSelector))]) = 1;
limitedGrid = obj(1).domain.grid(gridSelector);
objCopy = obj.copy();
objCopy = objCopy.changeDomain(quantity.Domain(domainName, limitedGrid));
objInverseTemp = objCopy.invert(domainName);
solution = interp1(objValueTemp(gridSelector), obj.domain.grid(gridSelector), rhs);
else
objInverseTemp = obj.invert(domainName);
solution = interp1(obj.on(), obj.domain.grid, rhs);
end
solution = objInverseTemp.on(rhs);
end % solveAlgebraic()
function inverse = invert(obj, domainName)
function inverse = invert(obj)
% inverse solves the function representet by the quantity for
% its variable, for instance, if obj represents y = f(x), then
% invert returns an object containing x = f^-1(y).
......@@ -860,15 +848,11 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete ...
arguments
obj (1, 1);
domainName (1, 1) string = obj(1).domain(1).name;
end
assert(isscalar(obj), "invert is only implemented for scalars");
assert(numel(obj.nargin) == 1, "invert is only implemented for quantities on 1 domain");
inverse = quantity.Discrete(...
repmat(obj(1).domain(obj(1).domain.index(domainName)).grid(:), [1, size(obj)]), ...
quantity.Domain([obj(1).name], obj.on()), ...
'name', domainName);
inverse = quantity.Discrete(obj(1).domain.grid, ...
quantity.Domain(obj(1).name, obj.on()), "name", obj.domain.name);
end % invert()
function solution = solveDVariableEqualQuantity(obj, varargin)
......
......@@ -260,32 +260,22 @@ classdef Symbolic < quantity.Function
end
end % subsNumeric()
function solution = solveAlgebraic(obj, rhs, domainName, objLimit)
%% this method solves
% obj(gridName) == rhs
% for the variable specified by gridName.
% rhs must be of apropriate size and gridName must
% be an gridName of obj. If the result is constant (i.e., if
% obj only depends on variable, then a double array is
% returned. Else the solution is of the type as obj.
function solution = solveAlgebraic(obj, rhs, findBetween)
% solveAlgebraic solves
% obj( x ) == rhs
% for the variable specified x.
% Both x and rhs must be scalars.
% The input parameter findBetween specifies minimum and maximum of the
% values of obj, between which the solution should be searched.
arguments
obj (1, 1);
rhs (1, 1) double;
domainName (1, 1) string = obj.domain(1).name;
objLimit = [];
findBetween double = [];
end
assert(obj(1).nargin == 1, "only implemented for quantites on 1 domain");
assert(all(strcmp([obj(1).domain.name], domainName)), ...
"quantity does not depend on variable");
symbolicSolution = solve(obj(:).sym == rhs(:), ...
obj(1).variable(strcmp(obj(1).domain.name, domainName)));
if isnumeric(rhs) && (numel(obj(1).variable) == 1)
% solution will be a double array
solution = double(symbolicSolution);
else
solution = quantity.Symbolic(symbolicSolution);
end
symbolicSolution = solve(obj(:).sym == rhs(:), obj(1).variable);
solution = double(symbolicSolution);
end % solveAlgebraic()
function solution = solveDVariableEqualQuantity(obj, varargin)
......
......@@ -881,7 +881,7 @@ function testInvert(testCase)
x = quantity.Domain("x", linspace(0, 1, 21));
% scalar
fScalar = quantity.Discrete((x.grid).^2, x);
fScalarInverse = fScalar.invert(fScalar.domain.name);
fScalarInverse = fScalar.invert();
testCase.verifyEqual(fScalarInverse.on(fScalar.on()), x.grid),
end
......@@ -889,7 +889,7 @@ function testSolveAlgebraic(testCase)
x = quantity.Domain("x", linspace(0, 1, 21));
% scalar
fScalar = quantity.Discrete((1+x.grid).^2, x);
solutionScalar = fScalar.solveAlgebraic(2, fScalar.domain.name);
solutionScalar = fScalar.solveAlgebraic(2);
testCase.verifyEqual(solutionScalar, sqrt(2)-1, "AbsTol", 1e-3);
end
......
......@@ -1090,7 +1090,7 @@ assume(x>0 & x<1);
X = quantity.Domain("x", linspace(0,1,11));
% scalar
fScalar = quantity.Symbolic([(1+x)^2], X);
solutionScalar = fScalar.solveAlgebraic(2, fScalar.domain(1).name);
solutionScalar = fScalar.solveAlgebraic(2);
testCase.verifyEqual(solutionScalar, sqrt(2)-1, "AbsTol", 1e-12);
% % array
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment