Commit 6da3dcdf authored by Ferdinand Fischer's avatar Ferdinand Fischer
Browse files

Temp state for the implementation of the domain object.

parent 50afa926
......@@ -90,23 +90,11 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
domainParser.parse(varargin{:});
if domainParser.isDefault('domain') && ...
domainParser.isDefault('grid') && ...
domainParser.isDefault('gridName')
( domainParser.isDefault('grid') || ...
domainParser.isDefault('gridName') )
% case 1: nothing about the grid is defined
% -> use default grid
assert(iscell(valueOriginal), 'If no grid is specified, valueOriginal must be a cell-array')
valueOriginalGridSize = size(valueOriginal{1});
myDomain = quantity.Domain.defaultGrid(valueOriginalGridSize);
elseif domainParser.isDefault('domain') && ...
domainParser.isDefault('grid')
% case 2: the gridNames are specified
% -> use default grid with specified names
assert(iscell(valueOriginal), 'If no grid is specified, valueOriginal must be a cell-array')
valueOriginalGridSize = size(valueOriginal{1});
myDomain = quantity.Domain.defaultGrid(valueOriginalGridSize, ...
misc.ensureIsCell(domainParser.Results.gridName));
error('No domain is specified! A domain is obligatory for the initialization of a quantity.')
elseif domainParser.isDefault('domain')
% case 3: the gridNames and the gridValues are defined:
% -> initialize quantity.Domain objects with the
......@@ -224,7 +212,7 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
% has already been computed.
empty = isempty(obj.valueDiscrete);
if any(empty(:))
obj.valueDiscrete = obj.on(obj.grid);
obj.valueDiscrete = obj.obj2value(obj.domain, true);
end
valueDiscrete = obj.valueDiscrete;
end
......@@ -287,46 +275,61 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
end
methods (Access = public)
function value = on(obj, myGrid, myGridName)
% TODO es sieht so aus als w�rde die Interpolation bei
% konstanten werten ziemlichen Quatsch machen!
% Da muss man nochmal ordentlich drauf schauen!
function value = on(obj, myDomain, gridNames)
% ON evaluation of the quantity on a certain domain.
% value = on(obj) or value = obj.on(); evaluates the quantity
% on its standard grid.
% value = obj.on( myDomain ) evalutes the quantity on the
% grid specified by myDomain. The order of the domains in
% domain, will be the same as from myDomain.
% value = obj.on( grid ) evaluates the quantity specified by
% grid. Grid must be a cell-array with the grids as elements.
% value = obj.on( grid, gridName ) evaluates the quantity
% specified by grid. Grid must be a cell-aary with the grids
% as elements. By the gridName parameter the order of the
% grid can be specified.
if isempty(obj)
value = zeros(size(obj));
else
if nargin == 1
myGrid = obj(1).grid;
myGridName = obj(1).gridName;
elseif nargin >= 2 && ~iscell(myGrid)
myGrid = {myGrid};
end
gridPermuteIdx = 1:obj(1).nargin;
if nargin == 3
if ~iscell(myGridName)
myGridName = {myGridName};
if nargin == 2
% case 1: a domain is specified by myDomain or by
% myDomain as a cell-array with grid entries
if iscell(myDomain) || isnumeric(myDomain)
myDomain = misc.ensureIsCell(myDomain);
assert(all(cellfun(@(v)isvector(v), myDomain)), 'The cell entries for a new grid have to be vectors')
newGrid = myDomain;
myDomain = quantity.Domain.empty();
for k = 1:length(newGrid)
myDomain(k) = quantity.Domain('grid', newGrid{k}, 'name', obj(1).domain(k).name);
end
end
assert(numel(myGrid) == numel(myGridName), ...
['If on() is called by using gridNames as third input', ...
', then the cell-array of grid and gridName must have ', ...
'equal number of elements.']);
assert(numel(myGridName) == obj(1).nargin, ...
'All (or none) gridName must be specified');
gridPermuteIdx = cellfun(@(v) obj(1).gridIndex(v), myGridName);
myGrid = myGrid(gridPermuteIdx);
elseif nargin == 3
assert(iscell(myDomain), 'If the domain is specified by cell-array pairs, the value myDomain must be a cell-array with grid entries')
assert(all(cellfun(@(v)isvector(v), myDomain)), 'The cell entries for a new grid have to be vectors')
assert(iscell(gridNames), 'The gridNames parameter must be cell array')
assert(all(cellfun(@ischar, gridNames)), 'The gridNames must be strings')
newGrid = myDomain;
myDomain = quantity.Domain.empty();
for k = 1:length(newGrid)
myDomain(k) = quantity.Domain('grid', newGrid{k}, 'name', gridNames{k});
end
else
myDomain = obj(1).domain;
end
% verify the domain
assert(numel(myDomain) == numel(obj(1).domain), ['Wrong grid for the evaluation of the object']);
[myDomain, gridPermuteIdx] = obj(1).domain.permute(myDomain);
% get the valueDiscrete data for this object. Apply the
% permuted myDomain. Then the obj2value will be evaluated
% in the order of the original domain. The permuatation to
% the new order will be done in the next step.
value = obj.obj2value(myDomain(gridPermuteIdx));
value = obj.obj2value();
if nargin >= 2 && (prod(obj(1).gridSize) > 1)
indexGrid = arrayfun(@(s)linspace(1,s,s), size(obj), 'UniformOutput', false);
tempInterpolant = numeric.interpolant(...
[obj(1).grid, indexGrid{:}], value);
value = tempInterpolant.evaluate(myGrid{:}, indexGrid{:});
elseif obj.isConstant
value = repmat(value, [cellfun(@(v) numel(v), myGrid), ones(1, length(size(obj)))]);
gridPermuteIdx = 1:numel(myGrid);
end
value = permute(reshape(value, [cellfun(@(v) numel(v), myGrid), size(obj)]), ...
value = permute(reshape(value, [cellfun(@(v) numel(v), {myDomain(gridPermuteIdx).grid}), size(obj)]), ...
[gridPermuteIdx, numel(gridPermuteIdx)+(1:ndims(obj))]);
end
end
......@@ -422,37 +425,6 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
end
end
function [gridJoined, gridNameJoined] = gridJoin(obj1, obj2)
%% gridJoin combines the grid and gridName of two objects (obj1,
% obj2), such that every gridName only occurs once and that the
% finer grid of both is used.
gridNameJoined = unique([obj1(1).gridName, obj2(1).gridName]);
gridJoined = cell(1, numel(gridNameJoined));
for it = 1 : numel(gridNameJoined)
currentGridName = gridNameJoined{it};
[index1, lolo1] = obj1.gridIndex(currentGridName);
[index2, lolo2] = obj2.gridIndex(currentGridName);
if ~any(lolo1)
gridJoined{it} = obj2(1).grid{index2};
elseif ~any(lolo2)
gridJoined{it} = obj1(1).grid{index1};
else
tempGrid1 = obj1(1).grid{index1};
tempGrid2 = obj2(1).grid{index2};
if ~obj1.isConstant && ~obj2.isConstant
assert(tempGrid1(1) == tempGrid2(1), 'Grids must have same domain for gridJoin')
assert(tempGrid1(end) == tempGrid2(end), 'Grids must have same domain for gridJoin')
end
if numel(tempGrid1) > numel(tempGrid2)
gridJoined{it} = tempGrid1;
else
gridJoined{it} = tempGrid2;
end
end
end
end % gridJoin()
function obj = sort(obj, varargin)
%SORT sorts the grid of the object in a desired order
% obj = sortGrid(obj) sorts the grid in alphabetical order.
......@@ -814,6 +786,26 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
end
function solution = subs(obj, gridName2Replace, values)
% SUBS substitute variables of a quantity
% solution = SUBS(obj, newDomain), replaces the original domain
% of the object with the new domain specified by newDomain.
% NewDomain must have the same grid name as the original
% domain.
%
% solution = SUBS(obj, GRIDNAMES2REPLACE, VALUES)
% replaces the domains which are specified by
% GRIDNAMES2REPLACE by VALUES. GRIDNAMES2REPLACE must be a
% cell-array with the names of the domains which should be
% replaced by VALUES. VALUES must be a cell-array of the new
% values or new grid names.
%
% Example:
% q = q.subs('z', 't')
% will replace the domain with the name 'z' by a domain
% with the name 't' but with the same discretization.
% q = q.subs('z', linspace(0,1)')
% will replace the grid of domain with the name 'z' by
% the new grid specified by linspace.
if nargin == 1 || isempty(gridName2Replace)
% if gridName2Replace is empty, then nothing must be done.
solution = obj;
......@@ -822,14 +814,19 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
solution = obj;
else
% input checks
assert(nargin == 3, ['Wrong number of input arguments. ', ...
'gridName2Replace and values must be cell-arrays!']);
if ~iscell(gridName2Replace)
gridName2Replace = {gridName2Replace};
end
if ~iscell(values)
values = {values};
if nargin == 2
assert(isa(gridName2Replace, 'quantity.Domain'), 'If only two parameters are specified, the second parameter must be a quantiy.Domain');
values = {gridName2Replace.grid};
gridName2Replace = {gridName2Replace.name};
elseif nargin == 3
gridName2Replace = misc.ensureIsCell(gridName2Replace);
values = misc.ensureIsCell(values);
end
assert(numel(values) == numel(gridName2Replace), ...
'gridName2Replace and values must be of same size');
......@@ -865,8 +862,8 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
% called with subs(f, zeta, z), then g(z) = f(z, z)
% results, hence the dimensions z and zeta are
% merged.
gridIndices = [obj(1).gridIndex(gridName2Replace{1}), ...
obj(1).gridIndex(values{1})];
gridIndices = [obj(1).domain.gridIndex(gridName2Replace{1}), ...
obj(1).domain.gridIndex(values{1})];
newGridForOn = obj(1).grid;
if numel(obj(1).grid{gridIndices(1)}) > numel(obj(1).grid{gridIndices(2)})
newGridForOn{gridIndices(2)} = newGridForOn{gridIndices(1)};
......@@ -886,7 +883,7 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
% changed.
newGrid = obj(1).grid;
newGridName = obj(1).gridName;
newGridName{obj(1).gridIndex(gridName2Replace{1})} ...
newGridName{obj(1).domain.gridIndex(gridName2Replace{1})} ...
= values{1};
newValue = obj.on();
end
......@@ -900,7 +897,7 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
% newGrid is the similar to the original grid, but the
% grid of gridName2Replace is removed.
newGrid = obj(1).grid;
newGrid = newGrid((1:1:numel(newGrid)) ~= obj.gridIndex(gridName2Replace{1}));
newGrid = newGrid((1:1:numel(newGrid)) ~= obj(1).domain.gridIndex(gridName2Replace{1}));
newGridSize = cellfun(@(v) numel(v), newGrid);
% newGridForOn is the similar to the original grid, but
% the grid of gridName2Replace is set to values{1} for
......@@ -930,9 +927,12 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
solution = solution.subs(gridName2Replace(2:end), values(2:end));
end
end
end
function [idx, logicalIdx] = gridIndex(obj, varargin)
[idx, logicalIdx] = obj(1).domain.gridIndex(varargin{:});
end
function value = at(obj, point)
% at() evaluates the object at one point and returns it as array
% with the same size as size(obj).
......@@ -1017,20 +1017,6 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
end
end
function matGrid = ndgrid(obj, grid)
% ndgrid calles ndgrid for the default grid, if no other grid
% is specified. Empty grid as input returns empty cell as
% result.
if nargin == 1
grid = obj.grid;
end
if isempty(grid)
matGrid = {};
else
[matGrid{1:obj.nargin}] = ndgrid(grid{:});
end
end % ndgrid()
function H = plot(obj, varargin)
H = [];
p = misc.Parser();
......@@ -1222,28 +1208,37 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
end % flipGrid()
function newObj = changeGrid(obj, gridNew, gridNameNew)
% CHANGEGRID change the grid of the quantity.
% newObj = CHANGEGRID(obj, gridNew, gridNameNew)
% change the grid of the obj quantity. The order of grid and
% gridName in the obj properties remains unchanged, only the
% data points are exchanged.
%
% example:
% q.changeGrid( linspace(0,1)', 't')
% will change the grid with the name 't' to the new grid linspace(0,1)'
if isempty(obj)
newObj = obj.copy();
return;
end
gridIndexNew = obj(1).gridIndex(gridNameNew);
myGrid = cell(1, numel(obj(1).grid));
myGridName = cell(1, numel(obj(1).grid));
for it = 1 : numel(myGrid)
myGrid{gridIndexNew(it)} = gridNew{it};
myGridName{gridIndexNew(it)} = gridNameNew{it};
gridNew = misc.ensureIsCell(gridNew);
gridNameNew = misc.ensureIsCell(gridNameNew);
[gridIndexNew, logIdx] = obj(1).domain.gridIndex(gridNameNew);
newDomain = obj(1).domain;
for i = 1 : length(gridIndexNew)
newDomain(gridIndexNew(i)) = quantity.Domain(...
'grid', gridNew{i}, 'name', gridNameNew{i});
end
assert(isequal(myGridName(:), obj(1).gridName(:)), 'rearranging grids failed');
assert(isequal({newDomain.name}, obj(1).gridName), 'rearranging grids failed');
newObj = obj.copy();
for it = 1 : numel(obj)
newObj(it).valueDiscrete = obj(it).on(myGrid);
[newObj.domain] = deal(newDomain);
for i = 1 : numel(obj)
newObj(i).valueDiscrete = obj(i).on(newDomain);
end
%[newObj.derivatives] = deal({});
[newObj.grid] = deal(myGrid);
end
function [lowerBounds, upperBounds] = getBoundaryValues(obj, varargin)
......@@ -1438,6 +1433,9 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
P = (b' * a')';
P.setName([a(1).name, ' ', b(1).name]);
return
elseif a.isConstant() && b.isConstant()
P = a.on() * b.on();
return
end
if isscalar(b)
% do the scalar multiplication in a loop
......@@ -1469,38 +1467,48 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
% multiple dimensions of the input are correctly arranged.
[idx, permuteGrid] = computePermutationVectors(a, b);
parameters = struct(a(1));
parameters.name = [a(1).name, ' ', b(1).name];
parameters.grid = [...
a(1).grid(idx.A.common), ...
b(1).grid(~idx.B.common)];
parameters.gridName = [...
a(1).gridName(idx.A.grid), ...
b(1).gridName(~idx.B.common)];
parameters.figureID = a(1).figureID;
domainA = a(1).domain;
domainB = b(1).domain;
% select finest grid from a and b
parameters.grid = cell(1, numel(parameters.gridName));
[gridJoined, gridNameJoined] = gridJoin(a, b);
joinedDomain = gridJoin(domainA, domainB);
newDomainName = {joinedDomain.name};
% gridJoin combines the grid of a and b while using the finer
% of both.
aGrid = cell(1, a.nargin); % for later call of a.on() with fine grid
bGrid = cell(1, b.nargin); % for later call of b.on() with fine grid
for it = 1 : numel(parameters.gridName)
parameters.grid{it} = gridJoined{...
strcmp(parameters.gridName{it}, gridNameJoined)};
if a.gridIndex(parameters.gridName{it})
aGrid{a.gridIndex(parameters.gridName{it})} = ...
parameters.grid{it};
finalGridOrder = [domainA(idx.A.common), domainA(~idx.A.common), domainB(~idx.B.common)];
%% generate the new grids
newDomainA = quantity.Domain.empty(); % for later call of a.on() with fine grid
newDomainB = quantity.Domain.empty(); % for later call of b.on() with fine grid
for i = 1 : numel(newDomainName)
parameters.domain(i) = finalGridOrder(i);
% if there is a component of the original domain in the
% joined domain, it can happen the length of a domain has
% changed. Thus, it must be updated for a later evaluation.
idxA = domainA.gridIndex(finalGridOrder(i).name);
idxB = domainB.gridIndex(finalGridOrder(i).name);
if idxA
newDomainA = [newDomainA, finalGridOrder(i)];
end
if b.gridIndex(parameters.gridName{it})
bGrid{b.gridIndex(parameters.gridName{it})} = ...
parameters.grid{it};
if idxB
newDomainB = [newDomainB, finalGridOrder(i)];
end
end
parameters = misc.struct2namevaluepair(parameters);
valueA = permute(a.on(aGrid), idx.A.permute);
valueB = permute(b.on(bGrid), idx.B.permute);
%%
valueA = a.on(newDomainA);
valueB = b.on(newDomainB);
C = misc.multArray(valueA, valueB, idx.A.value(end), idx.B.value(1), idx.common);
C = permute(C, permuteGrid);
......@@ -1712,7 +1720,7 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
function myGrid = gridOf(obj, myGridName)
if ~iscell(myGridName)
gridIdx = obj(1).gridIndex(myGridName);
gridIdx = obj(1).domain.gridIndex(myGridName);
if gridIdx > 0
myGrid = obj(1).grid{gridIdx};
else
......@@ -1721,7 +1729,7 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
else
myGrid = cell(size(myGridName));
for it = 1 : numel(myGrid)
gridIdx = obj(1).gridIndex(myGridName{it});
gridIdx = obj(1).domain.gridIndex(myGridName{it});
if gridIdx > 0
myGrid{it} = obj(1).grid{gridIdx};
else
......@@ -1731,37 +1739,6 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
end
end
function [idx, logicalIdx] = gridIndex(obj, names)
%% GRIDINDEX returns the index of the grid
% [idx, log] = gridIndex(obj, names) searches in the gridName
% properties of obj for the "names" and returns its index as
% "idx" and its logical index as "log"
if nargin == 1
names = obj(1).gridName;
end
if ~iscell(names)
names = {names};
end
idx = zeros(1, length(names));
nArgIdx = 1:obj.nargin();
logicalIdx = false(1, obj.nargin());
for k = 1:length(names)
log = strcmp(obj(1).gridName, names{k});
logicalIdx = logicalIdx | log;
if any(log)
idx(k) = nArgIdx(log);
else
idx(k) = 0;
end
end
end
function result = diff(obj, k, diffGridName)
% DIFF computation of the derivative
% result = DIFF(obj, k, diffGridName) applies the
......@@ -1888,8 +1865,6 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
myGrid = currentGrid(domainIdx{idxGrid});
for kObj = 1:numel(obj)
J = numeric.trapz_fast_nDim(myGrid, obj(kObj).atIndex(domainIdx{:}), idxGrid);
......@@ -1900,21 +1875,22 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
J = shiftdim(J);
end
if all(isGrid)
grdName = '';
newGrid = {};
else
grdName = obj(kObj).gridName{~isGrid};
newGrid = obj(kObj).grid{~isGrid};
end
% create result:
I(kObj).valueDiscrete = J;
I(kObj).gridName = grdName;
I(kObj).grid = newGrid;
I(kObj).name = ['int(' obj(kObj).name ')'];
end
if all(isGrid)
grdName = '';
newGrid = {};
else
grdName = obj(kObj).gridName{~isGrid};
newGrid = obj(kObj).grid{~isGrid};
end
newDomain = quantity.Domain('grid', newGrid, 'name', grdName);
[I.domain] = deal(newDomain);
end
function result = cumInt(obj, domain, lowerBound, upperBound)
......@@ -1930,7 +1906,7 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
% input parser since some default values depend on intGridName.
myParser = misc.Parser;
myParser.addRequired('domain', @(d) obj.gridIndex(d) ~= 0);
myParser.addRequired('domain', @(d) obj(1).domain.gridIndex(d) ~= 0);
myParser.addRequired('lowerBound', ...
@(l) isnumeric(l) || ischar(l) );
myParser.addRequired('upperBound', ...
......@@ -1939,7 +1915,7 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
% get grid
myGrid = obj(1).grid;
intGridIdx = obj.gridIndex(domain);
intGridIdx = obj(1).domain.gridIndex(domain);
% integrate
F = numeric.cumtrapz_fast_nDim(myGrid{intGridIdx}, ...
......@@ -1968,54 +1944,57 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
% for support of numeric inputs:
if ~isa(A, 'quantity.Discrete')
if isnumeric(A)
A = quantity.Discrete(A, 'name', 'c', 'gridName', {}, 'grid', {});
A = quantity.Discrete(A, 'name', 'c', 'domain', quantity.Domain.empty());
else
error('Not yet implemented')
end
elseif ~isa(B, 'quantity.Discrete')
if isnumeric(B)
B = quantity.Discrete(B, 'name', 'c', 'gridName', {});
B = quantity.Discrete(B, 'name', 'c', 'domain', quantity.Domain.empty());
else
B = quantity.Discrete(B, 'name', 'c', 'gridName', A(1).gridName, 'grid', A.grid);
end
end
% combine both domains with finest grid
[gridJoined, gridNameJoined] = gridJoin(A, B);
gridJoinedLength = cellfun(@(v) numel(v), gridJoined);
joinedDomain = gridJoin(A(1).domain, B(1).domain);
[aDiscrete] = A.expandValueDiscrete(gridJoined, gridNameJoined, gridJoinedLength);
[bDiscrete] = B.expandValueDiscrete(gridJoined, gridNameJoined, gridJoinedLength);
[aDiscrete] = A.expandValueDiscrete(joinedDomain);
[bDiscrete] = B.expandValueDiscrete(joinedDomain);
% create result object
C = quantity.Discrete(aDiscrete + bDiscrete, ...
'grid', gridJoined, 'gridName', gridNameJoined, ...
'size', size(A), 'name', [A(1).name, '+', B(1).name]);
'domain', joinedDomain, ...
'name', [A(1).name, '+', B(1).name]);
end
function [valDiscrete] = expandValueDiscrete(obj, gridJoined, gridNameJoined, gridJoinedLength)
function [valDiscrete] = expandValueDiscrete(obj, newDomain)
% EXPANDVALUEDISCRETE
% [valDiscrete, gridNameSorted] = ...
% expandValueDiscrete(obj, gridIndex, valDiscrete)
% Expanses the value of obj, so that
% todo
gridNameJoined = {newDomain.name};
gridJoinedLength = newDomain.gridLength;
% get the index of obj.grid in the joined grid
gridLogical = logical( obj.gridIndex(gridNameJoined) );
[~, logicalIdx] = newDomain.gridIndex({obj(1).domain.name});
valDiscrete = obj.on(gridJoined(gridLogical > 0), gridNameJoined(gridLogical > 0));
valDiscrete = obj.on( newDomain(logicalIdx) );
oldDim = ndims(valDiscrete);
valDiscrete = permute(valDiscrete, [(1:sum(~gridLogical)) + oldDim, 1:oldDim] );
valDiscrete = repmat(valDiscrete, [gridJoinedLength(~gridLogical), ones(1, ndims(valDiscrete))]);
valDiscrete = permute(valDiscrete, [(1:sum(~logicalIdx)) + oldDim, 1:oldDim] );
valDiscrete = repmat(valDiscrete, [gridJoinedLength(~logicalIdx), ones(1, ndims(valDiscrete))]);
%
valDiscrete = reshape(valDiscrete, ...
[gridJoinedLength(~gridLogical), gridJoinedLength(gridLogical), size(obj)]);
[gridJoinedLength(~logicalIdx), gridJoinedLength(logicalIdx), size(obj)]);
% % permute valDiscrete such that grids are in the order specified
% % by gridNameJoined.
gridIndex = 1:numel(gridLogical);
gridOrder = [gridIndex(~gridLogical), gridIndex(gridLogical)];
valDiscrete = permute(valDiscrete, [gridOrder, numel(gridLogical)+(1:ndims(obj))]);
% permute valDiscrete such that grids are in the order specified
% by gridNameJoined.