Index: /issm/trunk-jpl/test/NightlyRun/runme.py
===================================================================
--- /issm/trunk-jpl/test/NightlyRun/runme.py	(revision 13107)
+++ /issm/trunk-jpl/test/NightlyRun/runme.py	(revision 13108)
@@ -142,15 +142,17 @@
 			if strcmpi(procedure,'update'):
 
-				if not strcmp(socket.gethostname().lower().split('.')[0],'larsen'):
-#					raise RuntimeError("Nightly run archives must be saved on 'larsen' (hostname is '"+socket.gethostname()+"').")
-					print "Nightly run archives must be saved on 'larsen' (hostname is '"+socket.gethostname()+"')."
-#				f = h5py.File(os.path.join('..','Archives',archive_name+'.hdf5'),'w')
-				f = netCDF4.Dataset(os.path.join('..','Archives',archive_name+'.nc'),'w')
+				os.remove(os.path.join('..','Archives',archive_name+'.nc'))
+				f = netCDF4.Dataset(os.path.join('..','Archives',archive_name+'.nc'),'w',format='NETCDF3_CLASSIC')
 				for k,fieldname in enumerate(field_names):
 					field=numpy.array(field_values[k],dtype=float)
-#					f.create_dataset(archive_name+'_field'+str(k),data=field)
-					f.createDimension(archive_name+'_field'+str(k)+'_0',numpy.size(field,0))
-					f.createDimension(archive_name+'_field'+str(k)+'_1',numpy.size(field,1))
-					v = f.createVariable(archive_name+'_field'+str(k),'f8',(archive_name+'_field'+str(k)+'_0',archive_name+'_field'+str(k)+'_1'))
+					if len(field.shape) == 1:
+						if numpy.size(field):
+							field=field.reshape(numpy.size(field),1)
+						else:
+							field=field.reshape(0,0)
+					# Matlab uses base 1, so use base 1 in labels
+					f.createDimension(archive_name+'_field'+str(k+1)+'_1',numpy.size(field,0))
+					f.createDimension(archive_name+'_field'+str(k+1)+'_2',numpy.size(field,1))
+					v = f.createVariable(archive_name+'_field'+str(k+1),field.dtype,(archive_name+'_field'+str(k+1)+'_1',archive_name+'_field'+str(k+1)+'_2'))
 					v[:] = field
 				f.close()
@@ -162,5 +164,4 @@
 				#load archive
 				if os.path.exists(os.path.join('..','Archives',archive_name+'.nc')):
-#					f = h5py.File(os.path.join('..','Archives',archive_name+'.hdf5'),'r')
 					f = netCDF4.Dataset(os.path.join('..','Archives',archive_name+'.nc'),'r')
 				else:
@@ -171,23 +172,23 @@
 					try:
 						#Get field and tolerance
-						field=numpy.array(field_values[k],dtype=float)
-#						print 'field =',field
+						field=numpy.array(field_values[k])
+						if len(field.shape) == 1:
+							if numpy.size(field):
+								field=field.reshape(numpy.size(field),1)
+							else:
+								field=field.reshape(0,0)
 						tolerance=field_tolerances[k]
-#						print 'tolerance =',tolerance
 
 						#compare to archive
-#						if archive_name+'_field'+str(k) in f:
-#							archive=f[archive_name+'_field'+str(k)][...]
-						if archive_name+'_field'+str(k) in f.variables:
-							archive=f.variables[archive_name+'_field'+str(k)][:]
-						else:
-							raise NameError("Field name '"+archive_name+'_field'+str(k)+"' does not exist in archive file.")
-#						print 'archive =',archive
-						error_diff=numpy.amax(numpy.abs(archive-field),axis=1)/ \
-								   (numpy.amax(numpy.abs(archive),axis=1)+sys.float_info.epsilon)
-#						print 'error_diff =',error_diff
+						# Matlab uses base 1, so use base 1 in labels
+						if archive_name+'_field'+str(k+1) in f.variables:
+							archive=f.variables[archive_name+'_field'+str(k+1)][:]
+						else:
+							raise NameError("Field name '"+archive_name+'_field'+str(k+1)+"' does not exist in archive file.")
+						error_diff=numpy.amax(numpy.abs(archive-field),axis=0)/ \
+								   (numpy.amax(numpy.abs(archive),axis=0)+sys.float_info.epsilon)
 
 						#disp test result
