From 9cdda192d7e779f6535e1d71b00660f2dfd19a9d Mon Sep 17 00:00:00 2001
From: Ferdinand Fischer <ferdinand.fischer@fau.de>
Date: Tue, 10 Mar 2020 19:58:45 +0100
Subject: [PATCH] Change type of quantity.Domain.name from char to string.

Change the parameter order of quantity.*/diff
Now, the domain name wrt which the derivative should be taken is the second argument and the order of the derivative is the third.

speed up of the unittest utilizing setupOnce
---
 +misc/ensureString.m                |  16 ++++
 +mustBe/gridName.m                  |   8 ++
 +quantity/Discrete.m                | 108 ++++++++-------------
 +quantity/Domain.m                  | 144 ++++++++++++----------------
 +quantity/Piecewise.m               |   8 +-
 +quantity/Symbolic.m                |  37 +++----
 +unittests/+misc/testMisc.m         |  12 +++
 +unittests/+quantity/testDiscrete.m |  90 ++++++++++-------
 +unittests/+quantity/testDomain.m   |  24 +++--
 +unittests/+quantity/testSymbolic.m |  26 ++---
 10 files changed, 242 insertions(+), 231 deletions(-)
 create mode 100644 +misc/ensureString.m
 create mode 100644 +mustBe/gridName.m