-						if (error_diff>tolerance):
+						if (numpy.any(error_diff>tolerance)):
 							print 'ERROR   difference: %-7.2g > %7.2g test id: %i test name: %s field: %s' % \
 								(error_diff,tolerance,id,id_string,fieldname)
@@ -202,5 +203,5 @@
 						message=me2
 						if   strcmpi(output,'nightly'):
-							fid=open(os.path.join(ISSM_DIR,'nightlylog','matlaberror.log'), 'a')
+							fid=open(os.path.join(ISSM_DIR,'nightlylog','pythonerror.log'), 'a')
 							fid.write('%s' % message)
 							fid.write('\n------------------------------------------------------------------\n')
@@ -208,5 +209,5 @@
 							print 'FAILURE difference: N/A test id: %i test name: %s field: %s' % (id,id_string,fieldname)
 						elif strcmpi(output,'daily'):
-							fid=open(os.path.join(ISSM_DIR,'dailylog','matlaberror.log'), 'a')
+							fid=open(os.path.join(ISSM_DIR,'dailylog','pythonerror.log'), 'a')
 							fid.write('%s' % message)
 							fid.write('\n------------------------------------------------------------------\n')
@@ -225,5 +226,5 @@
 			message=me
 			if   strcmpi(output,'nightly'):
-				fid=open(os.path.join(ISSM_DIR+'nightlylog','matlaberror.log'), 'a')
+				fid=open(os.path.join(ISSM_DIR+'nightlylog','pythonerror.log'), 'a')
 				fid.write('%s' % message)
 				fid.write('\n------------------------------------------------------------------\n')
@@ -231,5 +232,5 @@
 				print 'FAILURE difference: N/A test id: %i test name: %s field: %s' % (id,id_string,'N/A')
 			elif strcmpi(output,'daily'):
-				fid=open(os.path.join(ISSM_DIR+'dailylog','matlaberror.log'), 'a')
+				fid=open(os.path.join(ISSM_DIR+'dailylog','pythonerror.log'), 'a')
 				fid.write('%s' % message)
 				fid.write('\n------------------------------------------------------------------\n')
Index: /issm/trunk-jpl/test/NightlyRun/runme2.m
===================================================================
--- /issm/trunk-jpl/test/NightlyRun/runme2.m	(revision 13108)
+++ /issm/trunk-jpl/test/NightlyRun/runme2.m	(revision 13108)
@@ -0,0 +1,213 @@
+function varargout=runme(varargin)
+%RUNME - test deck for ISSM nightly runs
+%
+%   In a test deck directory (tests/Vertification/NightlyRun for example)
+%   The following command will launch all the existing tests:
+%   >> runme
+%   To run the tests 101 and 102:
+%   >> runme('id',[101 102])
+%   etc...
+%
+%   Available options:
+%      'id'            followed by the list of ids requested
+%      'exclude'       ids to be excluded from the test
+%      'benchmark'     'nightly' (nightly run/ daily run)
+%                      'ismip'  : validation of ismip-hom tests
+%                      'eismint': validation of eismint tests
+%                      'thermal': validation of thermal tests
+%                      'mesh'   : validation of mesh tests
+%                      ...
+%      'procedure'     'check' : run the test (default)
+%                      'update': update the archive
+%                      'model' : prepare the model but no test is run
+%
+%   Usage:
+%      md=runme(varargin);
+%
+%   Examples:
+%      runme;
+%      runme('exclude',101);
+%      md=runme('id',102,'procedure','model');
+
+%Get ISSM_DIR variable
+ISSM_DIR=issmdir();
+
+%Check inputs
+% {{{1
+if nargout>1
+	help runme
+	error('runme error message: bad usage');
+end
+
+%recover options
+options=pairoptions(varargin{:});
+% }}}
+
+%Process options
+%GET benchmark {{{1
+benchmark=getfieldvalue(options,'benchmark','nightly');
+if ~ismember(benchmark,{'all','nightly','ismip','eismint','thermal','mesh','validation','tranforcing'})
+	disp('runme warning: benchmark not supported, defaulting to test ''nightly''')
+	benchmark='nightly';
+end
+% }}}
+%GET procedure {{{1
+procedure=getfieldvalue(options,'procedure','check');
+if ~ismember(procedure,{'check','update'})
+	disp('runme warning: procedure not supported, defaulting to test ''check''')
+	procedure='check';
+end
+% }}}
+%GET output {{{1
+output=getfieldvalue(options,'output','none');
+if ~ismember(output,{'nightly','daily','none'})
+	disp('runme warning: output not supported, defaulting to test ''none''')
+	output='none';
+end
+% }}}
+%GET RANK and NUMPROCS for mutlithreaded runs  {{{1
+rank=getfieldvalue(options,'rank',1);
+numprocs=getfieldvalue(options,'numprocs',1);
+if (numprocs<rank), numprocs=1; end
+% }}}
+%GET ids  {{{1
+flist=dir;%use dir, as it seems to act OS independent
+list_ids=[];
+for i=1:numel(flist),
+	if ( strncmp(flist(i).name,'test',4) &...                         %File name must start with 'test'
+			strncmp(fliplr(flist(i).name),fliplr('.m'),2)&...           %File name must end by '.m'
+			~strcmp(flist(i).name,'test.m'))                            %File name must be different than 'test.m'
+		list_ids(end+1)=eval(flist(i).name(5:end-2));                  %Keep test id only (skip 'test' and '.m')
+	end
+end
+[i1,i2]=parallelrange(rank,numprocs,length(list_ids));               %Get tests for this cpu only
+list_ids=list_ids(i1:i2);
+
+test_ids=getfieldvalue(options,'id',list_ids);
+test_ids=intersect(test_ids,list_ids);
+% }}}
+%GET exclude {{{1
+exclude_ids=getfieldvalue(options,'exclude',[]);
+exclude_ids=[exclude_ids];
+pos=find(ismember(test_ids,exclude_ids));
+test_ids(pos)=[];
+% }}}
+%Process Ids according to benchmarks{{{1
+if strcmpi(benchmark,'nightly'),
+	test_ids=intersect(test_ids,[1:999]);
+elseif strcmpi(benchmark,'ismip'),
+	test_ids=intersect(test_ids,[1101:1199]);
+elseif strcmpi(benchmark,'eismint'),
+	test_ids=intersect(test_ids,[1201:1299]);
+elseif strcmpi(benchmark,'thermal'),
+	test_ids=intersect(test_ids,[1301:1399]);
+elseif strcmpi(benchmark,'mesh'),
+	test_ids=intersect(test_ids,[1401:1499]);
+elseif strcmpi(benchmark,'validation'),
+	test_ids=intersect(test_ids,[1001:1999]);
+elseif strcmpi(benchmark,'tranforcing'),
+	test_ids=intersect(test_ids,[1501:1502]);
+end
+% }}}
+
+%Loop over tests and launch sequence
+root=pwd;
+for id=test_ids,
+	try,
+
+		%Execute test
+		eval(['cd ' root ]);
+		id_string=IdToName(id);
+		eval(['test' num2str(id)]);
+
+		%UPDATE ARCHIVE?
+		archive_name=['Archive' num2str(id) ];
+		if strcmpi(procedure,'update'),
+			delete(['../Archives/' archive_name '.nc'])
+			for k=1:length(field_names),
+				field=field_values{k};
+				% matlab writes the dimensions reversed and matrices transposed into netcdf, so compensate for that
+				nccreate(['../Archives/' archive_name '.nc'],[archive_name '_field' num2str(k)],...
+				         'Dimensions',{[archive_name '_field' num2str(k) '_2'] size(field,2) [archive_name '_field' num2str(k) '_1'] size(field,1)},...
+				         'Format','classic');
+				ncwrite(['../Archives/' archive_name '.nc'],[archive_name '_field' num2str(k)],transpose(field));
+			end
+			disp(sprintf(['File ./../Archives/' archive_name '.nc saved\n']));
+
+		%ELSE: CHECK TEST
+		else,
+			for k=1:length(field_names),
+
+				try,
+					%Get field and tolerance
+					field=field_values{k};
+					fieldname=field_names{k};
+					tolerance=field_tolerances{k};
+
+					%compare to archive
+					% matlab reads the dimensions reversed and matrices transposed from netcdf, so compensate for that
+					archive=transpose(ncread(['../Archives/' archive_name '.nc'],[archive_name '_field' num2str(k)]));
+					error_diff=full(max(abs(archive(:)-field(:)))/(max(abs(archive))+eps));
+
+					%disp test result
+					if (error_diff>tolerance);
+						disp(sprintf(['ERROR   difference: %-7.2g > %7.2g test id: %i test name: %s field: %s'],...
+							error_diff,tolerance,id,id_string,fieldname));
+					else
+						disp(sprintf(['SUCCESS difference: %-7.2g < %7.2g test id: %i test name: %s field: %s'],...
+							error_diff,tolerance,id,id_string,fieldname));
+					end
+
+				catch me2
+
+					%something went wrong, print failure message:
+					directory=strsplit(pwd,'/');
+					message=getReport(me2);
+					if strcmpi(output,'nightly')
+						fid=fopen([ISSM_DIR '/nightlylog/matlaberror.log'], 'at');
+						fprintf(fid,'%s',message);
+						fprintf(fid,'\n------------------------------------------------------------------\n');
+						fclose(fid);
+						disp(sprintf(['FAILURE difference: N/A test id: %i test name: %s field: %s'],id,id_string,fieldname));
+					elseif strcmpi(output,'daily');
+						fid=fopen([ISSM_DIR '/dailylog/matlaberror.log'], 'at');
+						fprintf(fid,'%s',message);
+						fprintf(fid,'\n------------------------------------------------------------------\n');
+						fclose(fid);
+						disp(sprintf(['FAILURE difference: N/A test id: %i test name: %s field: %s'],id,id_string,fieldname));
+					else
+						disp(sprintf(['FAILURE difference: N/A test id: %i test name: %s field: %s'],id,id_string,fieldname));
+						rethrow(me2);
+					end
+				end
+			end
+		end
+
+	catch me,
+
+		%something went wrong, print failure message:
+		directory=strsplit(pwd,'/');
+		message=getReport(me);
+		if strcmpi(output,'nightly')
+			fid=fopen([ISSM_DIR '/nightlylog/matlaberror.log'], 'at');
+			fprintf(fid,'%s',message);
+			fprintf(fid,'\n------------------------------------------------------------------\n');
+			fclose(fid);
+			disp(sprintf(['FAILURE difference: N/A test id: %i test name: %s field: %s'],id,id_string,'N/A'));
+		elseif strcmpi(output,'daily');
+			fid=fopen([ISSM_DIR '/dailylog/matlaberror.log'], 'at');
+			fprintf(fid,'%s',message);
+			fprintf(fid,'\n------------------------------------------------------------------\n');
+			fclose(fid);
+			disp(sprintf(['FAILURE difference: N/A test id: %i test name: %s field: %s'],id,id_string,'N/A'));
+		else
+			disp(sprintf(['FAILURE difference: N/A test id: %i test name: %s field: %s'],id,id_string,'N/A'));
+			rethrow(me);
+		end
+	end
+end
+
+%output md if requested
+if nargout==1
+	varargout{1}=md;
+end
Index: /issm/trunk-jpl/test/NightlyRun/test101.py
===================================================================
--- /issm/trunk-jpl/test/NightlyRun/test101.py	(revision 13107)
+++ /issm/trunk-jpl/test/NightlyRun/test101.py	(revision 13108)
@@ -23,10 +23,10 @@
 	1e-13,1e-13,1e-13]
 field_values=[\
-	[md.results.DiagnosticSolution.Vx],\
-	[md.results.DiagnosticSolution.Vy],\
-	[md.results.DiagnosticSolution.Vel],\
-	[md.results.DiagnosticSolution.Pressure],\
-	[md.results.DiagnosticSolution.StressTensorxx],\
-	[md.results.DiagnosticSolution.StressTensoryy],\
-	[md.results.DiagnosticSolution.StressTensorxy],\
+	md.results['DiagnosticSolution'][1]['Vx'],\
+	md.results['DiagnosticSolution'][1]['Vy'],\
+	md.results['DiagnosticSolution'][1]['Vel'],\
+	md.results['DiagnosticSolution'][1]['Pressure'],\
+	md.results['DiagnosticSolution'][1]['StressTensorxx'],\
+	md.results['DiagnosticSolution'][1]['StressTensoryy'],\
+	md.results['DiagnosticSolution'][1]['StressTensorxy'],\
 	]