diff --git a/+misc/ensureString.m b/+misc/ensureString.m
new file mode 100644
index 0000000..52d80b0
--- /dev/null
+++ b/+misc/ensureString.m
@@ -0,0 +1,16 @@
+function [str] = ensureString(chr)
+
+if iscell( chr )
+	if ~all( cellfun( @ischar, chr ) )
+		chr = [chr{:}];
+	end
+end
+
+if isstring( chr )
+	str = chr;
+else
+	str = convertCharsToStrings( chr );
+end
+
+end
+
diff --git a/+mustBe/gridName.m b/+mustBe/gridName.m
new file mode 100644
index 0000000..d2c4147
--- /dev/null
+++ b/+mustBe/gridName.m
@@ -0,0 +1,8 @@
+function gridName( name )
+
+name = misc.ensureString( name );
+
+assert( isstring( name ), 'A grid name should be a string-array')
+
+end
+
diff --git a/+quantity/Discrete.m b/+quantity/Discrete.m
index b435a3c..63841fc 100644
--- a/+quantity/Discrete.m
+++ b/+quantity/Discrete.m
@@ -1,4 +1,5 @@
-classdef  (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mixin.Copyable & matlab.mixin.CustomDisplay
+classdef  (InferiorClasses = {?quantity.Symbolic}) Discrete ...
+		< handle & matlab.mixin.Copyable & matlab.mixin.CustomDisplay
 
 	properties (SetAccess = protected)
 		% Discrete evaluation of the continuous quantity
@@ -79,7 +80,7 @@ classdef  (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
 				
 				%% input parser
 				myParser = misc.Parser();
-				myParser.addParameter('name', string(), @isstr);
+				myParser.addParameter('name', "", @mustBe.gridName);
 				myParser.addParameter('figureID', 1, @isnumeric);
 				myParser.parse(varargin{:});
 				
@@ -143,9 +144,9 @@ classdef  (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
 		%---------------------------
 		function gridName = get.gridName(obj)
 			if isempty(obj.domain)
-				gridName = {};
+				gridName = [];
 			else
-				gridName = {obj.domain.name};
+				gridName = [obj.domain.name];
 			end
 		end
 		
@@ -316,21 +317,18 @@ classdef  (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
 			%	for this, find the index of the common domain in list of
 			%	temporary combined domain
 			
-			intersectDomain = intersect( {originalDomain( ~logOfDomain ).name}, ...
-				{g(1).domain.name} );
+			intersectDomain = intersect( originalDomain( ~logOfDomain ), ...
+				g(1).domain );
 			
 			if ~isempty(intersectDomain)
 				
-				idx = 1:length(tmpDomain);
-				logCommon = strcmp({tmpDomain.name}, intersectDomain);
+				idx = tmpDomain.gridIndex( intersectDomain );
 				
 				% take the diagonal values of the common domain, i.e., z = zeta		
 				% use the diag_nd function because it seems to be faster
 				% then the diagNd function, although the values must be
 				% sorted.
-				% #TODO: Rewrite the diagNd function, using for loops, in order to be as fast as diag_nd
-				newValues = permute( newValues, [idx(logCommon), idx(~logCommon)]);
-				newValues = misc.diag_nd(newValues);
+				newValues = misc.diagNd(newValues, idx);
 			end
 			
 			% *) build a new valueDiscrete on the correct grid.		
@@ -398,14 +396,10 @@ classdef  (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
 						% Since the order of the domains is not neccessarily equal to the
 						% order in obj(1).domain, this is more involved:
 						myDomain = misc.ensureIsCell(myDomain);
-						gridNames = misc.ensureIsCell(gridNames);
+						gridNames = misc.ensureString(gridNames);
 
 						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();
@@ -1015,7 +1009,7 @@ classdef  (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
 		
 		function [idx, logicalIdx] = gridIndex(obj, varargin)
 			warning('DEPRICATED: use quantity.Domain.gridIndex method instead')
-			[idx, logicalIdx] = obj(1).domain.gridIndex(varargin{:});
+			[~, idx, logicalIdx] = obj(1).domain.find(varargin{:});
 		end 
 		
 		function value = at(obj, point)
@@ -1305,19 +1299,20 @@ classdef  (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
 			%	corresponding domain from DOMAIN.
 			%
 			%	example:
-			%	q.changeGrid( linspace(0,1)', 't')
-			%	will change the grid with the name 't' to the new grid linspace(0,1)'
+			%		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
 			
 			if isa(gridNew, 'quantity.Domain')
-				gridNameNew = {gridNew.name};
+				gridNameNew = [gridNew.name];
 				gridNew = {gridNew.grid};
 			else
+				gridNameNew = misc.ensureString(gridNameNew);				
 				gridNew  = misc.ensureIsCell(gridNew);
-				gridNameNew = misc.ensureIsCell(gridNameNew);
 			end
 			
 			if obj(1).isConstant
@@ -1325,7 +1320,7 @@ classdef  (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
 				newDomain(1:length( gridNew )) = quantity.Domain();
 				for it = 1 : length(gridNew)
 					newDomain(it) = ...
-						quantity.Domain(gridNameNew{it}, gridNew{it});
+						quantity.Domain(gridNameNew(it), gridNew{it});
 				end
 			else
 				gridIndexNew = obj(1).domain.gridIndex(gridNameNew);
@@ -1333,9 +1328,9 @@ classdef  (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
 
 				for it = 1 : length(gridIndexNew)
 					newDomain(gridIndexNew(it)) = ...
-						quantity.Domain(gridNameNew{it}, gridNew{it});
+						quantity.Domain(gridNameNew(it), gridNew{it});
 				end
-				assert(isequal({newDomain.name}, obj(1).gridName), ...
+				assert(isequal([newDomain.name], obj(1).gridName), ...
 					'rearranging grids failed');
 			end
 			
@@ -1661,17 +1656,13 @@ classdef  (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
 			% Optionally, a weight can be defined, such that instead
 			%	xNorm = sqrt(int_0^1 x.' * weight * x dz).
 			% The integral domain is specified by integralGrid.
-			
 			arguments
 				obj;
-				integralGridName = {obj(1).domain.name};
+				integralGridName {mustBe.gridName} = [obj(1).domain.name];
 				optArg.weight = eye(size(obj, 1));
 			end
 			
-			integralGridName = misc.ensureIsCell(integralGridName);
-			
-			assert(all(ischar([integralGridName{:}])), ...
-				'integralGrid must specify a gridName as a char');
+			integralGridName = misc.ensureString(integralGridName);
 			
 			if obj.nargin == 1 && all(strcmp(obj(1).gridName, integralGridName))
 				xNorm = sqrtm(on(int(obj.' * optArg.weight * obj), integralGridName));
@@ -1844,16 +1835,16 @@ classdef  (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
 			end
 		end
 		
-		function result = diff(obj, k, diffGridName)
+		function result = diff(obj, diffGridName, k)
 			% DIFF computation of the derivative
 			%	result = DIFF(obj, k, diffGridName) applies the
 			% 'k'th-derivative for the variable specified with the input
 			% 'diffGridName' to the obj. If no 'diffGridName' is specified,
 			% then diff applies the derivative w.r.t. all gridNames.
-			if nargin == 1 || isempty(k)
-				k = 1;  % by default, only one derivatve per diffGridName is applied
-			else
-				assert(isnumeric(k) && (round(k) == k))
+			arguments
+				obj;
+				diffGridName (1,1) string = obj(1).gridName;
+				k uint64 = 1;
 			end
 			
 			if obj.isConstant && isempty(obj(1).gridName)
@@ -1864,11 +1855,6 @@ classdef  (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
 				return
 			end
 			
-			if nargin < 3 % if no diffGridName is specified, then the derivative
-				% w.r.t. all gridNames is applied
-				diffGridName = obj(1).gridName;
-			end
-			
 			if isa(diffGridName, 'quantity.Domain')
 				% a quantity.Domain is used instead of a grid name 
 				%	-> get the grid name from the domain object
@@ -1880,22 +1866,7 @@ classdef  (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
 				diffGridName = {diffGridName.name};
 			end
 			
-			% diff for each element of diffGridName (this is rather
-			% inefficient, but an easy implementation of the specification)
-			if iscell(diffGridName) || isempty(diffGridName)
-				if numel(diffGridName) == 0 || isempty(diffGridName)
-					result = copy(obj);
-				else
-					result = obj.diff(k, diffGridName{1}); % init result
-					for it = 2 : numel(diffGridName)
-						result = result.diff(k, diffGridName{it});
-					end
-				end
-			elseif k == 0
-				result = obj;
-			else
-				result = obj.diff_inner(k, diffGridName);
-			end
+			result = obj.diff_inner(k, diffGridName);
 		end
 		
 		function I = int(obj, varargin)
@@ -2323,8 +2294,8 @@ classdef  (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
 		end
 		
 		function result = diff_inner(obj, k, diffGridName)
-			gridSelector = strcmp(obj(1).gridName, diffGridName);
-			gridSelectionIndex = find(gridSelector);
+			
+			gridSelectionIndex = obj(1).domain.gridIndex(diffGridName);
 
 			spacing = gradient(obj(1).grid{gridSelectionIndex}, 1);
 			assert(numeric.near(spacing, spacing(1)), ...
@@ -2350,9 +2321,9 @@ classdef  (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
 				'name', ['(d_{', diffGridName, '}', obj(1).name, ')']);
 
 			if k > 1
-				% 			% if a higher order derivative is requested, call the function
-				% 			% recursivly until the first-order derivative is reached
-				result = result.diff(k-1, diffGridName);
+				% if a higher order derivative is requested, call the function
+				% recursivly until the first-order derivative is reached
+				result = result.diff(diffGridName, k-1);
 			end
 		end
 		
@@ -2360,13 +2331,18 @@ classdef  (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
 			% Computes the required permutation vectors to use
 			% misc.multArray for multiplication of matrices
 			
-			uA = unique(a(1).gridName, 'stable');
-			assert(numel(uA) == numel(a(1).gridName), 'Gridnames have to be unique!');
-			uB = unique(b(1).gridName, 'stable');
-			assert(numel(uB) == numel(b(1).gridName), 'Gridnames have to be unique!');
+			% #todo this assertion should not be required!
+% 			uA = unique(a(1).gridName, 'stable');
+% 			assert(numel(uA) == numel(a(1).gridName), 'Gridnames have to be unique!');
+% 			uB = unique(b(1).gridName, 'stable');
+% 			assert(numel(uB) == numel(b(1).gridName), 'Gridnames have to be unique!');
 			
 			% 1) find common entries
-			common = intersect(a(1).gridName, b(1).gridName);
+			if isempty( b(1).gridName ) || isempty( a(1).gridName )
+				common = [];
+			else
+				common = intersect(a(1).gridName, b(1).gridName);
+			end
 			
 			commonA = false(1, a.nargin());
 			commonB = false(1, b.nargin());
diff --git a/+quantity/Domain.m b/+quantity/Domain.m
index 5717025..1e10a1a 100644
--- a/+quantity/Domain.m
+++ b/+quantity/Domain.m
@@ -11,7 +11,7 @@ classdef (InferiorClasses = {?quantity.EquidistantDomain}) Domain < ...
 		
 		% a speaking name for this domain; Should be unique, so that the
 		% domain can be identified by the name.
-		name char;
+		name string = "";
 		
 		n (1,1) double {mustBeInteger};		% number of discretization points == gridLength
 	end
@@ -96,7 +96,7 @@ classdef (InferiorClasses = {?quantity.EquidistantDomain}) Domain < ...
 			s = [obj.n];
 		end
 		
-		function d = find(obj, domain, varargin)
+		function d = find(obj, searchName)
 			% FIND a domain in object-array of quantity.Domain
 			%
 			%	d = find(OBJ, NAME) returns the domain with the name NAME
@@ -111,30 +111,56 @@ classdef (InferiorClasses = {?quantity.EquidistantDomain}) Domain < ...
 			%
 			%	d = find(OBJ, { NAME or DOMAIN}) the NAME or the DOMAIN to
 			%	be found can also be defined by cell-array.
-			
-			names = {obj.name};
-			if isa(domain, 'quantity.Domain')
-				searchName = {domain.name};
-			elseif ischar(domain)
-				searchName = {domain};
-			elseif iscell(domain)
-				searchName = domain;
-			else
-				error('Not implemented yet')
+			arguments
+				obj quantity.Domain;
+			end
+			arguments (Repeating)
+				searchName string;
+			end
+						
+			d = obj( obj.gridIndex( searchName ) );
+		end
+		function [idx, log] = gridIndex(obj, searchName, position)
+			%% GRIDINDEX returns the index of the grid
+			% [idx, log] = gridIndex(obj, names) searches in the name
+			% properties of obj for the "names" and returns its index as
+			% "idx" and its logical index as "log"
+			arguments
+				obj
+				searchName = [obj.name];
+				position string = "all";
 			end
 			
-			if numel(searchName) > 1
-				d = obj.find(searchName{:});
-				return
+			if isa(searchName, 'quantity.Domain')
+				searchName = [searchName.name];
 			end
 			
-			d = obj(strcmp(names, searchName));
+			objNames = [obj.name];
+			
+			if isempty(objNames)
+				idx = 0;
+				log = [];
+			else
+				searchName = misc.ensureString( searchName );
+				
+				log = false(size(objNames));
+				counter = 1:numel(objNames);
+				idx = [];
+				for k = 1 : numel(searchName)
+					log_ = objNames == searchName(k);
+					log = log | log_;
+					idx = [idx counter( log_ )];
+				end
+				if isempty(idx)
+					idx = 0;
+				end
+			end
 			
-			for it = 1 : numel(varargin)
-				d = [d, find(obj, varargin{:})];
+			if position == "first"
+				idx = idx(1);
 			end
-		end
-		
+			
+		end % gridIndex		
 		function l = ne(obj, obj2)
 			% ~= Not equal.
 			l = ~(obj == obj2);
@@ -155,27 +181,17 @@ classdef (InferiorClasses = {?quantity.EquidistantDomain}) Domain < ...
 				return;
 			end
 			
-			[joinedGrid, index] = unique({domain1.name, domain2.name}, 'stable');
+			[joinedGrid, index] = unique([domain1.name, domain2.name], 'stable');
 			
 			joinedDomain(1 : numel(joinedGrid)) = quantity.Domain();
 			
-			% #todo@domain: the gird comparison seems to be very
-			% complicated
-			
 			% check for each grid if it is in the domain of obj1 or obj2 or
 			% both
 			for i = 1 : numel(joinedGrid)
-				currentGridName = joinedGrid{i};
-				[index1, logicalIndex1] = domain1.gridIndex(currentGridName);
-				[index2, logicalIndex2] = domain2.gridIndex(currentGridName);
-				
-				%
-				% 				if ~any(logicalIndex1)
-				% 					joinedDomain(i) = obj2(index2);
-				% 				elseif ~any(logicalIndex2)
-				% 					joinedDomain(i) = obj1(index1);
-				% 				else
-				%
+				currentGridName = joinedGrid(i);
+				[index1, logicalIndex1] = domain1.gridIndex(currentGridName, "first");
+				[index2, logicalIndex2] = domain2.gridIndex(currentGridName, "first");
+								
 				% Check if a domain is in both domains:
 				%	-> then take the finer one of both
 				if any(logicalIndex1) && any(logicalIndex2)
@@ -192,7 +208,7 @@ classdef (InferiorClasses = {?quantity.EquidistantDomain}) Domain < ...
 					end
 				% If it is not in both, -> just take the normal grid
 				elseif any(logicalIndex1)
-					joinedDomain(i) = domain1(index1);
+					joinedDomain(i) = domain1(index1(1));
 				elseif any(logicalIndex2)
 					joinedDomain(i) = domain2(index2);
 				end
@@ -204,41 +220,7 @@ classdef (InferiorClasses = {?quantity.EquidistantDomain}) Domain < ...
 			[joinedDomain, index] = obj1.join(obj2);
 		end % gridJoin()
 				
-		function [idx, logicalIdx] = gridIndex(obj, names)
-			%% GRIDINDEX returns the index of the grid
-			% [idx, log] = gridIndex(obj, names) searches in the name
-			% properties of obj for the "names" and returns its index as
-			% "idx" and its logical index as "log"
-			arguments
-				obj
-				names = {obj.name};
-			end
-			
-			if isa(names, 'quantity.Domain')
-				names = {names.name};
-			end
-			
-			names = misc.ensureIsCell(names);
-			
-			idx = zeros(1, length(names));
-			nArgIdx = 1:obj.ndims();
-			
-			logicalIdx = false(1, obj.ndims());
-			
-			for k = 1:length(names)
-				log = strcmp({obj.name}, names{k});
-				logicalIdx = logicalIdx | log;
-				if any(log)
-					% #todo@domain: if the index for a grid name is searched in a
-					% list with multiple grids but same names, only the first
-					% occurrence is returned. this should be changed...
-					tmpFirst = nArgIdx(log);
-					idx(k) = tmpFirst(1);
-				else
-					idx(k) = 0;
-				end
-			end
-		end % gridIndex
+
 		
 		function i = isempty(obj)
 			i = any(size(obj) == 0);
@@ -269,14 +251,14 @@ classdef (InferiorClasses = {?quantity.EquidistantDomain}) Domain < ...
 		function [idx, newDomain] = getPermutationIdx(obj, order)
 			
 			if isa(order, 'quantity.Domain')
-				names = {order.name};
-			elseif ischar([order{:}])
-				names = order;
+				names = [order.name];
+			elseif iscell(order) || ischar(order) || isstring(order)
+				names = misc.ensureString( order );
 			else
-				error('the input parameter order must be a array of quantity.Domain objects or a cell-array with string')
+				error('the input parameter order must be a array of quantity.Domain objects or a string-array')
 			end
 						
-			idx = cellfun(@(v) obj.gridIndex(v), names);
+			idx = cellfun(@(v) obj.gridIndex(v), names); % #todo@domainNameString
 			
 			if isa(order, 'quantity.Domain')
 				newDomain = order;
@@ -302,7 +284,7 @@ classdef (InferiorClasses = {?quantity.EquidistantDomain}) Domain < ...
 			
 			% only sort the grids if there is something to sort
 			if obj.ndims > 1
-				gridNames = {obj.name};
+				gridNames = [obj.name];
 				
 				% this is the default case for ascending alphabetical
 				% order
@@ -404,7 +386,7 @@ classdef (InferiorClasses = {?quantity.EquidistantDomain}) Domain < ...
 			%% domain parser
 			domainParser = misc.Parser();
 			domainParser.addParameter('domain', {}, @(g) isa(g, 'quantity.Domain'));
-			domainParser.addParameter('gridName', '', @(g) ischar(g) || iscell(g));
+			domainParser.addParameter('gridName', '');
 			domainParser.addParameter('grid', [], @(g) isnumeric(g) || iscell(g));
 			domainParser.parse(varargin{:});
 
@@ -418,7 +400,7 @@ classdef (InferiorClasses = {?quantity.EquidistantDomain}) Domain < ...
 				%	-> initialize quantity.Domain objects with the
 				%	specified values
 
-				myGridName = misc.ensureIsCell(domainParser.Results.gridName);
+				myGridName = misc.ensureString(domainParser.Results.gridName);
 				myGrid = misc.ensureIsCell(domainParser.Results.grid);
 
 				assert(isequal(numel(myGrid), numel(myGridName)), ...
@@ -427,7 +409,7 @@ classdef (InferiorClasses = {?quantity.EquidistantDomain}) Domain < ...
 				% initialize the domain objects
 				myDomain = quantity.Domain.empty();
 				for k = 1:numel(myGrid)
-					myDomain(k) = quantity.Domain(myGridName{k}, myGrid{k});
+					myDomain(k) = quantity.Domain(myGridName(k), myGrid{k});
 				end
 			else
 				% else case: the domains are specified as domain
@@ -435,7 +417,7 @@ classdef (InferiorClasses = {?quantity.EquidistantDomain}) Domain < ...
 				myDomain = domainParser.Results.domain;
 			end	
 			
-			assert(numel(myDomain) == numel(unique({myDomain.name})), ...
+			assert(misc.isunique([myDomain.name]), ...
 				'The names of the domain must be unique');
 			
 			unmatched = domainParser.UnmatchedNameValuePair;
diff --git a/+quantity/Piecewise.m b/+quantity/Piecewise.m
index 4f2844d..adfb612 100644
--- a/+quantity/Piecewise.m
+++ b/+quantity/Piecewise.m
@@ -31,21 +31,21 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Piecewise < quantity.Discrete
 
 				% ensure all have the same domain
 				d = quantities{1}(1).domain;
-				assert( all( cellfun(@(q) all( strcmp( {d.name}, {q(1).domain.name} ) ), quantities) ) , ...
+				assert( all( cellfun(@(q) all( strcmp( [d.name], [q(1).domain.name] ) ), quantities) ) , ...
 					'The quantities for the piecewise combination must have the same domain names' );
 				assert(length(quantities) >= 2, 'Only one quantity is given for the piecewise combination. At least 2 are required.');
 
 				assert( quantities{1}(1).domain.gridIndex(domainToJoin) == 1, ...
 					'The domain to join must be the first domain!');
 
-				joinedGrid = quantities{1}(1).domain.find(domainToJoin).grid;
+				joinedGrid = quantities{1}(1).domain.find(domainToJoin.name).grid;
 				joinedValues = quantities{1}.on();
 
 				% ensure the domains fit to each other and then concatenate
 				% them
 				for k = 2:length(quantities)
-					dkm1 = quantities{k-1}(1).domain.find(domainToJoin);
-					dk = quantities{k}(1).domain.find(domainToJoin);
+					dkm1 = quantities{k-1}(1).domain.find(domainToJoin.name);
+					dk = quantities{k}(1).domain.find(domainToJoin.name);
 
 					assert(dkm1.upper == dk.lower, 'Domains do not connect to each other');
 
diff --git a/+quantity/Symbolic.m b/+quantity/Symbolic.m
index db27771..ae435a7 100644
--- a/+quantity/Symbolic.m
+++ b/+quantity/Symbolic.m
@@ -70,10 +70,10 @@ classdef Symbolic < quantity.Function
 					% variable
 					if isa(fun{k}, 'sym')
 						symb{k} = fun{k};
-						fun{k} = quantity.Symbolic.setValueContinuous(symb{k}, {myDomain.name});
+						fun{k} = quantity.Symbolic.setValueContinuous(symb{k}, [myDomain.name]);
 					elseif isa(fun{k}, 'double')
 						symb{k} = sym(fun{k});
-						fun{k} = quantity.Symbolic.setValueContinuous(symb{k}, {myDomain.name});						
+						fun{k} = quantity.Symbolic.setValueContinuous(symb{k}, [myDomain.name]);						
 					elseif isa(fun{k}, 'function_handle')
 						symb{k} = sym(fun{k});
 					else
@@ -299,10 +299,10 @@ classdef Symbolic < quantity.Function
 				else
 					gridName = {gridName.name};
 				end
-			else
-				gridName = misc.ensureIsCell(gridName);
 			end
 			
+			gridName = misc.ensureString(gridName);
+			
 			if nargin == 3 && isa(values, 'quantity.Domain')
 				% replacement of the grid AND the gridName
 				% 1) replace the grid
@@ -314,14 +314,6 @@ classdef Symbolic < quantity.Function
 				values = misc.ensureIsCell(values);
 			end
 			
-% 			% ensure that domains which should be replaced are known by the
-% 			% object
-% 			for k = 1:length(values)
-% 				if ischar(values{k})
-% 					assert( any( strcmp( obj(1).gridName, values{k} ) ), 'The domain name to be replaced must be a domain name of the object' );
-% 				end
-% 			end
-			
 			isNumericValue = cellfun(@isnumeric, values);
 			if any((cellfun(@(v) numel(v(:)), values)>1) & isNumericValue)
 				error('only implemented for one value per grid');
@@ -344,13 +336,13 @@ classdef Symbolic < quantity.Function
  				for it = 1 : numel(values)
  					if ~isNumericValue(it) && ~isempty(obj(1).gridName(~selectRemainingGrid)) 
 						% check if there is a symbolic value and if this value exists in the object
-						if ischar(values{it})
-							newGridName{strcmp(obj(1).gridName(~selectRemainingGrid), gridName{it})} ...
+						if isstring( values{it} ) || ischar( values{it} )
+							newGridName( strcmp(obj(1).gridName(~selectRemainingGrid), gridName(it)) ) ...
 								= values{it};
 						elseif isa(values{it}, 'sym')
 							gridNameTemp = symvar(values{it});
 							assert(numel(gridNameTemp) == 1, 'replacing one gridName with 2 gridName is not supported');
-							newGridName{strcmp(obj(1).gridName(~selectRemainingGrid), gridName{it})} ...
+							newGridName{strcmp(obj(1).gridName(~selectRemainingGrid), gridName(it))} ...
 								= char(gridNameTemp);
 							
 						else
@@ -359,7 +351,7 @@ classdef Symbolic < quantity.Function
  					end
 				end
 								
-				symbolicSolution = subs(obj.sym(), gridName, values);				
+				symbolicSolution = subs(obj.sym(), cellstr(gridName), values);				
 				
 				if isempty(symvar(symbolicSolution(:)))
 					% take the new values that are not numeric as the new
@@ -374,7 +366,7 @@ classdef Symbolic < quantity.Function
 					end
 					for it = 1 : numel(newGridName)
 						if ~isempty(charValues) && any(contains(charValues, newGridName{it}))
-							newGrid{it} = obj.gridOf(gridName{strcmp(values, newGridName{it})});
+							newGrid{it} = obj.gridOf(gridName( strcmp(values, newGridName{it}) ));
 						else
 							newGrid{it} = obj.gridOf(newGridName{it});
 						end
@@ -709,11 +701,8 @@ classdef Symbolic < quantity.Function
 			%  from a to b."
 			
 			if nargin == 2
-				if ~iscell(z)
-					z = {z};
-				end
 				
-				grdIdx = strcmp(obj(1).gridName, z);
+				grdIdx = obj(1).domain.gridIndex(z);
 				a = obj(1).grid{grdIdx}(1);
 				b = obj(1).grid{grdIdx}(end);
 			end
@@ -949,7 +938,11 @@ classdef Symbolic < quantity.Function
 					fDouble = double(f);
 					f = @(varargin) fDouble + quantity.Function.zero(varargin{:});
 				else
-					f = matlabFunction(f, 'Vars', symVar );
+					if iscell( symVar )
+						symVar = [symVar{:}];
+					end
+						
+					f = matlabFunction(f, 'Vars', convertStringsToChars( symVar ) );
 				end
 			end
 		end % setValueContinuous()
diff --git a/+unittests/+misc/testMisc.m b/+unittests/+misc/testMisc.m
index 009f05b..c8677b5 100644
--- a/+unittests/+misc/testMisc.m
+++ b/+unittests/+misc/testMisc.m
@@ -4,6 +4,18 @@ function [tests] = testMisc()
 tests = functiontests(localfunctions());
 end
 
+function testEnsureString(testCase)
+
+a = "a";
+b = 'b';
+
+testCase.verifyEqual( misc.ensureString(a), a)
+testCase.verifyEqual( misc.ensureString(b), string(b))
+testCase.verifyEqual( misc.ensureString({a, b}), [a, string(b)])
+testCase.verifyEqual( misc.ensureString({b, b}), [string(b), string(b)])
+
+end
+
 function testEyeNd(tc)
 n = 2;
 tc.verifyEqual(misc.eyeNd([n, n]), eye(n));
diff --git a/+unittests/+quantity/testDiscrete.m b/+unittests/+quantity/testDiscrete.m
index 2a45b97..7cbe9f6 100644
--- a/+unittests/+quantity/testDiscrete.m
+++ b/+unittests/+quantity/testDiscrete.m
@@ -1,14 +1,27 @@
-
 function [tests] = testDiscrete()
 %testQuantity Summary of this function goes here
 %   Detailed explanation goes here
 tests = functiontests(localfunctions);
 end
 
+
+function setupOnce(testCase)
+syms z zeta t sy
+testCase.TestData.sym.z = z;
+testCase.TestData.sym.zeta = zeta;
+testCase.TestData.sym.t = t;
+testCase.TestData.sym.sy = sy;
+end
+
 function testL2Norm(tc)
+
+Z = tc.TestData.sym.z;
+T = tc.TestData.sym.t;
+ZETA = tc.TestData.sym.zeta;
+
 t = quantity.Domain('t', linspace(0, 2, 101));
 z = quantity.Domain('z', linspace(0, 1, 51));
-x = quantity.Symbolic([sym('z') * sym('t'); sym('t')], 'domain', [z, t]);
+x = quantity.Symbolic([Z * T; T], 'domain', [z, t]);
 
 xNorm = sqrt(int(x.' * x, 'z'));
 tc.verifyEqual(MAX(abs(xNorm - x.l2norm('z'))), 0, 'AbsTol', 1e-12);
@@ -105,9 +118,6 @@ tc.verifyEqual(q1V , q2V')
 end % testSort
 
 function testBlkdiag(tc)
-% init some data
-syms z zeta
-
 z = quantity.Domain('z', linspace(0, 1, 21));
 zeta = quantity.Domain('zeta', linspace(0, 1, 41));
 
@@ -149,7 +159,9 @@ tc.verifyEqual(blub(2).name, 'asdf');
 end
 
 function testCtranspose(tc)
-syms z zeta
+z = tc.TestData.sym.z;
+zeta = tc.TestData.sym.zeta;
+
 qSymbolic = quantity.Symbolic(...
 	[1+z*zeta, -zeta; -z, z^2], 'grid', {linspace(0, 1, 21), linspace(0, 1, 41)},...
 	'gridName', {'z', 'zeta'}, 'name', 'q');
@@ -168,8 +180,9 @@ tc.verifyEqual(qDiscrete2.imag.on(), -qDiscrete2Ctransp.imag.on());
 end % testCtranspose
 
 function testTranspose(tc)
+z = tc.TestData.sym.z;
+zeta = tc.TestData.sym.zeta;
 
-syms z zeta
 qSymbolic = quantity.Symbolic(...
 	[1+z*zeta, -zeta; -z, z^2], 'grid', {linspace(0, 1, 21), linspace(0, 1, 41)},...
 	'gridName', {'z', 'zeta'}, 'name', 'q');
@@ -183,7 +196,9 @@ tc.verifyEqual(qDiscrete(2,1).on(), qDiscreteTransp(1,2).on());
 end % testTranspose
 
 function testFlipGrid(tc)
-syms z zeta
+z = tc.TestData.sym.z;
+zeta = tc.TestData.sym.zeta;
+
 myGrid = linspace(0, 1, 11);
 f = quantity.Discrete(quantity.Symbolic([1+z+zeta; 2*zeta+sin(z)] + zeros(2, 1)*z*zeta, ...
 	'gridName', {'z', 'zeta'}, 'grid', {myGrid, myGrid}));
@@ -398,7 +413,8 @@ end
 
 function testDiag2Vec(testCase)
 % quantity.Symbolic
-syms z
+z = testCase.TestData.sym.z;
+
 do = quantity.Domain('z', linspace(0,1,3));
 myMatrixSymbolic = quantity.Symbolic([sin(0.5*z*pi)+1, 0; 0, 0.9-z/2], 'domain', do);
 myVectorSymbolic = diag2vec(myMatrixSymbolic);
@@ -463,7 +479,9 @@ testCase.verifyEqual(solution.on(), referenceResult1 + referenceResult2, 'AbsTol
 end
 
 function testSolveDVariableEqualQuantityNegative(testCase)
-syms z zeta
+z = testCase.TestData.sym.z;
+zeta = testCase.TestData.sym.zeta;
+
 assume(z>0 & z<1); assume(zeta>0 & zeta<1);
 myParameterGrid = linspace(0, 0.1, 5);
 Lambda = quantity.Symbolic(-0.1-z^2, ...%, -1.2+z^2]),...1+z*sin(z)
@@ -482,7 +500,8 @@ end
 
 function testSolveDVariableEqualQuantityComparedToSym(testCase)
 %% compare with symbolic implementation
-syms z
+z = testCase.TestData.sym.z;
+
 assume(z>0 & z<1);
 quanBSym = quantity.Symbolic(1+z, 'grid', {linspace(0, 1, 5)}, ...
 	'gridName', 'z', 'name', 'bSym', 'gridName', {'z'});
@@ -496,7 +515,8 @@ end
 
 function testSolveDVariableEqualQuantityAbsolut(testCase)
 %% compare with symbolic implementation
-syms z
+z = testCase.TestData.sym.z;
+
 assume(z>0 & z<1);
 quanBSym = quantity.Symbolic(1+z, 'grid', {linspace(0, 1, 11)}, ...
 	'gridName', 'z', 'name', 'bSym', 'gridName', {'z'});
@@ -505,7 +525,7 @@ quanBDiscrete = quantity.Discrete(quanBSym.on(), 'grid', {linspace(0, 1, 11)}, .
 
 solutionBDiscrete = quanBDiscrete.solveDVariableEqualQuantity();
 myGrid = solutionBDiscrete.grid{1};
-solutionBDiscreteDiff = solutionBDiscrete.diff(1, 's');
+solutionBDiscreteDiff = solutionBDiscrete.diff('s');
 quanOfSolutionOfS = zeros(length(myGrid), length(myGrid), 1);
 for icIdx = 1 : length(myGrid)
 	quanOfSolutionOfS(:, icIdx, :) = quanBSym.on(solutionBDiscrete.on({myGrid, myGrid(icIdx)}));
@@ -523,7 +543,8 @@ b = quantity.Discrete(ones(5, 1), 'grid', linspace(0, 1, 5), 'gridName', 'z', ..
 	'size', [1, 1], 'name', 'b');
 ab  = a*b;
 %
-syms z
+z = testCase.TestData.sym.z;
+
 c = quantity.Symbolic(1, 'grid', linspace(0, 1, 21), 'gridName', 'z', 'name', 'c');
 ac = a*c;
 
@@ -547,10 +568,8 @@ sinfun = quantity.Discrete(sin(z), 'grid', z, 'gridName', 'z');
 % very bad a the boundarys of the domain.
 Z = linspace(0.1, pi-0.1)';
 testCase.verifyTrue(numeric.near(sinfun.diff().on(Z), cos(Z), 1e-3));
-testCase.verifyTrue(numeric.near(sinfun.diff(2).on(Z), -sin(Z), 1e-3));
-testCase.verifyTrue(numeric.near(sinfun.diff(3).on(Z), -cos(Z), 1e-3));
-
-
+testCase.verifyTrue(numeric.near(sinfun.diff('z', 2).on(Z), -sin(Z), 1e-3));
+testCase.verifyTrue(numeric.near(sinfun.diff('z', 3).on(Z), -cos(Z), 1e-3));
 
 end
 
@@ -560,27 +579,26 @@ function testDiffConstant2d(testCase)
 myQuantity = quantity.Discrete(cat(3, 2*ones(11, 21), zNdgrid, zetaNdgrid), ...
 	'grid', {linspace(0, 1, 11), linspace(0, 1, 21)}, ...
 	'gridName', {'z', 'zeta'}, 'name', 'constant', 'size', [3, 1]);
-myQuantityDz = diff(myQuantity, 1, 'z');
-myQuantityDzeta = diff(myQuantity, 1, 'zeta');
-myQuantityDZzeta = diff(myQuantity, 1);
-myQuantityDZzeta2 = diff(myQuantity, 1, {'z', 'zeta'});
+myQuantityDz = diff(myQuantity, 'z', 1);
+myQuantityDzeta = diff(myQuantity, 'zeta', 1);
 
-testCase.verifyEqual(myQuantityDZzeta.on(), myQuantityDZzeta2.on());
+testCase.verifyError( @() diff(myQuantity), 'MATLAB:functionValidation:NotScalar' )
+testCase.verifyError( @() diff(myQuantity, 1, {'z', 'zeta'}), 'MATLAB:functionValidation:ClassConversionError' )
+testCase.verifyError( @() diff(myQuantity,  {'z', 'zeta'}), 'MATLAB:functionValidation:NotScalar' )
 
 % constant
 testCase.verifyEqual(myQuantityDz(1).on(), zeros(11, 21));
 testCase.verifyEqual(myQuantityDzeta(1).on(), zeros(11, 21));
-testCase.verifyEqual(myQuantityDZzeta(1).on(), zeros(11, 21));
+
 
 % zNdgrid
 testCase.verifyEqual(myQuantityDz(2).on(), ones(11, 21), 'AbsTol', 10*eps);
 testCase.verifyEqual(myQuantityDzeta(2).on(), zeros(11, 21), 'AbsTol', 10*eps);
-testCase.verifyEqual(myQuantityDZzeta(2).on(), zeros(11, 21), 'AbsTol', 10*eps);
 
 % zetaNdgrid
 testCase.verifyEqual(myQuantityDz(3).on(), zeros(11, 21), 'AbsTol', 10*eps);
 testCase.verifyEqual(myQuantityDzeta(3).on(), ones(11, 21), 'AbsTol', 10*eps);
-testCase.verifyEqual(myQuantityDZzeta(3).on(), zeros(11, 21), 'AbsTol', 10*eps);
+
 end
 
 function testOn(testCase)
@@ -669,7 +687,7 @@ zeta11 = quantity.Domain('zeta', z11_);
 a = quantity.Discrete(ones([z11.n, z11.n, 2, 2]), 'size', [2, 2], ...
 	'domain', [z11, zeta11], 'name', 'A');
 
-syms zeta
+zeta = testCase.TestData.sym.zeta;
 z10_ = linspace(0, 1, 10);
 
 b = quantity.Symbolic((eye(2, 2)), 'gridName', 'zeta', ...
@@ -683,7 +701,9 @@ end
 
 function testMTimesPointWise(tc)
 
-syms z zeta
+z = tc.TestData.sym.z;
+zeta = tc.TestData.sym.zeta;
+
 Z = linspace(0, pi, 51)';
 ZETA = linspace(0, pi / 2, 71)';
 
@@ -785,7 +805,8 @@ tGrid = linspace(pi, 1.1*pi, 51)';
 s = tGrid;
 [T, S] = ndgrid(tGrid, tGrid);
 
-syms sy t
+t = testCase.TestData.sym.t;
+sy = testCase.TestData.sym.sy;
 
 a = [ 1, sy; t, 1];
 b = [ sy; 2*sy];
@@ -842,7 +863,10 @@ testCase.verifyEqual( f.on(f(1).grid, f(1).gridName), V.on(f(1).grid, f(1).gridN
 tGrid = linspace(pi, 1.1*pi, 51)';
 s = tGrid;
 [T, S] = ndgrid(tGrid, tGrid);
-syms sy tt
+
+sy = testCase.TestData.sym.sy;
+t = testCase.TestData.sym.t;
+
 a = [ 1, sy; t, 1];
 
 A = zeros([size(T), size(a)]);
@@ -1287,12 +1311,12 @@ testCase.verifyEqual(quan10, shiftdim(quan.on({1, 0})));
 testCase.verifyEqual(quan01, shiftdim(quan.on({0, 1})));
 testCase.verifyEqual(quanZetaZ.on(), quan.on());
 testCase.verifyEqual(quant1.on(), squeeze(quan.on({quan(1).grid{1}, 1})));
-testCase.verifyEqual(quanZetaZ(1).gridName, {'zeta', 'z'})
-testCase.verifyEqual(quant1(1).gridName, {'t'})
+testCase.verifyEqual(quanZetaZ(1).gridName, ["zeta", "z"])
+testCase.verifyEqual(quant1(1).gridName, ["t"])
 
 quanZetaZetaReference = misc.diagNd(quan.on({linspace(0, 1, 41), linspace(0, 1, 41)}), [1, 2]);
 testCase.verifyEqual(quanZetaZeta.on(), quanZetaZetaReference);
-testCase.verifyEqual(quanEta(1).gridName, {'eta', 'zeta'})
+testCase.verifyEqual(quanEta(1).gridName, ["eta", "zeta"])
 testCase.verifyEqual(quanPt.on(), shiftdim(quan.on({1, quan(1).grid{2}})));
 
 myQuantity = quanZetaZeta.subs(quantity.Domain('zeta', linspace(0,1,3)));
diff --git a/+unittests/+quantity/testDomain.m b/+unittests/+quantity/testDomain.m
index 7fff801..444efef 100644
--- a/+unittests/+quantity/testDomain.m
+++ b/+unittests/+quantity/testDomain.m
@@ -29,9 +29,9 @@ d = testCase.TestData.d;
 testCase.verifyEqual( d.find('a'), a)
 testCase.verifyEqual( d.find('b', 'c'), [b c])
 testCase.verifyEqual( d.find({'b', 'c'}), [b c])
-testCase.verifyEqual( d.find(b), b);
-testCase.verifyEqual( d.find({a c}), [a c])
-testCase.verifyEqual( d.find([a b]), [a b])
+testCase.verifyEqual( d.find(b.name), b);
+testCase.verifyEqual( d.find({a.name c.name}), [a c])
+testCase.verifyEqual( d.find([a.name b.name]), [a b])
 
 end
 
@@ -45,7 +45,7 @@ c = quantity.Domain('c', z);
 d = [a b c];
 
 testCase.verifyEqual(d.find('a'), a);
-testCase.verifyEqual(d.find(b), b);
+testCase.verifyEqual(d.find(b.name), b);
 testCase.verifyEqual(d.find('c'), c);
 
 end
@@ -88,7 +88,7 @@ d = [a b c];
 [d__, I__] = d.sort('ascend');
 d___ = d.sort();
 
-testCase.verifyEqual({d_.name}, {'c', 'b', 'a'});
+testCase.verifyEqual([d_.name], ["c", "b", "a"]);
 testCase.verifyEqual({d__.name}, {d.name});
 testCase.verifyEqual({d__.name}, {d___.name});
 testCase.verifyEqual( I_, flip(I__) );
@@ -168,16 +168,22 @@ joinedDomainCC = sort( gridJoin(c, c) );
 joinedDomainBC = sort( gridJoin(b, c) );
 joinedDomain = sort( gridJoin(Z, [Z, T]) );
 
-testCase.verifyEqual({joinedDomainAB.name}, {'p', 's', 't', 'z'});
+testCase.verifyEqual([joinedDomainAB.name], ["p", "s", "t", "z"]);
 testCase.verifyEqual({joinedDomainAB.grid}, {s(:), s(:), t(:), z(:)});
-testCase.verifyEqual({joinedDomainCC.name}, {'p'});
+testCase.verifyEqual(joinedDomainCC.name, "p");
 testCase.verifyEqual({joinedDomainCC.grid}, {t(:)});
-testCase.verifyEqual({joinedDomainBC.name}, {'p', 's'});
+testCase.verifyEqual([joinedDomainBC.name], ["p", "s"]);
 testCase.verifyEqual({joinedDomainBC.grid}, {s(:), t(:)});
 testCase.verifyEqual({joinedDomain.grid}, {t(:), z(:)});
+
+d1 = [Z Z T];
+d2 = quantity.Domain.empty;
+
+testCase.verifyEqual( d1.join( d2 ), [Z T] )
+
 end
 
-function testGridIndex(testCase)
+function testFind_Index(testCase)
 z = linspace(0, 2*pi, 71)';
 t = linspace(0, 3*pi, 51);
 s = linspace(0, 1);
diff --git a/+unittests/+quantity/testSymbolic.m b/+unittests/+quantity/testSymbolic.m
index 9631375..8a0e2ae 100644
--- a/+unittests/+quantity/testSymbolic.m
+++ b/+unittests/+quantity/testSymbolic.m
@@ -140,13 +140,8 @@ fdz = quantity.Symbolic([zeta, 1; 0, 0], ...
 fdzeta = quantity.Symbolic([z, 0; 1, 0], ...
 	'gridName', {'z', 'zeta'}, 'grid', {myGrid, myGrid});
 
-fRefTotal = 0*f.on();
-fRefTotal(:,:,1,1) = 1;
-testCase.verifyEqual(on(diff(f)), fRefTotal);
-testCase.verifyEqual(on(diff(f, 1, {'z', 'zeta'})), fRefTotal);
-testCase.verifyEqual(on(diff(f, 2, {'z', 'zeta'})), 0*fRefTotal);
-testCase.verifyEqual(on(diff(f, 1, 'z')), fdz.on());
-testCase.verifyEqual(on(diff(f, 1, 'zeta')), fdzeta.on());
+testCase.verifyEqual(on(diff(f, 'z')), fdz.on());
+testCase.verifyEqual(on(diff(f, 'zeta')), fdzeta.on());
 
 end
 
@@ -483,11 +478,10 @@ f2 = cosh(z * pi);
 f = quantity.Symbolic([f1 ; f2 ], 'name', 'f', 'domain', ...
 	quantity.Domain('z', linspace(0,1,11)));
 
-d2f = f.diff(2);
-d1f = f.diff(1);
+d2f = f.diff("z", 2);
+d1f = f.diff("z", 1);
 
 %%
-
 F1 = symfun([f1; f2], z);
 D1F = symfun([diff(f1,1); diff(f2,1)], z);
 D2F = symfun([diff(f1,2); diff(f2,2)], z);
@@ -500,8 +494,8 @@ R3 = D2F(z);
 
 %%
 verifyTrue(testCase, numeric.near(double([R1{:}]), f.on(), 1e-12));
-verifyTrue(testCase, numeric.near(double([R2{:}]), f.diff(1).on(), 1e-12));
-verifyTrue(testCase, numeric.near(double([R3{:}]), f.diff(2).on(), 1e-12));
+verifyTrue(testCase, numeric.near(double([R2{:}]), f.diff('z', 1).on(), 1e-12));
+verifyTrue(testCase, numeric.near(double([R3{:}]), f.diff('z', 2).on(), 1e-12));
 
 end
 
@@ -683,7 +677,7 @@ Q_var = quantity.Symbolic(z, 'domain', quantity.Domain('z', 1:2));
 
 testCase.verifyError(...
 	@() quantity.Symbolic(z, 'domain', quantity.Domain.empty()), ...
-	'quantity:Symbolic:Initialisation' );
+	'symbolic:sym:matlabFunction:InvalidVars' );
 
 testCase.verifyTrue(Q_constant.isConstant);
 testCase.verifyFalse(Q_var.isConstant);
@@ -809,16 +803,16 @@ assume(z>0 & z<1); assume(zeta>0 & zeta<1);
 F = quantity.Symbolic(zeros(1), 'grid', ...
 	{linspace(0, 1, 3), linspace(0, 1, 3)}, 'gridName', {'z', 'zeta'});
 Feta = F.subs('z', 'eta');
-testCase.verifyEqual(Feta(1).gridName, {'eta', 'zeta'});
+testCase.verifyEqual(Feta(1).gridName, ["eta", "zeta"]);
 
 %%
 fMessy = quantity.Symbolic(x^1*y^2*z^4*w^5, 'domain', [X, Y, Z, W]);
 fMessyA = fMessy.subs({'x', 'y', 'z', 'w'}, {'a', 'a', 'a', 'a'});
 fMessyYY = fMessy.subs({'w', 'x', 'z'}, {'xi', 'y', 'y'});
 
-testCase.verifyEqual(fMessyA.gridName, {'a'});
+testCase.verifyEqual(fMessyA.gridName, "a");
 testCase.verifyEqual(fMessyA.grid, {linspace(0, 1, 11)'});
-testCase.verifyEqual(fMessyYY.gridName, {'y', 'xi'});
+testCase.verifyEqual(fMessyYY.gridName, ["y", "xi"]);
 testCase.verifyEqual(fMessyYY.grid, {linspace(0, 1, 11)', linspace(0, 1, 3)'});
 % % sub multiple numerics -> not implemented yet
 % f11 = f.subs('x', [1; 2]);
-- 
GitLab