Index: /issm/trunk-jpl/src/m/classes/clusters/acenet.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/acenet.m	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/acenet.m	(revision 26332)
@@ -7,164 +7,164 @@
 
 classdef acenet
-    properties (SetAccess=public) 
-		 % {{{
-		 %name='glacdyn.ace-net.ca'
-		 name='placentia.ace-net.ca'
-		 %name='brasdor.ace-net.ca'
-		 login='klemorza';
-		 np=10;
-		 port=0;
-		 queue='longq';
-		 time=10;
-		 % codepath='/usr/local/issm-r11321/bin'; % this one is for issm on acenet global
-		 codepath='/home/klemorza/issm/trunk-jpl/bin'; % this one is for issm on my acenet directory
-		 %executionpath='/home/klemorza/issm/trunk-jpl/execution';
-		 %executionpath='/home/klemorza/scratch/issmres.dir';
-		 executionpath='/net/glacdyn-data/glacdyn/1/klemorza/issm.dir';                 
-		 %}}}
-	 end
-	 methods
-		 function cluster=acenet(varargin) % {{{
-			 %use provided options to change fields
-			 options=pairoptions(varargin{:});
-			 %initialize cluster using user settings if provided
-			 if (exist([cluster.name '_settings'])==2), eval([cluster.name '_settings']); end
+	properties (SetAccess=public)
+		% {{{
+		%name='glacdyn.ace-net.ca'
+		name='placentia.ace-net.ca'
+		%name='brasdor.ace-net.ca'
+		login='klemorza';
+		np=10;
+		port=0;
+		queue='longq';
+		time=10;
+		% codepath='/usr/local/issm-r11321/bin'; % this one is for issm on acenet global
+		codepath='/home/klemorza/issm/trunk-jpl/bin'; % this one is for issm on my acenet directory
+		%executionpath='/home/klemorza/issm/trunk-jpl/execution';
+		%executionpath='/home/klemorza/scratch/issmres.dir';
+		executionpath='/net/glacdyn-data/glacdyn/1/klemorza/issm.dir';
+		%}}}
+	end
+	methods
+		function cluster=acenet(varargin) % {{{
+			%use provided options to change fields
+			options=pairoptions(varargin{:});
+			%initialize cluster using user settings if provided
+			if (exist([cluster.name '_settings'])==2), eval([cluster.name '_settings']); end
 
-			 %OK get other fields
-			 cluster=AssignObjectFields(pairoptions(varargin{:}),cluster);
-		 end
-		 %}}} 
-		 function disp(cluster) % {{{
-			 %  display the object
-			 disp(sprintf('class ''%s'' object ''%s'' = ',class(cluster),inputname(1)));
-			 disp(sprintf('    name: %s',cluster.name));
-			 disp(sprintf('    login: %s',cluster.login));
-			 disp(sprintf('    np: %i',cluster.np));
-			 disp(sprintf('    port: %i',cluster.port));
-			 disp(sprintf('    queue: %s',cluster.queue));
-			 disp(sprintf('    time: %i',cluster.time));
-			 disp(sprintf('    codepath: %s',cluster.codepath));
-			 disp(sprintf('    executionpath: %s',cluster.executionpath));
-                 end
-		 %}}}
-		 function md = checkconsistency(cluster,md,solution,analyses) % {{{
+			%OK get other fields
+			cluster=AssignObjectFields(pairoptions(varargin{:}),cluster);
+		end
+		%}}} 
+		function disp(cluster) % {{{
+			% display the object
+			disp(sprintf('class ''%s'' object ''%s'' = ',class(cluster),inputname(1)));
+			disp(sprintf('    name: %s',cluster.name));
+			disp(sprintf('    login: %s',cluster.login));
+			disp(sprintf('    np: %i',cluster.np));
+			disp(sprintf('    port: %i',cluster.port));
+			disp(sprintf('    queue: %s',cluster.queue));
+			disp(sprintf('    time: %i',cluster.time));
+			disp(sprintf('    codepath: %s',cluster.codepath));
+			disp(sprintf('    executionpath: %s',cluster.executionpath));
+		end
+		%}}}
+		function md = checkconsistency(cluster,md,solution,analyses) % {{{
 
-			 available_queues={'debug','shortq','longq'};
-			 queue_requirements_time=[48*1 48*7 48*15];
-			 queue_requirements_np=[32 128 256];
-			 QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.np,cluster.time)
-		 end
-		 %}}}
-		 function BuildQueueScript(cluster,dirname,modelname,solution,io_gather,isvalgrind,isgprof,isdakota,isoceancoupling) % {{{
+			available_queues={'debug','shortq','longq'};
+			queue_requirements_time=[48*1 48*7 48*15];
+			queue_requirements_np=[32 128 256];
+			QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.np,cluster.time)
+		end
+		%}}}
+		function BuildQueueScript(cluster,dirname,modelname,solution,io_gather,isvalgrind,isgprof,isdakota,isoceancoupling) % {{{
 
-			 if(isvalgrind), disp('valgrind not supported by cluster, ignoring...'); end
-			 if(isgprof),    disp('gprof not supported by cluster, ignoring...'); end
+			if(isvalgrind), disp('valgrind not supported by cluster, ignoring...'); end
+			if(isgprof),    disp('gprof not supported by cluster, ignoring...'); end
 
-			 %write queuing script 
-			 fid=fopen([modelname '.queue'],'w');
-			 fprintf(fid,'#!/bin/bash\n');
-			 fprintf(fid,'#$ -cwd\n');
+			%write queuing script 
+			fid=fopen([modelname '.queue'],'w');
+			fprintf(fid,'#!/bin/bash\n');
+			fprintf(fid,'#$ -cwd\n');
 
-                         fprintf(fid,'#$ -N issm\n');
-                         % fprintf(fid,'#$ -l h_rt=00:15:00\n');
-                         % fprintf(fid,'#$ -l h_rt=5:00:0\n');
-                         % fprintf(fid,'#$ -l h_rt=25:00:0\n');
-                         % fprintf(fid,'#$ -l h_rt=47:59:00\n');
-                         % fprintf(fid,'#$ -l h_rt=72:00:0\n');
-                         % fprintf(fid,'#$ -l h_rt=96:00:0\n');
-                         % fprintf(fid,'#$ -l h_rt=336:00:0\n');
-                         tstr = sprintf('#$ -l h_rt=%i:00:00\n',cluster.time);
-                         fprintf(fid,tstr);
+			fprintf(fid,'#$ -N issm\n');
+			% fprintf(fid,'#$ -l h_rt=00:15:00\n');
+			% fprintf(fid,'#$ -l h_rt=5:00:0\n');
+			% fprintf(fid,'#$ -l h_rt=25:00:0\n');
+			% fprintf(fid,'#$ -l h_rt=47:59:00\n');
+			% fprintf(fid,'#$ -l h_rt=72:00:0\n');
+			% fprintf(fid,'#$ -l h_rt=96:00:0\n');
+			% fprintf(fid,'#$ -l h_rt=336:00:0\n');
+			tstr = sprintf('#$ -l h_rt=%i:00:00\n',cluster.time);
+			fprintf(fid,tstr);
 
-                         fprintf(fid,'#$ -l h_vmem=2G\n');
+			fprintf(fid,'#$ -l h_vmem=2G\n');
 
-                         if strcmp(cluster.executionpath,'/home/klemorza/scratch/issmres.dir')
-                             % ---- Which acent queue to use ----
-                             fprintf(fid,'#$ -q short.q@*,medium.q@*\n');
-                             %fprintf(fid,'#$ -q medium.q@*,long.q@*\n');
-                             %fprintf(fid,'#$ -q medium.q@*\n');
-                             %fprintf(fid,'#$ -q short.q@*\n');
-                             % Acenet nodes with 16cpus and more than 60G mem
-                             % fprintf(fid,'#$ -l h=cl001|cl002|cl003|cl004|cl005|cl006|cl007|cl008|cl009|cl010|cl011|cl012|cl021|cl022|cl023|cl024 \n');
-                             % ---- cpus on different nodes ----
-                             if cluster.np==4
-                                 % -------- All cpus in the same node --------          
-                                 fprintf(fid,'#$ -pe openmp %i\n',cluster.np);
-                             else
-                                 fprintf(fid,'#$ -pe ompi %i\n',cluster.np); % To avoid green acenet that does not have InfiniBand
-                             end
-                         
-                         elseif strcmp(cluster.executionpath,'/net/glacdyn-data/glacdyn/1/klemorza/issm.dir')
-                             % ---- Which node for Lev's queue are selected ----
-                             fprintf(fid,'#$ -q tarasov.q\n');
-                             fprintf(fid,'#$ -l h=cl27*|cl28*|cl29*|cl30*|cl31*|cl320|cl267|cl268|cl269|cl338 \n');
-                             %fprintf(fid,'#$ -l h=cl27*|cl28*|cl29*|cl30*|cl31*|cl320|cl267|cl268|cl269 \n');
-                             %fprintf(fid,'#$ -l h=cl0* \n');
-                             % fprintf(fid,'#$ -l h=cl338 \n');
-                             
-                             if cluster.np==4
-                                 % -------- All cpus in the same node --------          
-                                 fprintf(fid,'#$ -pe openmp %i\n',cluster.np);
-                             else
-                                 fprintf(fid,'#$ -pe ompi* %i\n',cluster.np);
-                                 %fprintf(fid,'#$ -pe 4per %i\n',cluster.np);
-                                 %fprintf(fid,'#$ -pe 8per %i\n',cluster.np);
-                             end
-                         end
-                                                  
-                         % ---- misc ----
-                         fprintf(fid,'#$ -j y\n');
-                         
-                         fprintf(fid,'module purge\n');
-                         %fprintf(fid,'module load gcc openmpi/gcc\n');
-                         %fprintf(fid,'module unload openmpi\n');
-                         fprintf(fid,'module load intel/12.1.7.367\n');
-                         fprintf(fid,'module load openmpi/intel/1.2.9\n');
+			if strcmp(cluster.executionpath,'/home/klemorza/scratch/issmres.dir')
+				% ---- Which acent queue to use ----
+				fprintf(fid,'#$ -q short.q@*,medium.q@*\n');
+				%fprintf(fid,'#$ -q medium.q@*,long.q@*\n');
+				%fprintf(fid,'#$ -q medium.q@*\n');
+				%fprintf(fid,'#$ -q short.q@*\n');
+				% Acenet nodes with 16cpus and more than 60G mem
+				% fprintf(fid,'#$ -l h=cl001|cl002|cl003|cl004|cl005|cl006|cl007|cl008|cl009|cl010|cl011|cl012|cl021|cl022|cl023|cl024 \n');
+				% ---- cpus on different nodes ----
+				if cluster.np==4
+					% -------- All cpus in the same node --------          
+					fprintf(fid,'#$ -pe openmp %i\n',cluster.np);
+				else
+					fprintf(fid,'#$ -pe ompi %i\n',cluster.np); % To avoid green acenet that does not have InfiniBand
+				end
 
-                         fprintf(fid,'module load gsl\n');
-                         %fprintf(fid,'module load issm\n');
-                         fprintf(fid,'export ISSM_DIR="%s/../"\n',cluster.codepath); %FIXME
-                         fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n');       %FIXME
-                         fprintf(fid,'\n');
-                         fprintf(fid,'mpiexec %s/issm.exe %s %s %s 2> %s.errlog >%s.outlog\n',...
-                                 cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname,modelname,modelname);
-                         %fprintf(fid,'echo $HOSTNAME >>%s.outlog',modelname);
-			 fclose(fid);
+			elseif strcmp(cluster.executionpath,'/net/glacdyn-data/glacdyn/1/klemorza/issm.dir')
+				% ---- Which node for Lev's queue are selected ----
+				fprintf(fid,'#$ -q tarasov.q\n');
+				fprintf(fid,'#$ -l h=cl27*|cl28*|cl29*|cl30*|cl31*|cl320|cl267|cl268|cl269|cl338 \n');
+				%fprintf(fid,'#$ -l h=cl27*|cl28*|cl29*|cl30*|cl31*|cl320|cl267|cl268|cl269 \n');
+				%fprintf(fid,'#$ -l h=cl0* \n');
+				% fprintf(fid,'#$ -l h=cl338 \n');
+				
+				if cluster.np==4
+					% -------- All cpus in the same node --------          
+					fprintf(fid,'#$ -pe openmp %i\n',cluster.np);
+				else
+					fprintf(fid,'#$ -pe ompi* %i\n',cluster.np);
+					%fprintf(fid,'#$ -pe 4per %i\n',cluster.np);
+					%fprintf(fid,'#$ -pe 8per %i\n',cluster.np);
+				end
+			end
+						
+			% ---- misc ----
+			fprintf(fid,'#$ -j y\n');
+			
+			fprintf(fid,'module purge\n');
+			%fprintf(fid,'module load gcc openmpi/gcc\n');
+			%fprintf(fid,'module unload openmpi\n');
+			fprintf(fid,'module load intel/12.1.7.367\n');
+			fprintf(fid,'module load openmpi/intel/1.2.9\n');
 
-		 end
-		 %}}}
-		 function UploadQueueJob(cluster,modelname,dirname,filelist)% {{{
+			fprintf(fid,'module load gsl\n');
+			%fprintf(fid,'module load issm\n');
+			fprintf(fid,'export ISSM_DIR="%s/../"\n',cluster.codepath); %FIXME
+			fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n');       %FIXME
+			fprintf(fid,'\n');
+			fprintf(fid,'mpiexec %s/issm.exe %s %s %s 2> %s.errlog >%s.outlog\n',...
+					cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname,modelname,modelname);
+			%fprintf(fid,'echo $HOSTNAME >>%s.outlog',modelname);
+			fclose(fid);
 
-			 %compress the files into one zip.
-			 compressstring=['tar -zcf ' dirname '.tar.gz '];
-			 for i=1:numel(filelist),
-				 compressstring = [compressstring ' ' filelist{i}];
-			 end
-			 system(compressstring);
+		end
+		%}}}
+		function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{
 
-			 disp('uploading input file and queueing script');
-			 issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
+			%compress the files into one zip.
+			compressstring=['tar -zcf ' dirname '.tar.gz '];
+			for i=1:numel(filelist),
+				compressstring = [compressstring ' ' filelist{i}];
+			end
+			system(compressstring);
 
-		 end %}}}
+			disp('uploading input file and queueing script');
+			issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
 
-		 function LaunchQueueJob(cluster,modelname,dirname,filelist,restart)% {{{
+		end %}}}
 
-			 disp('launching solution sequence on remote cluster');
-			 if ~isempty(restart)
-				 launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && qsub ' modelname '.queue '];
-			 else
-				 launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ...
-					 ' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz && qsub ' modelname '.queue '];
-			 end
-			 issmssh(cluster.name,cluster.login,cluster.port,launchcommand);
-		 end %}}}
+		function LaunchQueueJob(cluster,modelname,dirname,filelist,restart) % {{{
 
-		 function Download(cluster,dirname,filelist)% {{{
+			disp('launching solution sequence on remote cluster');
+			if ~isempty(restart)
+				launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && qsub ' modelname '.queue '];
+			else
+				launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ...
+					' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz && qsub ' modelname '.queue '];
+			end
+			issmssh(cluster.name,cluster.login,cluster.port,launchcommand);
+		end %}}}
 
-			 %copy files from cluster to current directory
-			 directory=[cluster.executionpath '/' dirname '/'];
-			 issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist);
+		function Download(cluster,dirname,filelist) % {{{
 
-		 end %}}}
+			%copy files from cluster to current directory
+			directory=[cluster.executionpath '/' dirname '/'];
+			issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist);
+
+		end %}}}
 	end
 end
Index: /issm/trunk-jpl/src/m/classes/clusters/aci.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/aci.m	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/aci.m	(revision 26332)
@@ -53,5 +53,5 @@
 			QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.ppn*cluster.nodes,1)
 
-			%Miscelaneous
+			%Miscellaneous
 			if cluster.ppn>20, md = checkmessage(md,'cannot request more that 20 cores per node'); end
 			if isempty(cluster.login), md = checkmessage(md,'login empty'); end
Index: /issm/trunk-jpl/src/m/classes/clusters/aurora.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/aurora.m	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/aurora.m	(revision 26332)
@@ -38,4 +38,6 @@
 			disp(sprintf('    numnodes: %i',cluster.numnodes));
 			disp(sprintf('    cpuspernode: %i',cluster.cpuspernode));
+			disp(sprintf('    np: %i',cluster.nprocs()));
+			disp(sprintf('    modules: %s',strjoin(cluster.modules,', ')));
 			disp(sprintf('    port: %i',cluster.port));
 			disp(sprintf('    queue: %s',cluster.queue));
@@ -43,4 +45,5 @@
 			disp(sprintf('    codepath: %s',cluster.codepath));
 			disp(sprintf('    executionpath: %s',cluster.executionpath));
+			disp(sprintf('    mpipath: %s',cluster.mpipath));
 		end
 		%}}}
Index: /issm/trunk-jpl/src/m/classes/clusters/camhpc.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/camhpc.m	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/camhpc.m	(revision 26332)
@@ -38,8 +38,8 @@
 			disp(sprintf('    name: %s',cluster.name));
 			disp(sprintf('    login: %s',cluster.login));
-			disp(sprintf('    port: %i',cluster.port));
 			disp(sprintf('    numnodes: %i',cluster.numnodes));
 			disp(sprintf('    cpuspernode: %i',cluster.cpuspernode));
-			disp(sprintf('    np: %i',cluster.cpuspernode*cluster.numnodes));
+			disp(sprintf('    np: %i',cluster.nprocs()));
+			disp(sprintf('    port: %i',cluster.port));
 			disp(sprintf('    project: %s',cluster.project));
 			disp(sprintf('    partition: %s',cluster.partition));
@@ -62,7 +62,7 @@
 			queue_requirements_np=[80 80];
 
-			QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.project,cluster.np,1)
+			QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.project,cluster.nprocs(),1)
 
-			%Miscelaneous
+			%Miscellaneous
 			if isempty(cluster.login), md = checkmessage(md,'login empty'); end
 			if isempty(cluster.codepath), md = checkmessage(md,'codepath empty'); end
@@ -92,5 +92,5 @@
 			fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n');       %FIXME
 			fprintf(fid,'cd %s/%s\n\n',cluster.executionpath,dirname);
-			fprintf(fid,'mpirun -np %i %s/issm.exe %s %s %s\n',cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
+			fprintf(fid,'mpirun -np %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
 			if ~io_gather, %concatenate the output files:
 				fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname);
@@ -101,5 +101,5 @@
 			if cluster.interactive,
 				fid=fopen([modelname '.run'],'w');
-				fprintf(fid,'mpirun -np %i %s/issm.exe %s %s %s\n',cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
+				fprintf(fid,'mpirun -np %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
 				if ~io_gather, %concatenate the output files:
 					fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname);
Index: /issm/trunk-jpl/src/m/classes/clusters/castor.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/castor.m	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/castor.m	(revision 26332)
@@ -7,101 +7,101 @@
 
 classdef castor
-    properties (SetAccess=public) 
-		 % {{{
-		 name='castor'
-		 login='username';
-		 np   =128;
-		 port=0;
-		 queue='shortc';
-		 time=180;
-		 codepath='/workp/edw/issm-2.0/bin'
-		 executionpath='/workp/edw/Testing/Execution'
-		 %}}}
-	 end
-	 methods
-		 function cluster=castor(varargin) % {{{
-			 cluster=AssignObjectFields(pairoptions(varargin{:}),cluster);
-		 end
-		 %}}}
-		 function disp(cluster) % {{{
-			 %  display the object
-			 disp(sprintf('class ''%s'' object ''%s'' = ',class(cluster),inputname(1)));
-			 disp(sprintf('    name: %s',cluster.name));
-			 disp(sprintf('    login: %s',cluster.login));
-			 disp(sprintf('    np: %i',cluster.np));
-			 disp(sprintf('    port: %i',cluster.port));
-			 disp(sprintf('    queue: %s',cluster.queue));
-			 disp(sprintf('    time: %i',cluster.time));
-			 disp(sprintf('    codepath: %s',cluster.codepath));
-			 disp(sprintf('    executionpath: %s',cluster.executionpath));
-		 end
-		 %}}}
-		 function md = checkconsistency(cluster,md,solution,analyses) % {{{
+	properties (SetAccess=public)
+		% {{{
+		name='castor'
+		login='username';
+		np=128;
+		port=0;
+		queue='shortc';
+		time=180;
+		codepath='/workp/edw/issm-2.0/bin'
+		executionpath='/workp/edw/Testing/Execution'
+		%}}}
+	end
+	methods
+		function cluster=castor(varargin) % {{{
+			cluster=AssignObjectFields(pairoptions(varargin{:}),cluster);
+		end
+		%}}}
+		function disp(cluster) % {{{
+			%  display the object
+			disp(sprintf('class ''%s'' object ''%s'' = ',class(cluster),inputname(1)));
+			disp(sprintf('    name: %s',cluster.name));
+			disp(sprintf('    login: %s',cluster.login));
+			disp(sprintf('    np: %i',cluster.np));
+			disp(sprintf('    port: %i',cluster.port));
+			disp(sprintf('    queue: %s',cluster.queue));
+			disp(sprintf('    time: %i',cluster.time));
+			disp(sprintf('    codepath: %s',cluster.codepath));
+			disp(sprintf('    executionpath: %s',cluster.executionpath));
+		end
+		%}}}
+		function md = checkconsistency(cluster,md,solution,analyses) % {{{
 
-			 available_queues={'shortc','longc'};
-			 queue_requirements_time=[180 720];
-			 queue_requirements_np=[128 128];
+			available_queues={'shortc','longc'};
+			queue_requirements_time=[180 720];
+			queue_requirements_np=[128 128];
 
-			 QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.np,cluster.time)
-		 end
-		 %}}}
-		 function BuildQueueScript(cluster,dirname,modelname,solution,io_gather,isvalgrind,isgprof,isdakota,isoceancoupling) % {{{
+			QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.np,cluster.time)
+		end
+		%}}}
+		function BuildQueueScript(cluster,dirname,modelname,solution,io_gather,isvalgrind,isgprof,isdakota,isoceancoupling) % {{{
 
-			 if(isvalgrind), disp('valgrind not supported by cluster, ignoring...'); end
-			 if(isgprof),    disp('gprof not supported by cluster, ignoring...'); end
+			if(isvalgrind), disp('valgrind not supported by cluster, ignoring...'); end
+			if(isgprof),    disp('gprof not supported by cluster, ignoring...'); end
 
-			 %write queuing script 
-			 fid=fopen([modelname '.queue'],'w');
-			 fprintf(fid,'#!/bin/sh\n');
-			 fprintf(fid,'#PBS -l walltime=%i\n',cluster.time*60); %walltime is in seconds.
-			 fprintf(fid,'#PBS -N %s\n',modelname);
-			 fprintf(fid,'#PBS -l ncpus=%i\n',cluster.np);
-			 if ~isempty(queue),
-				 fprintf(fid,'#PBS -q %s\n',cluster.queue);
-			 end
-			 fprintf(fid,'#PBS -o %s.outlog \n',modelname);
-			 fprintf(fid,'#PBS -e %s.errlog \n',modelname);
-			 fprintf(fid,'export PBS_O_WORKDIR=%s\n',[cluster.executionpath '/' dirname]);
-			 fprintf(fid,'cd $PBS_O_WORKDIR\n');
-			 fprintf(fid,'export OMP_NUM_THREADS=1\n');
-			 fprintf(fid,'dplace -s1 -c0-%i mpiexec -np %i %s/issm.exe %s %s %s',cluster.np-1,cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
-			 fclose(fid);
+			%write queuing script 
+			fid=fopen([modelname '.queue'],'w');
+			fprintf(fid,'#!/bin/sh\n');
+			fprintf(fid,'#PBS -l walltime=%i\n',cluster.time*60); %walltime is in seconds.
+			fprintf(fid,'#PBS -N %s\n',modelname);
+			fprintf(fid,'#PBS -l ncpus=%i\n',cluster.np);
+			if ~isempty(queue),
+				fprintf(fid,'#PBS -q %s\n',cluster.queue);
+			end
+			fprintf(fid,'#PBS -o %s.outlog \n',modelname);
+			fprintf(fid,'#PBS -e %s.errlog \n',modelname);
+			fprintf(fid,'export PBS_O_WORKDIR=%s\n',[cluster.executionpath '/' dirname]);
+			fprintf(fid,'cd $PBS_O_WORKDIR\n');
+			fprintf(fid,'export OMP_NUM_THREADS=1\n');
+			fprintf(fid,'dplace -s1 -c0-%i mpiexec -np %i %s/issm.exe %s %s %s',cluster.np-1,cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
+			fclose(fid);
 
-		 end
-		 %}}}
-		 function UploadQueueJob(cluster,modelname,dirname,filelist)% {{{
+		end
+		%}}}
+		function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{
 
-			 %compress the files into one zip.
-			 compressstring=['tar -zcf ' dirname '.tar.gz '];
-			 for i=1:numel(filelist),
-				 compressstring = [compressstring ' ' filelist{i}];
-			 end
-			 if cluster.interactive,
-				 compressstring = [compressstring ' ' modelname '.errlog ' modelname '.outlog '];
-			 end
-			 system(compressstring);
+			%compress the files into one zip.
+			compressstring=['tar -zcf ' dirname '.tar.gz '];
+			for i=1:numel(filelist),
+				compressstring = [compressstring ' ' filelist{i}];
+			end
+			if cluster.interactive,
+				compressstring = [compressstring ' ' modelname '.errlog ' modelname '.outlog '];
+			end
+			system(compressstring);
 
-			 disp('uploading input file and queueing script');
-			 issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
+			disp('uploading input file and queueing script');
+			issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
 
-		 end %}}}
-		 function LaunchQueueJob(cluster,modelname,dirname,filelist,restart)% {{{
+		end %}}}
+		function LaunchQueueJob(cluster,modelname,dirname,filelist,restart) % {{{
 
-			 disp('launching solution sequence on remote cluster');
-			 if ~isempty(restart)
-				 launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && qsub ' modelname '.queue '];
-			 else
-				 launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ...
-					 ' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz  && qsub ' modelname '.queue '];
-			 end
-			 issmssh(cluster.name,cluster.login,cluster.port,launchcommand);
-		 end %}}}
-		 function Download(cluster,dirname,filelist)% {{{
+			disp('launching solution sequence on remote cluster');
+			if ~isempty(restart)
+				launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && qsub ' modelname '.queue '];
+			else
+				launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ...
+					' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz  && qsub ' modelname '.queue '];
+			end
+			issmssh(cluster.name,cluster.login,cluster.port,launchcommand);
+		end %}}}
+		function Download(cluster,dirname,filelist) % {{{
 
-			 %copy files from cluster to current directory
-			 directory=[cluster.executionpath '/' dirname '/'];
-			 issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist);
+			%copy files from cluster to current directory
+			directory=[cluster.executionpath '/' dirname '/'];
+			issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist);
 
-		 end %}}}
+		end %}}}
 	end
 end
Index: /issm/trunk-jpl/src/m/classes/clusters/cloud.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/cloud.m	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/cloud.m	(revision 26332)
@@ -6,5 +6,5 @@
 
 classdef cloud
-	properties (SetAccess=public) 
+	properties (SetAccess=public)
 		% {{{
 		name='';
@@ -64,5 +64,5 @@
 		end
 		%}}}
-		function UploadQueueJob(cluster,modelname,dirname,filelist)% {{{
+		function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{
 
 			%compress the files into one zip.
@@ -80,5 +80,5 @@
 
 		end %}}}
-		function LaunchQueueJob(cluster,modelname,dirname,filelist,restart)% {{{
+		function LaunchQueueJob(cluster,modelname,dirname,filelist,restart) % {{{
 
 			if cluster.interactive, 
@@ -101,5 +101,5 @@
 			issmstssh(cluster.name,cluster.login,launchcommand);
 		end %}}}
-		function Download(cluster,dirname,filelist)% {{{
+		function Download(cluster,dirname,filelist) % {{{
 
 			%copy files from cluster to current directory
Index: /issm/trunk-jpl/src/m/classes/clusters/cosmos.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/cosmos.m	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/cosmos.m	(revision 26332)
@@ -7,101 +7,101 @@
 
 classdef cosmos
-    properties (SetAccess=public) 
-		 % {{{
-		 name='cosmos'
-		 login='username';
-		 np=128;
-		 port=0;
-		 queue='shortq';
-		 time=3*60;
-		 codepath='/work00/edw/issm-2.0/bin';
-		 executionpath='/work00/edw/Execution';
-		 %}}}
-	 end
-	 methods
-		 function cluster=cosmos(varargin) % {{{
-			 cluster=AssignObjectFields(pairoptions(varargin{:}),cluster);
-		 end
-		 %}}}
-		 function disp(cluster) % {{{
-			 %  display the object
-			 disp(sprintf('class ''%s'' object ''%s'' = ',class(cluster),inputname(1)));
-			 disp(sprintf('    name: %s',cluster.name));
-			 disp(sprintf('    login: %s',cluster.login));
-			 disp(sprintf('    np: %i',cluster.np));
-			 disp(sprintf('    port: %i',cluster.port));
-			 disp(sprintf('    queue: %s',cluster.queue));
-			 disp(sprintf('    time: %i',cluster.time));
-			 disp(sprintf('    codepath: %s',cluster.codepath));
-			 disp(sprintf('    executionpath: %s',cluster.executionpath));
-		 end
-		 %}}}
-		 function md = checkconsistency(cluster,md,solution,analyses) % {{{
+	properties (SetAccess=public)
+		% {{{
+		name='cosmos'
+		login='username';
+		np=128;
+		port=0;
+		queue='shortq';
+		time=3*60;
+		codepath='/work00/edw/issm-2.0/bin';
+		executionpath='/work00/edw/Execution';
+		%}}}
+	end
+	methods
+		function cluster=cosmos(varargin) % {{{
+			cluster=AssignObjectFields(pairoptions(varargin{:}),cluster);
+		end
+		%}}}
+		function disp(cluster) % {{{
+			%  display the object
+			disp(sprintf('class ''%s'' object ''%s'' = ',class(cluster),inputname(1)));
+			disp(sprintf('    name: %s',cluster.name));
+			disp(sprintf('    login: %s',cluster.login));
+			disp(sprintf('    np: %i',cluster.np));
+			disp(sprintf('    port: %i',cluster.port));
+			disp(sprintf('    queue: %s',cluster.queue));
+			disp(sprintf('    time: %i',cluster.time));
+			disp(sprintf('    codepath: %s',cluster.codepath));
+			disp(sprintf('    executionpath: %s',cluster.executionpath));
+		end
+		%}}}
+		function md = checkconsistency(cluster,md,solution,analyses) % {{{
 
-			 available_queues={'debug','shortq','longq'};
-			 queue_requirements_time=[60*1 60*3 60*17];
-			 queue_requirements_np=[32 128 256];
+			available_queues={'debug','shortq','longq'};
+			queue_requirements_time=[60*1 60*3 60*17];
+			queue_requirements_np=[32 128 256];
 
-			 QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.np,cluster.time)
-		 end
-		 %}}}
-		 function BuildQueueScript(cluster,dirname,modelname,solution,io_gather,isvalgrind,isgprof,isdakota,isoceancoupling) % {{{
+			QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.np,cluster.time)
+		end
+		%}}}
+		function BuildQueueScript(cluster,dirname,modelname,solution,io_gather,isvalgrind,isgprof,isdakota,isoceancoupling) % {{{
 
-			 if(isvalgrind), disp('valgrind not supported by cluster, ignoring...'); end
-			 if(isgprof),    disp('gprof not supported by cluster, ignoring...'); end
+			if(isvalgrind), disp('valgrind not supported by cluster, ignoring...'); end
+			if(isgprof),    disp('gprof not supported by cluster, ignoring...'); end
 
-			 %write queuing script 
-			 fid=fopen([modelname '.queue'],'w');
-			 fprintf(fid,'#!/bin/bash\n');
-			 fprintf(fid,'#PBS -l select=%i:ncpus=1\n',cluster.np);
-			 fprintf(fid,'#PBS -N %s\n',modelname);
-			 fprintf(fid,'#PBS -l walltime=%i\n',time*60); %walltime is in seconds.
-			 fprintf(fid,'#PBS -q %s\n',queue);
-			 fprintf(fid,'#PBS -o %s.outlog \n',modelname);
-			 fprintf(fid,'#PBS -e %s.errlog \n',modelname);
-			 fprintf(fid,'export PBS_O_WORKDIR=%s\n',[cluster.executionpath '/' dirname]);
-			 fprintf(fid,'cd $PBS_O_WORKDIR\n');
-			 fprintf(fid,'export OMP_NUM_THREADS=1\n');
-			 fprintf(fid,'ulimit -s unlimited\n');
-			 fprintf(fid,'ulimit -c 0\n');
-			 fprintf(fid,'/opt/mpich/gm/intel10.1/bin/mpiexec -np %i %s/issm.exe %s %s %s',cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
-			 fclose(fid);
+			%write queuing script
+			fid=fopen([modelname '.queue'],'w');
+			fprintf(fid,'#!/bin/bash\n');
+			fprintf(fid,'#PBS -l select=%i:ncpus=1\n',cluster.np);
+			fprintf(fid,'#PBS -N %s\n',modelname);
+			fprintf(fid,'#PBS -l walltime=%i\n',time*60); %walltime is in seconds.
+			fprintf(fid,'#PBS -q %s\n',queue);
+			fprintf(fid,'#PBS -o %s.outlog \n',modelname);
+			fprintf(fid,'#PBS -e %s.errlog \n',modelname);
+			fprintf(fid,'export PBS_O_WORKDIR=%s\n',[cluster.executionpath '/' dirname]);
+			fprintf(fid,'cd $PBS_O_WORKDIR\n');
+			fprintf(fid,'export OMP_NUM_THREADS=1\n');
+			fprintf(fid,'ulimit -s unlimited\n');
+			fprintf(fid,'ulimit -c 0\n');
+			fprintf(fid,'/opt/mpich/gm/intel10.1/bin/mpiexec -np %i %s/issm.exe %s %s %s',cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
+			fclose(fid);
 
-		 end
-		 %}}}
-		 function UploadQueueJob(cluster,modelname,dirname,filelist)% {{{
+		end
+		%}}}
+		function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{
 
-			 %compress the files into one zip.
-			 compressstring=['tar -zcf ' dirname '.tar.gz '];
-			 for i=1:numel(filelist),
-				 compressstring = [compressstring ' ' filelist{i}];
-			 end
-			 if cluster.interactive,
-				 compressstring = [compressstring ' ' modelname '.errlog ' modelname '.outlog '];
-			 end
-			 system(compressstring);
+			%compress the files into one zip.
+			compressstring=['tar -zcf ' dirname '.tar.gz '];
+			for i=1:numel(filelist),
+				compressstring = [compressstring ' ' filelist{i}];
+			end
+			if cluster.interactive,
+				compressstring = [compressstring ' ' modelname '.errlog ' modelname '.outlog '];
+			end
+			system(compressstring);
 
-			 disp('uploading input file and queueing script');
-			 issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
+			disp('uploading input file and queueing script');
+			issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
 
-		 end %}}}
-		 function LaunchQueueJob(cluster,modelname,dirname,filelist,restart)% {{{
+		end %}}}
+		function LaunchQueueJob(cluster,modelname,dirname,filelist,restart) % {{{
 
-			 disp('launching solution sequence on remote cluster');
-			 if ~isempty(restart)
-				 launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && qsub ' modelname '.queue '];
-			 else
-				 launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ...
-					 ' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz  && qsub ' modelname '.queue '];
-			 end
-			 issmssh(cluster.name,cluster.login,cluster.port,launchcommand);
-		 end %}}}
-		 function Download(cluster,dirname,filelist)% {{{
+			disp('launching solution sequence on remote cluster');
+			if ~isempty(restart)
+				launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && qsub ' modelname '.queue '];
+			else
+				launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ...
+					' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz  && qsub ' modelname '.queue '];
+			end
+			issmssh(cluster.name,cluster.login,cluster.port,launchcommand);
+		end %}}}
+		function Download(cluster,dirname,filelist) % {{{
 
-			 %copy files from cluster to current directory
-			 directory=[cluster.executionpath '/' dirname '/'];
-			 issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist);
+			%copy files from cluster to current directory
+			directory=[cluster.executionpath '/' dirname '/'];
+			issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist);
 
-		 end %}}}
+		end %}}}
 	end
 end
Index: /issm/trunk-jpl/src/m/classes/clusters/cyclone.py
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/cyclone.py	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/cyclone.py	(revision 26332)
@@ -12,14 +12,15 @@
 
 class cyclone(object):
-    """
-    Be aware that this is not a cluster as we usually know them. There is no scheduling and ressources are pretty low.
-    The Computer have 20 cpus and 512Gb of memory used by a number of person so be respectful with your usage.
-    I putted some restrictive upper limits to avoid over - use. (Basile)
+    """CYCLONE cluster class definition
 
-       Usage:
-          cluster = cyclone()
+    Be aware that this is not a cluster as we usually know them. There is no scheduling and resources are pretty low.
+    The computer has 20 CPUs and 512GB of memory used by a number of persons, so be respectful with your usage.
+    I have put some restrictive upper limits in place to avoid overuse. (Basile)
+
+    Usage:
+        cluster = cyclone()
     """
 
-    def __init__(self, *args):    # {{{
+    def __init__(self, *args):  # {{{
         self.name = 'cyclone'
         self.login = ''
@@ -31,16 +32,15 @@
         self.interactive = 0
 
-    #use provided options to change fields
+        # Use provided options to change fields
         options = pairoptions(*args)
 
-    #initialize cluster using user settings if provided
+        # Initialize cluster using user settings if provided
         self = cyclone_settings(self)
-    #OK get other fields
+        # OK get other fields
         self = options.AssignObjectFields(self)
-
     # }}}
 
-    def __repr__(self):    # {{{
-        #  display the object
+    def __repr__(self):  # {{{
+        # Display the object
         s = "class cyclone object:"
         s = "%s\n%s" % (s, fielddisplay(self, 'name', 'name of the cluster'))
@@ -53,6 +53,6 @@
     # }}}
 
-    def checkconsistency(self, md, solution, analyses):    # {{{
-        #Miscelaneous
+    def checkconsistency(self, md, solution, analyses):  # {{{
+        # Miscellaneous
         if not self.login:
             md = md.checkmessage('login empty')
@@ -69,7 +69,7 @@
     # }}}
 
-    def BuildQueueScript(self, dirname, modelname, solution, io_gather, isvalgrind, isgprof, isdakota, isoceancoupling):    # {{{
+    def BuildQueueScript(self, dirname, modelname, solution, io_gather, isvalgrind, isgprof, isdakota, isoceancoupling):  # {{{
         executable = 'issm.exe'
-        #write queuing script
+        # Write queuing script
         fid = open(modelname + '.queue', 'w')
         fid.write('export ISSM_DIR="%s/../ "\n' % self.codepath)
@@ -83,18 +83,16 @@
         fid.write('mpiexec -np %i %s/%s %s %s %s>%s.outlog 2>%s.errlog\n' % (self.np, self.codepath, executable, str(solution), rundir, modelname, runfile, runfile))
         fid.close()
-
     # }}}
-    def UploadQueueJob(self, modelname, dirname, filelist):    # {{{
+    def UploadQueueJob(self, modelname, dirname, filelist):  # {{{
         #compress the files into one zip.
         compressstring = 'tar -zcf %s.tar.gz ' % dirname
         for file in filelist:
-            compressstring += ' %s' % file
+            compressstring += ' {}'.format(file)
         subprocess.call(compressstring, shell=True)
 
         print('uploading input file and queueing script')
         issmscpout(self.name, self.executionpath, self.login, self.port, [dirname + '.tar.gz'])
-
     # }}}
-    def LaunchQueueJob(self, modelname, dirname, filelist, restart, batch):    # {{{
+    def LaunchQueueJob(self, modelname, dirname, filelist, restart, batch):  # {{{
         print('launching solution sequence on remote cluster')
         if restart:
@@ -103,8 +101,7 @@
             launchcommand = 'cd %s && rm -rf ./%s && mkdir %s && cd %s && mv ../%s.tar.gz ./ && tar -zxf %s.tar.gz  && chmod +x ./%s.queue && ./%s.queue' % (self.executionpath, dirname, dirname, dirname, dirname, dirname, modelname, modelname)
         issmssh(self.name, self.login, self.port, launchcommand)
-
     # }}}
-    def Download(self, dirname, filelist):    # {{{
-        #copy files from cluster to current directory
+    def Download(self, dirname, filelist):  # {{{
+        # Copy files from cluster to current directory
         directory = '%s/%s/' % (self.executionpath, dirname)
         issmscpin(self.name, self.login, self.port, directory, filelist)
Index: /issm/trunk-jpl/src/m/classes/clusters/discover.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/discover.m	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/discover.m	(revision 26332)
@@ -11,7 +11,7 @@
 		name=oshostname();
 		login='';
-		modules        = {};
+		modules={'comp/intel/20.0.0.166' 'mpi/sgi-mpt/2.17' 'cmake/3.17.0'};
 		numnodes=20;
-		cpuspernode=8; 
+		cpuspernode=8;
 		port=0;
 		queue='general';
@@ -20,4 +20,5 @@
 		codepath='';
 		executionpath='';
+		grouplist='';
 		interactive=0;
 		bbftp=0;
@@ -43,14 +44,18 @@
 			disp(sprintf('    login: %s',cluster.login));
 			disp(sprintf('    modules: %s',strjoin(cluster.modules,', ')));
-			disp(sprintf('    port: %i',cluster.port));
 			disp(sprintf('    numnodes: %i',cluster.numnodes));
 			disp(sprintf('    cpuspernode: %i',cluster.cpuspernode));
-			disp(sprintf('    np: %i',cluster.cpuspernode*cluster.numnodes));
+			disp(sprintf('    np: %i',cluster.nprocs()));
+			disp(sprintf('    port: %i',cluster.port));
 			disp(sprintf('    queue: %s',cluster.queue));
 			disp(sprintf('    time: %i',cluster.time));
 			disp(sprintf('    processor: %s',cluster.processor));
+			disp(sprintf('    srcpath: %s',cluster.srcpath));
 			disp(sprintf('    codepath: %s',cluster.codepath));
 			disp(sprintf('    executionpath: %s',cluster.executionpath));
+			disp(sprintf('    grouplist: %s',cluster.grouplist));
 			disp(sprintf('    interactive: %i',cluster.interactive));
+			disp(sprintf('    bbftp: %s',cluster.bbftp));
+			disp(sprintf('    numstreams: %s',cluster.numstreams));
 			disp(sprintf('    hyperthreading: %i',cluster.hyperthreading));
 			disp(sprintf('    email: %s',cluster.email));
@@ -68,5 +73,5 @@
 			queue_requirements_np=[560 6000 532];
 
-			QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.np,cluster.time)
+			QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.nprocs(),cluster.time)
 
 			%now, check cluster.cpuspernode according to processor type
@@ -83,5 +88,5 @@
 			end
 
-			%Miscelaneous
+			%Miscellaneous
 			if isempty(cluster.login), md = checkmessage(md,'login empty'); end
 			if isempty(cluster.codepath), md = checkmessage(md,'codepath empty'); end
@@ -113,11 +118,8 @@
 			fprintf(fid,'#SBATCH -o %s.outlog \n',modelname);
 			fprintf(fid,'#SBATCH -e %s.errlog \n',modelname);
-			fprintf(fid,'#SBATCH -n %i \n',cluster.numnodes*cluster.cpuspernode);
+			fprintf(fid,'#SBATCH -n %i \n',cluster.nprocs());
 			fprintf(fid,'#SBATCH -N %i \n',cluster.numnodes);
 			fprintf(fid,'#SBATCH -t %02i:%02i:00 \n',floor(cluster.time/3600),floor(mod(cluster.time,3600)/60));
-			fprintf(fid,'#SBATCH -A s1690 \n\n');
-			for i=1:numel(cluster.modules),
-				fprintf(fid,['module load ' cluster.modules{i} '\n']);
-			end
+			fprintf(fid,'#SBATCH -A %s \n\n',cluster.grouplist);
 			if length(find(cluster.email=='@'))>0
 				fprintf(fid,'#SBATCH --mail-user=%s \n',cluster.email);
@@ -125,7 +127,7 @@
 			end
 			fprintf(fid,'. /usr/share/modules/init/bash\n\n');
-			fprintf(fid,'module load comp/intel/20.0.0.166\n');
-			fprintf(fid,'module load mpi/sgi-mpt/2.17\n');
-			fprintf(fid,'module load cmake/3.17.0\n');
+			for i=1:numel(cluster.modules),
+				fprintf(fid,['module load ' cluster.modules{i} '\n']);
+			end
 			fprintf(fid,'export MPI_GROUP_MAX=64\n\n');
 			fprintf(fid,'export MPI_UNBUFFERED_STDIO=true\n\n');
@@ -135,5 +137,5 @@
 			fprintf(fid,'cd %s/%s\n\n',cluster.executionpath,dirname);
 
-			fprintf(fid,'mpiexec -np %i %s/%s %s %s %s\n',cluster.np,cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname);
+			fprintf(fid,'mpiexec -np %i %s/%s %s %s/%s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,cluster.executionpath,dirname,modelname);
 			if ~io_gather, %concatenate the output files:
 				fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname);
@@ -145,7 +147,7 @@
 				fid=fopen([modelname '.run'],'w');
 				if ~isvalgrind,
-					fprintf(fid,'mpiexec -np %i %s/%s %s %s %s\n',cluster.np,cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname);
+					fprintf(fid,'mpiexec -np %i %s/%s %s %s/%s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,cluster.executionpath,dirname,modelname);
 				else
-					fprintf(fid,'mpiexec -np %i valgrind --leak-check=full %s/%s %s %s %s\n',cluster.np,cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname);
+					fprintf(fid,'mpiexec -np %i valgrind --leak-check=full %s/%s %s %s/%s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,cluster.executionpath,dirname,modelname);
 				end
 				if ~io_gather, %concatenate the output files:
@@ -153,7 +155,7 @@
 				end
 				fclose(fid);
-				fid=fopen([modelname '.errlog'],'w');
+				fid=fopen([modelname '.errlog'],'w'); % TODO: Change this to system call (touch <file>)?
 				fclose(fid);
-				fid=fopen([modelname '.outlog'],'w');
+				fid=fopen([modelname '.outlog'],'w'); % TODO: Change this to system call (touch <file>)?
 				fclose(fid);
 			end
@@ -162,5 +164,5 @@
 
 			%compress the files into one zip.
-			compressstring=['tar -zcf ' dirname '.tar.gz '];
+			compressstring=['tar -zcf ' dirname '.tar.gz'];
 			for i=1:numel(filelist),
 				compressstring = [compressstring ' ' filelist{i}];
@@ -178,8 +180,8 @@
 			end
 
-			if ~cluster.bbftp,
+			if cluster.bbftp,
+				issmbbftpout(cluster.name,directory,cluster.login,cluster.port,cluster.numstreams,{[dirname '.tar.gz']});
+			else
 				issmscpout(cluster.name,directory,cluster.login,cluster.port,{[dirname '.tar.gz']});
-			else
-				issmbbftpout(cluster.name,directory,cluster.login,cluster.port,cluster.numstreams,{[dirname '.tar.gz']});
 			end
 
@@ -188,5 +190,11 @@
 		function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{
 
-			if ~cluster.interactive, 
+			if cluster.interactive,
+				if ~isempty(restart)
+					launchcommand=['cd ' cluster.executionpath '/Interactive' num2str(cluster.interactive)];
+				else
+					launchcommand=['cd ' cluster.executionpath '/Interactive' num2str(cluster.interactive) ' && tar -zxf ' dirname '.tar.gz'];
+				end
+			else
 				if ~isempty(restart)
 					launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && sbatch ' modelname '.queue '];
@@ -195,10 +203,4 @@
 						' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz  && sbatch ' modelname '.queue '];
 				end
-			else
-				if ~isempty(restart)
-					launchcommand=['cd ' cluster.executionpath '/Interactive' num2str(cluster.interactive)];
-				else
-					launchcommand=['cd ' cluster.executionpath '/Interactive' num2str(cluster.interactive) ' && tar -zxf ' dirname '.tar.gz'];
-				end
 			end
 
@@ -210,14 +212,14 @@
 
 			%copy files from cluster to current directory
-			if ~cluster.interactive,
+			if cluster.interactive,
+				directory=[cluster.executionpath '/Interactive' num2str(cluster.interactive) '/'];
+			else
 				directory=[cluster.executionpath '/' dirname '/'];
-			else
-				directory=[cluster.executionpath '/Interactive' num2str(cluster.interactive) '/'];
-			end
-
-			if ~cluster.bbftp,
+			end
+
+			if cluster.bbftp,
+				issmbbftpin(cluster.name, cluster.login, cluster.port, cluster.numstreams, directory, filelist);
+			else
 				issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist);
-			else
-				issmbbftpin(cluster.name, cluster.login, cluster.port, cluster.numstreams, directory, filelist);
 			end
 
Index: /issm/trunk-jpl/src/m/classes/clusters/discover.py
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/discover.py	(revision 26332)
+++ /issm/trunk-jpl/src/m/classes/clusters/discover.py	(revision 26332)
@@ -0,0 +1,224 @@
+import subprocess
+
+try:
+    from discover_settings import discover_settings
+except ImportError:
+    print('You need discover_settings.py to proceed, check presence and sys.path')
+from fielddisplay import fielddisplay
+from IssmConfig import IssmConfig
+from issmscpin import issmscpin
+from issmscpout import issmscpout
+from issmssh import issmssh
+from MatlabFuncs import *
+import math
+import numpy as np
+from pairoptions import pairoptions
+from QueueRequirements import QueueRequirements
+
+class discover(object):
+    """DISCOVER cluster class definition
+
+    Usage:
+        cluster = discover()
+        cluster = discover('np', 3)
+        cluster = discover('np', 3, 'login', 'username')
+    """
+
+    def __init__(self, *args):  # {{{
+        self.name = oshostname()
+        self.login = ''
+        self.modules = ['comp/intel/20.0.0.166', 'mpi/sgi-mpt/2.17', 'cmake/3.17.0']
+        self.numnodes = 20
+        self.cpuspernode = 8
+        self.port = 0
+        self.queue = 'general'
+        self.time = 12 * 60 * 60
+        self.processor = 'west'
+        self.srcpath = ''
+        self.codepath = ''
+        self.executionpath = ''
+        self.grouplist = ''
+        self.interactive = 0
+        self.bbftp = 0
+        self.numstreams = 8
+        self.hyperthreading = 0
+        self.email = ''
+
+        # Use provided options to change fields
+        options = pairoptions(*args)
+
+        # Initialize cluster using user settings if provided
+        try:
+            self = discover_settings(self)
+        except NameError:
+            print('discover_settings.py not found, using default settings')
+
+        # OK get other fields
+        self = options.AssignObjectFields(self)
+    # }}}
+
+    def __repr__(self):  # {{{
+        # Display the object
+        s = 'class pfe object\n'
+        s += '    name: {}\n'.format(self.name)
+        s += '    login: {}\n'.format(self.login)
+        s += '    modules: {}\n'.format(strjoin(self.modules, ', '))
+        s += '    numnodes: {}\n'.format(self.numnodes)
+        s += '    cpuspernode: {}\n'.format(self.cpuspernode)
+        s += '    np: {}\n'.format(self.nprocs())
+        s += '    port: {}\n'.format(self.port)
+        s += '    queue: {}\n'.format(self.queue)
+        s += '    time: {}\n'.format(self.time)
+        s += '    processor: {}\n'.format(self.processor)
+        s += '    srcpath: {}\n'.format(self.srcpath)
+        s += '    codepath: {}\n'.format(self.codepath)
+        s += '    executionpath: {}\n'.format(self.executionpath)
+        s += '    grouplist: {}\n'.format(self.grouplist)
+        s += '    interactive: {}\n'.format(self.interactive)
+        s += '    bbftp: {}\n'.format(self.bbftp)
+        s += '    numstreams: {}\n'.format(self.numstreams)
+        s += '    hyperthreading: {}\n'.format(self.hyperthreading)
+        return s
+    # }}}
+
+    def nprocs(self):  # {{{
+        return self.numnodes * self.cpuspernode
+    # }}}
+
+    def checkconsistency(self, md, solution, analyses):  # {{{
+        queuedict = {'long': [24*60*60, 560],
+                     'allnccs': [12*60*60, 6000],
+                     'debug': [1*60*60, 532]}
+        QueueRequirements(queuedict, self.queue, self.nprocs(), self.time)
+
+        # Now, check cluster.cpuspernode according to processor type
+        if self.processor == 'sand':
+            if self.cpuspernode > 16 or self.cpuspernode < 1:
+                md = md.checkmessage('cpuspernode should be between 1 and 16 for \'sand\' processors in hyperthreading mode')
+        elif self.processor == 'hasw':
+            if self.cpuspernode > 28 or self.cpuspernode < 1:
+                md = md.checkmessage('cpuspernode should be between 1 and 28 for \'hasw\' processors in hyperthreading mode')
+        else:
+            md = md.checkmessage('unknown processor type, should be \'sand\' or \'hasw\'')
+
+        # Miscellaneous
+        if not self.login:
+            md = md.checkmessage('login empty')
+        if not self.codepath:
+            md = md.checkmessage('codepath empty')
+        if not self.executionpath:
+            md = md.checkmessage('executionpath empty')
+
+        return self
+    # }}}
+
+    def BuildQueueScript(self, dirname, modelname, solution, io_gather, isvalgrind, isgprof, isdakota, isoceancoupling):  # {{{
+        if isgprof:
+            print('gprof not supported by cluster, ignoring...')
+
+        executable = 'issm.exe'
+        if isdakota:
+            version = IssmConfig('_DAKOTA_VERSION_')[0:2]
+            version = float(version)
+            if version >= 6:
+                executable = 'issm_dakota.exe'
+        if isoceancoupling:
+            executable = 'issm_ocean.exe'
+
+        # Write queuing script
+        fid = open(modelname + '.queue', 'w')
+
+        fid.write('#/bin/bash\n')
+        fid.write('#SBATCH -J {} \n'.format(modelname))
+        fid.write('#SBATCH --qos={} \n'.format(self.queue))
+        fid.write('#SBATCH -o {}.outlog \n'.format(modelname))
+        fid.write('#SBATCH -e {}.errlog \n'.format(modelname))
+        fid.write('#SBATCH -n {} \n'.format(self.nprocs()))
+        fid.write('#SBATCH -N {} \n'.format(self.numnodes))
+        fid.write('#SBATCH -y {:02d}:{:02d}:00 \n'.format(int(math.floor(self.time / 3600)), int(math.floor(self.time % 3600) / 60)))
+        fid.write('#SBATCH -A {} \n\n'.format(self.grouplist))
+        if len(np.where(self.email, '@')[0]):
+            fid.write('#SBATCH --mail-user={} \n'.format(self.email))
+            fid.write('#SBATCH --mail-type=end \n\n')
+        fid.write('. /usr/share/modules/init/bash\n\n')
+        for i in range(len(self.modules)):
+            fid.write('module load {}\n'.format(self.modules[i]))
+        fid.write('export MPI_GROUP_MAX=64\n\n')
+        fid.write('export MPI_UNBUFFERED_STDIO=true\n\n')
+        fid.write('export PATH="$PATH:."\n\n')
+        fid.write('export ISSM_DIR="{}/../"\n'.format(self.codepath)) # FIXME
+        fid.write('source $ISSM_DIR/etc/environment.sh\n') # FIXME
+        fid.write('cd {}/{}\n\n'.format(self.executionpath, dirname))
+
+        fid.write('mpiexec -np {} {}/{} {} {}/{} {}\n'.format(self.nprocs(), self.codepath, executable, solution, self.executionpath, dirname, modelname))
+
+        if not io_gather: # concatenate the output files
+            fid.write('cat {}.outbin.* > {}.outbin'.format(modelname, modelname))
+        fid.close()
+
+        # In interactive mode, create a run file, and errlog and outlog file
+        if self.interactive:
+            fid = open(modelname + '.run', 'w')
+            if not isvalgrind:
+                fid.write('mpiexec -np {} {}/{} {} {}/{} {}\n'.format(self.nprocs(), self.codepath, executable, solution, self.executionpath, dirname, modelname))
+            else:
+                fid.write('mpiexec -np {} valgrind --leak-check=full {}/{} {} {}/{} {}\n'.format(self.nprocs(), self.codepath, executable, solution, self.executionpath, dirname, modelname))
+            if not io_gather: # concatenate the output files
+                fid.write('cat {}.outbin.* > {}.outbin'.format(modelname, modelname))
+            fid.close()
+            fid = open(modelname + '.errlog', 'w') # TODO: Change this to system call (touch <file>)?
+            fid.close()
+            fid = open(modelname + '.outlog', 'w') # TODO: Change this to system call (touch <file>)?
+            fid.close()
+        end
+    # }}}
+
+    def UploadQueueJob(self, modelname, dirname, filelist):  # {{{
+        # Compress the files into one zip
+        compressstring = 'tar -zcf {}.tar.gz'.format(dirname)
+        for file in filelist:
+            compressstring += ' {}'.format(file)
+        if self.interactive:
+            compressstring += ' {}.run {}.errlog {}.outlog'.format(modelname, modelname, modelname)
+        subprocess.call(compressstring, shell=True)
+
+        print('uploading input file and queueing script')
+        if self.interactive:
+            directory = '{}/Interactive{}'.format(self.executionpath, self.interactive)
+        else:
+            directory = self.executionpath
+
+        if self.bbftp:
+            issmbbftpout(self.name, directory, self.login, self.port, self.numstreams, '{}.tar.gz'.format(dirname))
+        else:
+            issmscpout(self.name, directory, self.login, self.port, '{}.tar.gz'.format(dirname))
+    # }}}
+
+    def LaunchQueueJob(self, modelname, dirname, filelist, restart, batch):  # {{{
+        if self.interactive:
+            if restart:
+                launchcommand = 'cd {}/Interactive{}'.format(self.executionpath, self.interactive)
+            else:
+                launchcommand = 'cd {}/Interactive{} && tar -zxf {}.tar.gz'.format(self.executionpath, self.interactive, dirname)
+        else:
+            if restart:
+                launchcommand = 'cd {} && cd {} && sbatch {}.queue'.format(self.executionpath, dirname, modelname)
+            else:
+                launchcommand = 'cd {} && rm -rf ./{} && mkdir {} && cd {} && mv ../{}.tar.gz ./ && tar -zxf {}.tar.gz && sbatch {}.queue'.format(self.executionpath, dirname, dirname, dirname, dirname, dirname, modelname)
+
+        print('launching solution sequence on remote cluster')
+        issmssh(self.name, self.login, self.port, launchcommand)
+    # }}}
+
+    def Download(self, dirname, filelist):  # {{{
+        # Copy files from cluster to current directory
+        if self.interactive:
+            directory = '{}/Interactive{}'.format(self.executionpath, self.interactive)
+        else:
+            directory = '{}/{}/'.format(self.executionpath, dirname)
+
+        if self.bbftp:
+            issmbbftpin(self.name, self.login, self.port, self.numstreams, directory, filelist)
+        else:
+            issmscpin(self.name, self.login, self.port, directory, filelist)
+    # }}}
Index: /issm/trunk-jpl/src/m/classes/clusters/fram.py
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/fram.py	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/fram.py	(revision 26332)
@@ -15,21 +15,21 @@
 
 class fram(object):
-    """
-    Fram cluster class definition
+    """FRAM cluster class definition
+
     This is a SLURM queue
     The priorities are based on a point system, reservation when reaching 20000 and earning 1 point per min.
-     - Devel queue starts at 19990
-     - Normal starts at 19940
-     - Normal unpri atarts at 19400
+    - Devel queue starts at 19990
+    - Normal starts at 19940
+    - Normal unpri atarts at 19400
 
     Jobs can be:
-     - normal (4 to 30 nodes, more if asked, 48h max walltime, 60Gb per nodes)
-     - bigmem for big memory nodes (8 512Gb nodes and 2 6Tb nodes, shared nodes, 14days max walltime
+    - normal (4 to 30 nodes, more if asked, 48h max walltime, 60Gb per nodes)
+    - bigmem for big memory nodes (8 512Gb nodes and 2 6Tb nodes, shared nodes, 14days max walltime
 
-       Usage:
-          cluster = stallo()
+    Usage:
+        cluster = fram()
     """
 
-    def __init__(self, *args):    # {{{
+    def __init__(self, *args):  # {{{
         self.name = 'fram'
         self.login = ''
@@ -45,17 +45,18 @@
         self.accountname = ''
         self.profiling = 0
-    #use provided options to change fields
+        # Use provided options to change fields
         options = pairoptions(*args)
 
-    #initialize cluster using user settings if provided
+        # Initialize cluster using user settings if provided
         self = fram_settings(self)
-    #OK get other fields
+
+        # OK get other fields
         self = options.AssignObjectFields(self)
         self.np = self.numnodes * self.cpuspernode
     # }}}
 
-    def __repr__(self):    # {{{
-        #  display the object
-        s = "class vilje object:"
+    def __repr__(self):  # {{{
+        # Display the object
+        s = "class fram object:"
         s = "%s\n%s" % (s, fielddisplay(self, 'name', 'name of the cluster'))
         s = "%s\n%s" % (s, fielddisplay(self, 'login', 'login'))
@@ -74,10 +75,10 @@
 
     def checkconsistency(self, md, solution, analyses):  # {{{
-        #Queue dictionarry  gives queue name as key and max walltime and cpus as var
+        # Queue dictionary gives queue name as key and max walltime and CPUs as var
         queuedict = {'normal': [2 * 24 * 60, 2048],
                      'devel': [4 * 60, 2048]}
         QueueRequirements(queuedict, self.queue, self.np, self.time)
 
-    #Miscelaneous
+        # Miscellaneous
         if not self.login:
             md = md.checkmessage('login empty')
@@ -91,5 +92,5 @@
     # }}}
 
-    def BuildQueueScript(self, dirname, modelname, solution, io_gather, isvalgrind, isgprof, isdakota, isoceancoupling):    # {{{
+    def BuildQueueScript(self, dirname, modelname, solution, io_gather, isvalgrind, isgprof, isdakota, isoceancoupling):  # {{{
         executable = 'issm.exe'
         if isdakota:
@@ -100,5 +101,5 @@
         if isoceancoupling:
             executable = 'issm_ocean.exe'
-    #write queuing script
+        # Write queuing script
         shortname = modelname[0:min(12, len(modelname))]
         fid = open(modelname + '.queue', 'w')
@@ -125,5 +126,5 @@
         fid.write('module load ParMETIS/4.0.3-intel-2017a\n')
         fid.write('cd %s/%s/ \n\n' % (self.executionpath, dirname))
-        if self.profiling == 1:
+        if self.profiling:
             fid.write('module load perf-report\n')
             fid.write('perf-report mpirun -np %i %s/%s %s %s/%s %s\n' % (self.np, self.codepath, executable, str(solution), self.executionpath, dirname, modelname))
@@ -131,12 +132,11 @@
             fid.write('mpirun -np %i %s/%s %s %s/%s %s\n' % (self.np, self.codepath, executable, str(solution), self.executionpath, dirname, modelname))
         fid.close()
-
     # }}}
 
-    def UploadQueueJob(self, modelname, dirname, filelist):    # {{{
-        #compress the files into one zip.
+    def UploadQueueJob(self, modelname, dirname, filelist):  # {{{
+        # Compress the files into one zip
         compressstring = 'tar -zcf %s.tar.gz ' % dirname
         for file in filelist:
-            compressstring += ' %s' % file
+            compressstring += ' {}'.format(file)
         subprocess.call(compressstring, shell=True)
 
@@ -145,5 +145,5 @@
 
     # }}}
-    def LaunchQueueJob(self, modelname, dirname, filelist, restart, batch):    # {{{
+    def LaunchQueueJob(self, modelname, dirname, filelist, restart, batch):  # {{{
         print('launching solution sequence on remote cluster')
         if restart:
@@ -152,8 +152,7 @@
             launchcommand = 'cd %s && rm -rf ./%s && mkdir %s && cd %s && mv ../%s.tar.gz ./ && tar -zxf %s.tar.gz  && sbatch %s.queue' % (self.executionpath, dirname, dirname, dirname, dirname, dirname, modelname)
         issmssh(self.name, self.login, self.port, launchcommand)
-
     # }}}
-    def Download(self, dirname, filelist):    # {{{
-        #copy files from cluster to current directory
+    def Download(self, dirname, filelist):  # {{{
+        # Copy files from cluster to current directory
         directory = '%s/%s/' % (self.executionpath, dirname)
         issmscpin(self.name, self.login, self.port, directory, filelist)
Index: /issm/trunk-jpl/src/m/classes/clusters/gemini.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/gemini.m	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/gemini.m	(revision 26332)
@@ -7,5 +7,5 @@
 
 classdef gemini
-    properties (SetAccess=public) 
+	properties (SetAccess=public)
 	% {{{
 		name='gemini'
@@ -18,91 +18,91 @@
 		executionpath='/workg/edw/Testing/Execution'
 	%}}}
-    end
-    methods
-		 function cluster=gemini(varargin) % {{{
-			 cluster=AssignObjectFields(pairoptions(varargin{:}),cluster);
-		 end
-		 %}}}
-		 function disp(cluster) % {{{
-			 %  display the object
-			 disp(sprintf('class ''%s'' object ''%s'' = ',class(cluster),inputname(1)));
-			 disp(sprintf('    name: %s',cluster.name));
-			 disp(sprintf('    login: %s',cluster.login));
-			 disp(sprintf('    np: %i',cluster.np));
-			 disp(sprintf('    port: %i',cluster.port));
-			 disp(sprintf('    queue: %s',cluster.queue));
-			 disp(sprintf('    time: %i',cluster.time));
-			 disp(sprintf('    codepath: %s',cluster.codepath));
-			 disp(sprintf('    executionpath: %s',cluster.executionpath));
-		 end
-		 %}}}
-		 function md = checkconsistency(cluster,md,solution,analyses) % {{{
+	end
+	methods
+		function cluster=gemini(varargin) % {{{
+			cluster=AssignObjectFields(pairoptions(varargin{:}),cluster);
+		end
+		%}}}
+		function disp(cluster) % {{{
+			%  display the object
+			disp(sprintf('class ''%s'' object ''%s'' = ',class(cluster),inputname(1)));
+			disp(sprintf('    name: %s',cluster.name));
+			disp(sprintf('    login: %s',cluster.login));
+			disp(sprintf('    np: %i',cluster.np));
+			disp(sprintf('    port: %i',cluster.port));
+			disp(sprintf('    queue: %s',cluster.queue));
+			disp(sprintf('    time: %i',cluster.time));
+			disp(sprintf('    codepath: %s',cluster.codepath));
+			disp(sprintf('    executionpath: %s',cluster.executionpath));
+		end
+		%}}}
+		function md = checkconsistency(cluster,md,solution,analyses) % {{{
 
-			 available_queues={'debug','shortg','longg'};
-			 queue_requirements_time=[60 180 720];
-			 queue_requirements_np=[50 50 50];
+			available_queues={'debug','shortg','longg'};
+			queue_requirements_time=[60 180 720];
+			queue_requirements_np=[50 50 50];
 
-			 QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.np,cluster.time)
-		 end
-		 %}}}
-		 function BuildQueueScript(cluster,dirname,modelname,solution,io_gather,isvalgrind,isgprof,isdakota,isoceancoupling) % {{{
+			QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.np,cluster.time)
+		end
+		%}}}
+		function BuildQueueScript(cluster,dirname,modelname,solution,io_gather,isvalgrind,isgprof,isdakota,isoceancoupling) % {{{
 
-			 if(isvalgrind), disp('valgrind not supported by cluster, ignoring...'); end
-			 if(isgprof),    disp('gprof not supported by cluster, ignoring...'); end
+			if(isvalgrind), disp('valgrind not supported by cluster, ignoring...'); end
+			if(isgprof),    disp('gprof not supported by cluster, ignoring...'); end
 
-			 %write queuing script 
-			 fid=fopen([modelname '.queue'],'w');
-			 fprintf(fid,'#!/bin/sh\n');
-			 fprintf(fid,'#PBS -l walltime=%i\n',cluster.time*60); %walltime is in seconds.
-			 fprintf(fid,'#PBS -N %s\n',modelname);
-			 fprintf(fid,'#PBS -l ncpus=%i\n',cluster.np);
-			 if ~isempty(queue),
-				 fprintf(fid,'#PBS -q %s\n',cluster.queue);
-			 end
-			 fprintf(fid,'#PBS -o %s.outlog \n',modelname);
-			 fprintf(fid,'#PBS -e %s.errlog \n',modelname);
+			%write queuing script 
+			fid=fopen([modelname '.queue'],'w');
+			fprintf(fid,'#!/bin/sh\n');
+			fprintf(fid,'#PBS -l walltime=%i\n',cluster.time*60); %walltime is in seconds.
+			fprintf(fid,'#PBS -N %s\n',modelname);
+			fprintf(fid,'#PBS -l ncpus=%i\n',cluster.np);
+			if ~isempty(queue),
+				fprintf(fid,'#PBS -q %s\n',cluster.queue);
+			end
+			fprintf(fid,'#PBS -o %s.outlog \n',modelname);
+			fprintf(fid,'#PBS -e %s.errlog \n',modelname);
 
-			 fprintf(fid,'export PBS_O_WORKDIR=%s\n',[cluster.executionpath '/' dirname]);
-			 fprintf(fid,'cd $PBS_O_WORKDIR\n');
-			 fprintf(fid,'export OMP_NUM_THREADS=1\n');
-			 fprintf(fid,'dplace -s1 -c0-%i mpiexec -np %i %s/issm.exe %s %s %s',cluster.np-1,cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
-			 fclose(fid);
+			fprintf(fid,'export PBS_O_WORKDIR=%s\n',[cluster.executionpath '/' dirname]);
+			fprintf(fid,'cd $PBS_O_WORKDIR\n');
+			fprintf(fid,'export OMP_NUM_THREADS=1\n');
+			fprintf(fid,'dplace -s1 -c0-%i mpiexec -np %i %s/issm.exe %s %s %s',cluster.np-1,cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
+			fclose(fid);
 
-		 end
-		 %}}}
-		 function UploadQueueJob(cluster,modelname,dirname,filelist)% {{{
+		end
+		%}}}
+		function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{
 
-			 %compress the files into one zip.
-			 compressstring=['tar -zcf ' dirname '.tar.gz '];
-			 for i=1:numel(filelist),
-				 compressstring = [compressstring ' ' filelist{i}];
-			 end
-			 if cluster.interactive,
-				 compressstring = [compressstring ' ' modelname '.errlog ' modelname '.outlog '];
-			 end
-			 system(compressstring);
+			%compress the files into one zip.
+			compressstring=['tar -zcf ' dirname '.tar.gz '];
+			for i=1:numel(filelist),
+				compressstring = [compressstring ' ' filelist{i}];
+			end
+			if cluster.interactive,
+				compressstring = [compressstring ' ' modelname '.errlog ' modelname '.outlog '];
+			end
+			system(compressstring);
 
-			 disp('uploading input file and queueing script');
-			 issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
+			disp('uploading input file and queueing script');
+			issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
 
-		 end %}}}
-		 function LaunchQueueJob(cluster,modelname,dirname,filelist,restart)% {{{
+		end %}}}
+		function LaunchQueueJob(cluster,modelname,dirname,filelist,restart) % {{{
 
-			 disp('launching solution sequence on remote cluster');
-			 if ~isempty(restart)
-				 launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && qsub ' modelname '.queue '];
-			 else
-				 launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ...
-					 ' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz  && qsub ' modelname '.queue '];
-			 end
-			 issmssh(cluster.name,cluster.login,cluster.port,launchcommand);
-		 end %}}}
-		 function Download(cluster,dirname,filelist)% {{{
+			disp('launching solution sequence on remote cluster');
+			if ~isempty(restart)
+				launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && qsub ' modelname '.queue '];
+			else
+				launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ...
+					' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz  && qsub ' modelname '.queue '];
+			end
+			issmssh(cluster.name,cluster.login,cluster.port,launchcommand);
+		end %}}}
+		function Download(cluster,dirname,filelist) % {{{
 
-			 %copy files from cluster to current directory
-			 directory=[cluster.executionpath '/' dirname '/'];
-			 issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist);
+			%copy files from cluster to current directory
+			directory=[cluster.executionpath '/' dirname '/'];
+			issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist);
 
-		 end %}}}
+		end %}}}
 	end
 end
Index: /issm/trunk-jpl/src/m/classes/clusters/generic.py
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/generic.py	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/generic.py	(revision 26332)
@@ -1,3 +1,2 @@
-from socket import gethostname
 from subprocess import call
 
@@ -9,5 +8,5 @@
 except ImportError:
     print('Warning generic_settings.py not found, default will be used')
-from MatlabFuncs import ispc
+from MatlabFuncs import *
 from IssmConfig import IssmConfig
 from issmdir import issmdir
@@ -44,5 +43,5 @@
 
         # Get name
-        self.name = gethostname()
+        self.name = oshostname()
 
         # Initialize cluster using user settings if provided
@@ -58,16 +57,16 @@
     def __repr__(self):  # {{{
         #  display the object
-        s = "class '%s' object '%s' = \n" % (type(self), 'self')
-        s += '{}\n'.format(fielddisplay(self, 'name', ''))
-        s += '{}\n'.format(fielddisplay(self, 'login', ''))
-        s += '{}\n'.format(fielddisplay(self, 'np', ''))
-        s += '{}\n'.format(fielddisplay(self, 'port', ''))
-        s += '{}\n'.format(fielddisplay(self, 'codepath', ''))
-        s += '{}\n'.format(fielddisplay(self, 'executionpath', ''))
-        s += '{}\n'.format(fielddisplay(self, 'valgrind', ''))
-        s += '{}\n'.format(fielddisplay(self, 'valgrindlib', ''))
-        s += '{}\n'.format(fielddisplay(self, 'valgrindsup', ''))
-        s += '{}\n'.format(fielddisplay(self, 'verbose', ''))
-        s += '{}\n'.format(fielddisplay(self, 'shell', ''))
+        s = 'class \'{}\' object \'{}\' = \n'.format(type(self), 'self')
+        s += '    name: {}\n'.format(self.name)
+        s += '    login: {}\n'.format(self.login)
+        s += '    np: {}\n'.format(self.np)
+        s += '    port: {}\n'.format(self.port)
+        s += '    codepath: {}\n'.format(self.codepath)
+        s += '    executionpath: {}\n'.format(self.executionpath)
+        s += '    valgrind: {}\n'.format(self.valgrind)
+        s += '    valgrindlib: {}\n'.format(self.valgrindlib)
+        s += '    valgrindsup: {}\n'.format(self.valgrindsup)
+        s += '    verbose: {}\n'.format(self.verbose)
+        s += '    shell: {}\n'.format(self.shell)
         return s
     # }}}
Index: /issm/trunk-jpl/src/m/classes/clusters/generic_static.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/generic_static.m	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/generic_static.m	(revision 26332)
@@ -36,4 +36,6 @@
 			disp(sprintf('    np: %i',cluster.np));
 			disp(sprintf('    codepath: %s',cluster.codepath));
+			disp(sprintf('    executionpath: %s',cluster.executionpath));
+			disp(sprintf('    interactive: %s',cluster.interactive));
 			disp(sprintf('    shell: %s',cluster.shell));
 		end
@@ -84,9 +86,9 @@
 		end
 		%}}}
-		function UploadQueueJob(cluster,modelname,dirname,filelist)% {{{
+		function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{
 			% Do nothing
 			return;
 		end %}}}
-		function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch)% {{{
+		function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{
 			if ~ispc,
 				% Figure out which file extension to use
@@ -104,5 +106,5 @@
 			end
 		end %}}}
-		function Download(cluster,dirname,filelist)% {{{
+		function Download(cluster,dirname,filelist) % {{{
 			% Do nothing
 			return;
Index: /issm/trunk-jpl/src/m/classes/clusters/generic_static.py
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/generic_static.py	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/generic_static.py	(revision 26332)
@@ -1,9 +1,6 @@
 import math
 import os
-import socket
 import subprocess
-
 import numpy as np
-
 from IssmConfig import IssmConfig
 from issmdir import issmdir
@@ -11,14 +8,13 @@
 from issmscpin import issmscpin
 from issmscpout import issmscpout
-import MatlabFuncs as m
+from MatlabFuncs import *
 from pairoptions import pairoptions
 
 
 class generic_static(object):
-    """
-    GENERIC cluster class definition
+    """GENERIC cluster class definition
 
-       Usage:
-          cluster = generic_static('name', 'astrid', 'np', 3)
+    Usage:
+        cluster = generic_static('name', 'astrid', 'np', 3)
     """
 
@@ -38,5 +34,5 @@
 
         #get name
-        self.name = socket.gethostname()
+        self.name = oshostname()
 
         #initialize cluster using user settings if provided
Index: /issm/trunk-jpl/src/m/classes/clusters/greenplanet.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/greenplanet.m	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/greenplanet.m	(revision 26332)
@@ -37,8 +37,8 @@
 			disp(sprintf('    name: %s',cluster.name));
 			disp(sprintf('    login: %s',cluster.login));
-			disp(sprintf('    port: %i',cluster.port));
 			disp(sprintf('    numnodes: %i',cluster.numnodes));
 			disp(sprintf('    cpuspernode: %i',cluster.cpuspernode));
-			disp(sprintf('    np: %i',cluster.cpuspernode*cluster.numnodes));
+			disp(sprintf('    np: %i',cluster.nprocs()));
+			disp(sprintf('    port: %i',cluster.port));
 			disp(sprintf('    queue: %s',cluster.queue));
 			disp(sprintf('    codepath: %s',cluster.codepath));
@@ -60,7 +60,7 @@
 			queue_requirements_np=[80 80 80 80 80 80 80 80 80];
 
-			QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.np,1)
+			QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.nprocs(),1)
 
-			%Miscelaneous
+			%Miscellaneous
 			if isempty(cluster.login), md = checkmessage(md,'login empty'); end
 			if isempty(cluster.codepath), md = checkmessage(md,'codepath empty'); end
@@ -87,5 +87,5 @@
 			fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n');       %FIXME
 			fprintf(fid,'cd %s/%s\n\n',cluster.executionpath,dirname);
-			fprintf(fid,'mpiexec -np %i %s/kriging.exe %s %s\n',cluster.np,cluster.codepath,[cluster.executionpath '/' modelname],modelname);
+			fprintf(fid,'mpiexec -np %i %s/kriging.exe %s %s\n',cluster.nprocs(),cluster.codepath,[cluster.executionpath '/' modelname],modelname);
 			if ~io_gather, %concatenate the output files:
 				fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname);
@@ -120,5 +120,5 @@
 			fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n');       %FIXME
 			fprintf(fid,'cd %s/%s\n\n',cluster.executionpath,dirname);
-			fprintf(fid,'mpiexec -n %i %s/issm.exe %s %s %s\n',cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
+			fprintf(fid,'mpiexec -n %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
 			if ~io_gather, %concatenate the output files:
 				fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname);
@@ -129,5 +129,5 @@
 			if cluster.interactive,
 				fid=fopen([modelname '.run'],'w');
-				fprintf(fid,'mpiexec -n %i %s/issm.exe %s %s %s\n',cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
+				fprintf(fid,'mpiexec -n %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
 				if ~io_gather, %concatenate the output files:
 					fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname);
Index: /issm/trunk-jpl/src/m/classes/clusters/hpc.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/hpc.m	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/hpc.m	(revision 26332)
@@ -35,8 +35,8 @@
 			disp(sprintf('    name: %s',cluster.name));
 			disp(sprintf('    login: %s',cluster.login));
-			disp(sprintf('    port: %i',cluster.port));
 			disp(sprintf('    numnodes: %i',cluster.numnodes));
 			disp(sprintf('    cpuspernode: %i',cluster.cpuspernode));
-			disp(sprintf('    np: %i',cluster.cpuspernode*cluster.numnodes));
+			disp(sprintf('    np: %i',cluster.nprocs()));
+			disp(sprintf('    port: %i',cluster.port));
 			disp(sprintf('    queue: %s',cluster.queue));
 			disp(sprintf('    codepath: %s',cluster.codepath));
@@ -56,7 +56,7 @@
 			queue_requirements_np=[64 64 48 48 48];
 
-			QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.np,1)
+			QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.nprocs(),1)
 
-			%Miscelaneous
+			%Miscellaneous
 			if isempty(cluster.login), md = checkmessage(md,'login empty'); end
 			if isempty(cluster.codepath), md = checkmessage(md,'codepath empty'); end
@@ -83,5 +83,5 @@
 			fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n');       %FIXME
 			fprintf(fid,'cd %s/%s\n\n',cluster.executionpath,modelname);
-			fprintf(fid,'mpiexec -np %i %s/kriging.exe %s %s\n',cluster.np,cluster.codepath,[cluster.executionpath '/' modelname],modelname);
+			fprintf(fid,'mpiexec -np %i %s/kriging.exe %s %s\n',cluster.nprocs(),cluster.codepath,[cluster.executionpath '/' modelname],modelname);
 			if ~io_gather, %concatenate the output files:
 				fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname);
@@ -108,5 +108,5 @@
 			fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n');       %FIXME
 			fprintf(fid,'cd %s/%s\n\n',cluster.executionpath,dirname);
-			fprintf(fid,'mpiexec -np %i %s/issm.exe %s %s %s\n',cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
+			fprintf(fid,'mpiexec -np %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
 			if ~io_gather, %concatenate the output files:
 				fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname);
@@ -117,5 +117,5 @@
 			if cluster.interactive,
 				fid=fopen([modelname '.run'],'w');
-				fprintf(fid,'mpiexec -np %i %s/issm.exe %s %s %s\n',cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
+				fprintf(fid,'mpiexec -np %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
 				if ~io_gather, %concatenate the output files:
 					fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname);
Index: /issm/trunk-jpl/src/m/classes/clusters/hpc_simba.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/hpc_simba.m	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/hpc_simba.m	(revision 26332)
@@ -36,8 +36,8 @@
 			disp(sprintf('    name: %s',cluster.name));
 			disp(sprintf('    login: %s',cluster.login));
-			disp(sprintf('    port: %i',cluster.port));
 			disp(sprintf('    numnodes: %i',cluster.numnodes));
 			disp(sprintf('    cpuspernode: %i',cluster.cpuspernode));
-			disp(sprintf('    np: %i',cluster.cpuspernode*cluster.numnodes));
+			disp(sprintf('    np: %i',cluster.np));
+			disp(sprintf('    port: %i',cluster.port));
 			disp(sprintf('    queue: %s',cluster.queue));
 			disp(sprintf('    codepath: %s',cluster.codepath));
@@ -45,9 +45,4 @@
 			disp(sprintf('    interactive: %i',cluster.interactive));
 		end
-		%}}}
-		%function numprocs=nprocs(cluster) % {{{
-		%	%compute number of processors
-		%	numprocs=cluster.numnodes*cluster.cpuspernode;
-		% end
 		%}}}
 		function md = checkconsistency(cluster,md,solution,analyses) % {{{
@@ -59,5 +54,5 @@
 			QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.np,1)
 
-			%Miscelaneous
+			%Miscellaneous
 			if isempty(cluster.login), md = checkmessage(md,'login empty'); end
 			if isempty(cluster.codepath), md = checkmessage(md,'codepath empty'); end
Index: /issm/trunk-jpl/src/m/classes/clusters/local.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/local.m	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/local.m	(revision 26332)
@@ -36,6 +36,6 @@
 			disp(sprintf('    np: %i',cluster.np));
 			disp(sprintf('    codepath: %s',cluster.codepath));
+			disp(sprintf('    etcpath: %s',cluster.etcpath));
 			disp(sprintf('    executionpath: %s',cluster.executionpath));
-			disp(sprintf('    etcpath: %s',cluster.etcpath));
 			disp(sprintf('    verbose: %s',cluster.verbose));
 			disp(sprintf('    shell: %s',cluster.shell));
Index: /issm/trunk-jpl/src/m/classes/clusters/localpfe.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/localpfe.m	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/localpfe.m	(revision 26332)
@@ -1,3 +1,3 @@
-%localpfe cluster class definition
+%LOCALPFE cluster class definition
 %
 %   Usage:
@@ -53,8 +53,10 @@
 			disp(sprintf('    login: %s',cluster.login));
 			disp(sprintf('    np: %i',cluster.np));
+			disp(sprintf('    npocean: %i',cluster.npocean));
 			disp(sprintf('    port: %i',cluster.port));
+			disp(sprintf('    interactive: %i',cluster.interactive));
 			disp(sprintf('    codepath: %s',cluster.codepath));
+			disp(sprintf('    etcpath: %s',cluster.etcpath));
 			disp(sprintf('    executionpath: %s',cluster.executionpath));
-			disp(sprintf('    etcpath: %s',cluster.etcpath));
 			disp(sprintf('    valgrind: %s',cluster.valgrind));
 			disp(sprintf('    valgrindlib: %s',cluster.valgrindlib));
Index: /issm/trunk-jpl/src/m/classes/clusters/lonestar.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/lonestar.m	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/lonestar.m	(revision 26332)
@@ -43,5 +43,6 @@
 			disp(sprintf('    numnodes: %i',cluster.numnodes));
 			disp(sprintf('    cpuspernode: %i',cluster.cpuspernode));
-			disp(sprintf('    np: %i',cluster.np));
+			disp(sprintf('    np: %i',cluster.nprocs()));
+			disp(sprintf('    port: %i',cluster.port));
 			disp(sprintf('    queue: %s',cluster.queue));
 			disp(sprintf('    codepath: %s',cluster.codepath));
@@ -63,7 +64,7 @@
 			queue_requirements_np=[4104 264];
 
-			QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.np,cluster.time)
-
-			%Miscelaneous
+			QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.nprocs(),cluster.time)
+
+			%Miscellaneous
 			if isempty(cluster.login), md = checkmessage(md,'login empty'); end
 			if isempty(cluster.codepath), md = checkmessage(md,'codepath empty'); end
@@ -89,5 +90,5 @@
 			fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n');       %FIXME
 			fprintf(fid,'cd %s/%s\n\n',cluster.executionpath,modelname);
-			fprintf(fid,'mpiexec -np %i %s/kriging.exe %s %s\n',cluster.np,cluster.codepath,[cluster.executionpath '/' modelname],modelname);
+			fprintf(fid,'mpiexec -np %i %s/kriging.exe %s %s\n',cluster.nprocs(),cluster.codepath,[cluster.executionpath '/' modelname],modelname);
 			if ~io_gather, %concatenate the output files:
 				fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname);
@@ -120,5 +121,5 @@
 			fprintf(fid,'#SBATCH -o %s.outlog \n',modelname);
 			fprintf(fid,'#SBATCH -e %s.errlog \n',modelname);
-			fprintf(fid,'#SBATCH -n %i \n',cluster.numnodes*max(cluster.np/cluster.numnodes,24));
+			fprintf(fid,'#SBATCH -n %i \n',cluster.numnodes*max(cluster.nprocs()/cluster.numnodes,24));
 			fprintf(fid,'#SBATCH -N %i \n',cluster.numnodes);
 			fprintf(fid,'#SBATCH -t %02i:%02i:00 \n\n',floor(cluster.time/3600),floor(mod(cluster.time,3600)/60));
@@ -142,5 +143,5 @@
 			fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n');       %FIXME
 			fprintf(fid,'cd %s/%s\n\n',cluster.executionpath,dirname);
-			fprintf(fid,'ibrun -np %i %s/%s %s %s %s\n',cluster.np,cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname);
+			fprintf(fid,'ibrun -np %i %s/%s %s %s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname);
 			if ~io_gather, %concatenate the output files:
 				fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname);
@@ -152,5 +153,5 @@
 			if cluster.interactive,
 				fid=fopen([modelname '.run'],'w');
-				fprintf(fid,'ibrun -np %i %s/%s %s %s %s\n',cluster.np,executable,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
+				fprintf(fid,'ibrun -np %i %s/%s %s %s %s\n',cluster.nprocs(),executable,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
 				if ~io_gather, %concatenate the output files:
 					fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname);
Index: /issm/trunk-jpl/src/m/classes/clusters/maui.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/maui.m	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/maui.m	(revision 26332)
@@ -38,8 +38,8 @@
 			disp(sprintf('    name: %s',cluster.name));
 			disp(sprintf('    login: %s',cluster.login));
-			disp(sprintf('    port: %i',cluster.port));
 			disp(sprintf('    numnodes: %i',cluster.numnodes));
 			disp(sprintf('    cpuspernode: %i',cluster.cpuspernode));
-			disp(sprintf('    np: %i',cluster.cpuspernode*cluster.numnodes));
+			disp(sprintf('    np: %i',cluster.nprocs()));
+			disp(sprintf('    port: %i',cluster.port));
 			disp(sprintf('    projectaccount: %s',cluster.projectaccount));
 			disp(sprintf('    partition: %s',cluster.partition));
@@ -62,7 +62,7 @@
 			partition_requirements_np=[80];
 
-			QueueRequirements(available_partitions,partition_requirements_time,partition_requirements_np,cluster.partition,cluster.np,1)
+			QueueRequirements(available_partitions,partition_requirements_time,partition_requirements_np,cluster.partition,cluster.nprocs(),1)
 
-			%Miscelaneous
+			%Miscellaneous
 			if isempty(cluster.login), md = checkmessage(md,'login empty'); end
 			if isempty(cluster.codepath), md = checkmessage(md,'codepath empty'); end
@@ -95,5 +95,5 @@
 			fprintf(fid,'module swap PrgEnv-cray PrgEnv-intel\n');
 			fprintf(fid,'cd %s/%s\n\n',cluster.executionpath,dirname);
-			fprintf(fid,'srun -n %i %s/issm.exe %s %s %s\n',cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
+			fprintf(fid,'srun -n %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
 			if ~io_gather, %concatenate the output files:
 				fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname);
@@ -104,5 +104,5 @@
 			if cluster.interactive,
 				fid=fopen([modelname '.run'],'w');
-				fprintf(fid,'mpiexec -n %i %s/issm.exe %s %s %s\n',cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
+				fprintf(fid,'mpiexec -n %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
 				if ~io_gather, %concatenate the output files:
 					fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname);
Index: /issm/trunk-jpl/src/m/classes/clusters/pfe.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/pfe.m	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/pfe.m	(revision 26332)
@@ -21,5 +21,5 @@
 		codepath       = '';
 		executionpath  = '';
-		grouplist     = 's1690';
+		grouplist      = '';
 		interactive    = 0;
 		bbftp          = 0;
@@ -39,32 +39,27 @@
 		%}}}
 		function disp(cluster) % {{{
-			% TODO:
-			% - Correct formatting of modules and cluster.np
-			%
-
 			% display the object
 			disp(sprintf('class ''%s'' object ''%s'' = ',class(cluster),inputname(1)));
-			fielddisplay(cluster,'name','name of the cluster');
-			fielddisplay(cluster,'login','login');
-			modules=''; for i=1:length(cluster.modules), modules=[modules cluster.modules{i} ',']; end; modules=modules(1:end-1);
-			disp(sprintf('         modules                : %s',modules));
-			fielddisplay(cluster,'port','machine access port');
-			fielddisplay(cluster,'numnodes','number of nodes');
-			fielddisplay(cluster,'cpuspernode','number of CPUs per node');
-			disp(sprintf('         np:                    : %i             -- %s',cluster.np(),'number of CPUs'));
-			fielddisplay(cluster,'queue','name of the queue');
-			fielddisplay(cluster,'time','walltime requested');
-			fielddisplay(cluster,'processor','type of processor');
-			fielddisplay(cluster,'srcpath','$ISSM_DIR on pfe');
-			fielddisplay(cluster,'codepath','$ISSM_DIR/bin on pfe');
-			fielddisplay(cluster,'executionpath','directory containing issm.exe on pfe');
-			fielddisplay(cluster,'grouplist','grouplist');
-			fielddisplay(cluster,'interactive','');
-			fielddisplay(cluster,'bbftp','');
-			fielddisplay(cluster,'numstreams','');
-			fielddisplay(cluster,'hyperthreading','');
-		end
-		%}}}
-		function numprocs=np(cluster) % {{{
+			disp(sprintf('    name: %s',cluster.name));
+			disp(sprintf('    login: %s',cluster.login));
+			disp(sprintf('    modules: %s',strjoin(cluster.modules,', ')));
+			disp(sprintf('    numnodes: %s',cluster.numnodes));
+			disp(sprintf('    cpuspernode: %s',cluster.cpuspernode));
+			disp(sprintf('    np: %i',cluster.nprocs()));
+			disp(sprintf('    port: %i',cluster.port));
+			disp(sprintf('    queue: %i',cluster.queue));
+			disp(sprintf('    time: %i',cluster.time));
+			disp(sprintf('    processor: %i',cluster.processor));
+			disp(sprintf('    srcpath: %s',cluster.srcpath));
+			disp(sprintf('    codepath: %s',cluster.codepath));
+			disp(sprintf('    executionpath: %s',cluster.executionpath));
+			disp(sprintf('    grouplist: %s',cluster.grouplist));
+			disp(sprintf('    interactive: %s',cluster.interactive));
+			disp(sprintf('    bbftp: %s',cluster.bbftp));
+			disp(sprintf('    numstreams: %s',cluster.numstreams));
+			disp(sprintf('    hyperthreading: %s',cluster.hyperthreading));
+		end
+		%}}}
+		function numprocs=nprocs(cluster) % {{{
 			%compute number of processors
 			numprocs=cluster.numnodes*cluster.cpuspernode;
@@ -77,5 +72,5 @@
 			queue_requirements_np=[2048 2048 150 150 2048];
 
-			QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.np,cluster.time)
+			QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.nprocs(),cluster.time)
 
 			%now, check cluster.cpuspernode according to processor type
@@ -183,7 +178,7 @@
 			fprintf(fid,'cd %s/%s/\n\n',cluster.executionpath,dirname);
 			if ~isvalgrind,
-				fprintf(fid,'/u/scicon/tools/bin/several_tries mpiexec -np %i /u/scicon/tools/bin/mbind.x -cs -n%i %s/%s %s %s/%s %s\n',cluster.np,cluster.cpuspernode,cluster.codepath,executable,solution,cluster.executionpath,dirname,modelname);
-			else
-				fprintf(fid,'mpiexec -np %i valgrind --leak-check=full %s/%s %s %s %s\n',cluster.np,cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname);
+				fprintf(fid,'/u/scicon/tools/bin/several_tries mpiexec -np %i /u/scicon/tools/bin/mbind.x -cs -n%i %s/%s %s %s/%s %s\n',cluster.nprocs(),cluster.cpuspernode,cluster.codepath,executable,solution,cluster.executionpath,dirname,modelname);
+			else
+				fprintf(fid,'mpiexec -np %i valgrind --leak-check=full %s/%s %s %s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname);
 			end
 			if ~io_gather, %concatenate the output files:
@@ -197,10 +192,10 @@
 				if cluster.interactive==10,
 						fprintf(fid,'module unload mpi-mvapich2/1.4.1/gcc\n');
-						fprintf(fid,'mpiexec -np %i %s/%s %s %s %s\n',cluster.np,cluster.codepath,executable,solution,[pwd() '/run'],modelname);
+						fprintf(fid,'mpiexec -np %i %s/%s %s %s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,[pwd() '/run'],modelname);
 				else
 					if ~isvalgrind,
-						fprintf(fid,'mpiexec -np %i %s/%s %s %s %s\n',cluster.np,cluster.codepath,executable,solution,[cluster.executionpath '/Interactive' num2str(cluster.interactive)],modelname);
+						fprintf(fid,'mpiexec -np %i %s/%s %s %s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,[cluster.executionpath '/Interactive' num2str(cluster.interactive)],modelname);
 					else
-						fprintf(fid,'mpiexec -np %i valgrind --leak-check=full %s/%s %s %s %s\n',cluster.np,cluster.codepath,executable,solution,[cluster.executionpath '/Interactive' num2str(cluster.interactive)],modelname);
+						fprintf(fid,'mpiexec -np %i valgrind --leak-check=full %s/%s %s %s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,[cluster.executionpath '/Interactive' num2str(cluster.interactive)],modelname);
 					end
 				end
@@ -325,5 +320,5 @@
 			fprintf(fid,'export MPI_GROUP_MAX=64\n\n');
 			fprintf(fid,'cd %s/%s/\n\n',cluster.executionpath,modelname);
-			fprintf(fid,'mpiexec -np %i %s/kriging.exe %s %s\n',cluster.np,cluster.codepath,[cluster.executionpath '/' modelname],modelname); %FIXME
+			fprintf(fid,'mpiexec -np %i %s/kriging.exe %s %s\n',cluster.nprocs(),cluster.codepath,[cluster.executionpath '/' modelname],modelname); %FIXME
 			if ~io_gather, %concatenate the output files:
 				fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname);
@@ -335,7 +330,7 @@
 				fid=fopen([modelname '.run'],'w');
 				if ~isvalgrind,
-					fprintf(fid,'mpiexec -np %i %s/kriging.exe %s %s\n',cluster.np,cluster.codepath,[cluster.executionpath '/' modelname],modelname);
-				else
-					fprintf(fid,'mpiexec -np %i valgrind --leak-check=full %s/kriging.exe %s %s\n',cluster.np,cluster.codepath,[cluster.executionpath '/' modelname],modelname);
+					fprintf(fid,'mpiexec -np %i %s/kriging.exe %s %s\n',cluster.nprocs(),cluster.codepath,[cluster.executionpath '/' modelname],modelname);
+				else
+					fprintf(fid,'mpiexec -np %i valgrind --leak-check=full %s/kriging.exe %s %s\n',cluster.nprocs(),cluster.codepath,[cluster.executionpath '/' modelname],modelname);
 				end
 				if ~io_gather, %concatenate the output files:
@@ -410,8 +405,8 @@
 			end
 
-			if ~cluster.bbftp,
+			if cluster.bbftp,
+				issmbbftpout(cluster.name,directory,cluster.login,cluster.port,cluster.numstreams,{[dirname '.tar.gz']});
+			else
 				issmscpout(cluster.name,directory,cluster.login,cluster.port,{[dirname '.tar.gz']});
-			else
-				issmbbftpout(cluster.name,directory,cluster.login,cluster.port,cluster.numstreams,{[dirname '.tar.gz']});
 			end
 
@@ -420,13 +415,6 @@
 		function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{
 
-			%lauch command, to be executed via ssh
-			if ~cluster.interactive, 
-				if ~isempty(restart)
-					launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && qsub ' modelname '.queue '];
-				else
-					launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ...
-						' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz  && qsub ' modelname '.queue '];
-				end
-			else
+			%launch command, to be executed via ssh
+			if cluster.interactive,
 				if ~isempty(restart)
 					launchcommand=['cd ' cluster.executionpath '/Interactive' num2str(cluster.interactive)];
@@ -437,4 +425,11 @@
 						launchcommand=['cd ' cluster.executionpath '/Interactive' num2str(cluster.interactive) ' && tar -zxf ' dirname '.tar.gz'];
 					end
+				end
+			else
+				if ~isempty(restart)
+					launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && qsub ' modelname '.queue '];
+				else
+					launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ...
+						' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz  && qsub ' modelname '.queue '];
 				end
 			end
@@ -455,8 +450,8 @@
 			end
 
-			if ~cluster.bbftp,
+			if cluster.bbftp,
+				issmbbftpin(cluster.name, cluster.login, cluster.port, cluster.numstreams, directory, filelist);
+			else
 				issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist);
-			else
-				issmbbftpin(cluster.name, cluster.login, cluster.port, cluster.numstreams, directory, filelist);
 			end
 
Index: /issm/trunk-jpl/src/m/classes/clusters/pfe.py
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/pfe.py	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/pfe.py	(revision 26332)
@@ -6,4 +6,5 @@
 from issmscpout import issmscpout
 from issmssh import issmssh
+from MatlabFuncs import *
 from pairoptions import pairoptions
 try:
@@ -35,5 +36,5 @@
         self.codepath = ''
         self.executionpath = ''
-        self.grouplist = 's1690'
+        self.grouplist = ''
         self.interactive = 0
         self.bbftp = 0
@@ -50,37 +51,29 @@
             print('pfe_settings.py not found, using default settings')
 
-        #OK get other fields
+        # OK get other fields
         self = options.AssignObjectFields(self)
     # }}}
 
     def __repr__(self):  # {{{
-        # TODO:
-        # - Correct formatting of modules and cluster.np
-        #
-
         # Display the object
         s = 'class pfe object\n'
-        s += '{}\n'.format(fielddisplay(self, 'name', 'name of the cluster'))
-        s += '{}\n'.format(fielddisplay(self, 'login', 'login'))
-        modules = ''
-        for i in range(len(self.modules)):
-            modules += self.modules[i] + ','
-        modules = modules[:-1]
-        s += '         modules                : {}\n'.format(modules)
-        s += '{}\n'.format(fielddisplay(self, 'port', 'machine access port'))
-        s += '{}\n'.format(fielddisplay(self, 'numnodes', 'number of nodes'))
-        s += '{}\n'.format(fielddisplay(self, 'cpuspernode', 'number of CPUs per node'))
-        s += '         np:                    : {}             -- {}\n'.format(self.nprocs(), 'number of CPUs')
-        s += '{}\n'.format(fielddisplay(self, 'queue', 'name of the queue'))
-        s += '{}\n'.format(fielddisplay(self, 'time', 'walltime requested'))
-        s += '{}\n'.format(fielddisplay(self, 'processor', 'type of processor'))
-        s += '{}\n'.format(fielddisplay(self, 'srcpath', '$ISSM_DIR on pfe'))
-        s += '{}\n'.format(fielddisplay(self, 'codepath', '$ISSM_DIR/bin on pfe'))
-        s += '{}\n'.format(fielddisplay(self, 'executionpath', 'directory containing issm.exe on pfe'))
-        s += '{}\n'.format(fielddisplay(self, 'grouplist', 'grouplist'))
-        s += '{}\n'.format(fielddisplay(self, 'interactive', ''))
-        s += '{}\n'.format(fielddisplay(self, 'bbftp', ''))
-        s += '{}\n'.format(fielddisplay(self, 'numstreams', ''))
-        s += '{}\n'.format(fielddisplay(self, 'hyperthreading', ''))
+        s += '    name: {}\n'.format(self.name)
+        s += '    login: {}\n'.format(self.login)
+        s += '    modules: {}\n'.format(strjoin(self.modules, ', '))
+        s += '    numnodes: {}\n'.format(self.numnodes)
+        s += '    cpuspernode: {}\n'.format(self.cpuspernode)
+        s += '    np: {}\n'.format(self.nprocs())
+        s += '    port: {}\n'.format(self.port)
+        s += '    queue: {}\n'.format(self.queue)
+        s += '    time: {}\n'.format(self.time)
+        s += '    processor: {}\n'.format(self.processor)
+        s += '    srcpath: {}\n'.format(self.srcpath)
+        s += '    codepath: {}\n'.format(self.codepath)
+        s += '    executionpath: {}\n'.format(self.executionpath)
+        s += '    grouplist: {}\n'.format(self.grouplist)
+        s += '    interactive: {}\n'.format(self.interactive)
+        s += '    bbftp: {}\n'.format(self.bbftp)
+        s += '    numstreams: {}\n'.format(self.numstreams)
+        s += '    hyperthreading: {}\n'.format(self.hyperthreading)
         return s
     # }}}
@@ -101,24 +94,38 @@
             if self.hyperthreading:
                 if self.cpuspernode > 40 or self.cpuspernode < 1:
-                    md = md.checkmessage('cpuspernode should be between 1 and 40 for ''ivy'' processors in hyperthreading mode')
+                    md = md.checkmessage('cpuspernode should be between 1 and 40 for \'ivy\' processors in hyperthreading mode')
             else:
                 if self.cpuspernode > 20 or self.cpuspernode < 1:
-                    md = md.checkmessage('cpuspernode should be between 1 and 20 for ''ivy'' processors')
+                    md = md.checkmessage('cpuspernode should be between 1 and 20 for \'ivy\' processors')
         elif self.processor == 'bro':
             if self.hyperthreading:
                 if self.cpuspernode > 56 or self.cpuspernode < 1:
-                    md = md.checkmessage('cpuspernode should be between 1 and 56 for ''bro'' processors in hyperthreading mode')
+                    md = md.checkmessage('cpuspernode should be between 1 and 56 for \'bro\' processors in hyperthreading mode')
             else:
                 if self.cpuspernode > 28 or self.cpuspernode < 1:
-                    md = md.checkmessage('cpuspernode should be between 1 and 28 for ''bro'' processors')
-        elif self.processor == 'har' or self.processor == 'neh':
-            if self.hyperthreading:
+                    md = md.checkmessage('cpuspernode should be between 1 and 28 for \'bro\' processors')
+        elif self.processor == 'has':
+            if self.hyperthreading:
+                if self.cpuspernode > 48 or self.cpuspernode < 1:
+                    md = md.checkmessage('cpuspernode should be between 1 and 48 for \'has\' processors in hyperthreading mode')
+            else:
+                if self.cpuspernode > 24 or self.cpuspernode < 1:
+                    md = md.checkmessage('cpuspernode should be between 1 and 24 for \'has\' processors')
+        elif self.processor == 'san':
+            if self.hyperthreading:
+                if self.cpuspernode > 32 or self.cpuspernode < 1:
+                    md = md.checkmessage('cpuspernode should be between 1 and 32 for \'san\' processors in hyperthreading mode')
+            else:
                 if self.cpuspernode > 16 or self.cpuspernode < 1:
-                    md = md.checkmessage('cpuspernode should be between 1 and 16 for ''neh'' and ''har'' processors in hyperthreading mode')
-            else:
-                if self.cpuspernode > 8 or self.cpuspernode < 1:
-                    md = md.checkmessage('cpuspernode should be between 1 and 8 for ''neh'' and ''har'' processors')
+                    md = md.checkmessage('cpuspernode should be between 1 and 16 for \'san\' processors')
+        elif self.processor == 'cas_ait':
+            if self.hyperthreading:
+                if self.cpuspernode > 80 or self.cpuspernode < 1:
+                    md = md.checkmessage('cpuspernode should be between 1 and 80 for \'cas_ait\' processors in hyperthreading mode')
+            else:
+                if self.cpuspernode > 40 or self.cpuspernode < 1:
+                    md = md.checkmessage('cpuspernode should be between 1 and 40 for \'cas_ait\' processors')
         else:
-            md = md.checkmessage('unknown processor type, should be \'ivy\', \'bro\', \'har\', or \'neh\'')
+            md = md.checkmessage('unknown processor type, should be \'bro\', \'has\', \'ivy\', \'san\', or \'cas_ait\'')
 
         # Miscellaneous
@@ -182,5 +189,5 @@
         compressstring = 'tar -zcf {}.tar.gz'.format(dirname)
         for file in filelist:
-            compressstring += file
+            compressstring += ' {}'.format(file)
         subprocess.call(compressstring, shell=True)
 
@@ -191,8 +198,18 @@
     # }}}
     def LaunchQueueJob(self, modelname, dirname, filelist, restart, batch):  # {{{
-        if restart:
-            launchcommand = 'cd {} && cd {} && qsub {}.queue'.format(self.executionpath, dirname, modelname)
+        # Launch command, to be executed via ssh
+        if self.interactive:
+            if restart:
+                launchcommand = 'cd {} /Interactive{}'.format(self.executionpath, self.interactive)
+            else:
+                if self.interactive == 10:
+                    launchcommand = 'cd {}/run && tar -zxf {}.tar.gz'.format(pwd(), dirname)
+                else:
+                    launchcommand = 'cd {} /Interactive{} && tar -zxf {}.tar.gz'.format(self.executionpath, self.interactive, dirname)
         else:
-            launchcommand = 'cd {} && rm -rf ./{} && mkdir {} && cd {} && mv ../{}.tar.gz ./ && tar -zxf {}.tar.gz  && qsub {}.queue'.format(self.executionpath, dirname, dirname, dirname, dirname, dirname, modelname)
+            if restart:
+                launchcommand = 'cd {} && cd {} && qsub {}.queue'.format(self.executionpath, dirname, modelname)
+            else:
+                launchcommand = 'cd {} && rm -rf ./{} && mkdir {} && cd {} && mv ../{}.tar.gz ./ && tar -zxf {}.tar.gz  && qsub {}.queue'.format(self.executionpath, dirname, dirname, dirname, dirname, dirname, modelname)
 
         print('launching solution sequence on remote cluster')
Index: /issm/trunk-jpl/src/m/classes/clusters/pollux.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/pollux.m	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/pollux.m	(revision 26332)
@@ -7,98 +7,98 @@
 
 classdef pollux
-    properties (SetAccess=public) 
-		 % {{{
-		 name='pollux'
-		 login='username';
-		 np=128;
-		 port=0;
-		 queue='shortp';
-		 time=180;
-		 codepath='/workc/edw/issm-2.0/bin'
-		 executionpath='/workc/edw/Testing/Execution'
-		 %}}}
-	 end
-	 methods
-		 function cluster=pollux(varargin) % {{{
-			 cluster=AssignObjectFields(pairoptions(varargin{:}),cluster);
-		 end
-		 %}}}
-		 function disp(cluster) % {{{
-			 %  display the object
-			 disp(sprintf('class ''%s'' object ''%s'' = ',class(cluster),inputname(1)));
-			 disp(sprintf('    name: %s',cluster.name));
-			 disp(sprintf('    login: %s',cluster.login));
-			 disp(sprintf('    port: %i',cluster.port));
-			 disp(sprintf('    np: %i',cluster.np));
-			 disp(sprintf('    queue: %s',cluster.queue));
-			 disp(sprintf('    time: %i',cluster.time));
-			 disp(sprintf('    codepath: %s',cluster.codepath));
-			 disp(sprintf('    executionpath: %s',cluster.executionpath));
-		 end
-		 %}}}
-		 function md = checkconsistency(cluster,md,solution,analyses) % {{{
+	properties (SetAccess=public)
+		% {{{
+		name='pollux'
+		login='username';
+		np=128;
+		port=0;
+		queue='shortp';
+		time=180;
+		codepath='/workc/edw/issm-2.0/bin'
+		executionpath='/workc/edw/Testing/Execution'
+		%}}}
+	end
+	methods
+		function cluster=pollux(varargin) % {{{
+			cluster=AssignObjectFields(pairoptions(varargin{:}),cluster);
+		end
+		%}}}
+		function disp(cluster) % {{{
+			%  display the object
+			disp(sprintf('class ''%s'' object ''%s'' = ',class(cluster),inputname(1)));
+			disp(sprintf('    name: %s',cluster.name));
+			disp(sprintf('    login: %s',cluster.login));
+			disp(sprintf('    port: %i',cluster.port));
+			disp(sprintf('    np: %i',cluster.np));
+			disp(sprintf('    queue: %s',cluster.queue));
+			disp(sprintf('    time: %i',cluster.time));
+			disp(sprintf('    codepath: %s',cluster.codepath));
+			disp(sprintf('    executionpath: %s',cluster.executionpath));
+		end
+		%}}}
+		function md = checkconsistency(cluster,md,solution,analyses) % {{{
 
-			 available_queues={'shortp','longp'};
-			 queue_requirements_time=[180 720];
-			 queue_requirements_np=[128 128];
+			available_queues={'shortp','longp'};
+			queue_requirements_time=[180 720];
+			queue_requirements_np=[128 128];
 
-			 QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.np,cluster.time)
-		 end
-		 %}}}
-		 function BuildQueueScript(cluster,dirname,modelname,solution,io_gather,isvalgrind,isgprof,isdakota,isoceancoupling) % {{{
+			QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.np,cluster.time)
+		end
+		%}}}
+		function BuildQueueScript(cluster,dirname,modelname,solution,io_gather,isvalgrind,isgprof,isdakota,isoceancoupling) % {{{
 
-			 if(isvalgrind), disp('valgrind not supported by cluster, ignoring...'); end
-			 if(isgprof),    disp('gprof not supported by cluster, ignoring...'); end
+			if(isvalgrind), disp('valgrind not supported by cluster, ignoring...'); end
+			if(isgprof),    disp('gprof not supported by cluster, ignoring...'); end
 
-			 %write queuing script 
-			 fid=fopen([modelname '.queue'],'w');
-			 fprintf(fid,'#!/bin/sh\n');
-			 fprintf(fid,'#PBS -l walltime=%i\n',cluster.time*60); %walltime is in seconds.
-			 fprintf(fid,'#PBS -N %s\n',modelname);
-			 fprintf(fid,'#PBS -l ncpus=%i\n',cluster.np);
-			 if ~isempty(queue),
-				 fprintf(fid,'#PBS -q %s\n',cluster.queue);
-			 end
-			 fprintf(fid,'#PBS -o %s.outlog \n',modelname);
-			 fprintf(fid,'#PBS -e %s.errlog \n',modelname);
-			 fprintf(fid,'export PBS_O_WORKDIR=%s\n',[cluster.executionpath '/' dirname]);
-			 fprintf(fid,'cd $PBS_O_WORKDIR\n');
-			 fprintf(fid,'export OMP_NUM_THREADS=1\n');
-			 fprintf(fid,'dplace -s1 -c0-%i mpiexec -np %i %s/issm.exe %s %s %s',cluster.np-1,cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
-			 fclose(fid);
+			%write queuing script 
+			fid=fopen([modelname '.queue'],'w');
+			fprintf(fid,'#!/bin/sh\n');
+			fprintf(fid,'#PBS -l walltime=%i\n',cluster.time*60); %walltime is in seconds.
+			fprintf(fid,'#PBS -N %s\n',modelname);
+			fprintf(fid,'#PBS -l ncpus=%i\n',cluster.np);
+			if ~isempty(queue),
+				fprintf(fid,'#PBS -q %s\n',cluster.queue);
+			end
+			fprintf(fid,'#PBS -o %s.outlog \n',modelname);
+			fprintf(fid,'#PBS -e %s.errlog \n',modelname);
+			fprintf(fid,'export PBS_O_WORKDIR=%s\n',[cluster.executionpath '/' dirname]);
+			fprintf(fid,'cd $PBS_O_WORKDIR\n');
+			fprintf(fid,'export OMP_NUM_THREADS=1\n');
+			fprintf(fid,'dplace -s1 -c0-%i mpiexec -np %i %s/issm.exe %s %s %s',cluster.np-1,cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
+			fclose(fid);
 
-		 end
-		 %}}}
-		 function LaunchQueueJob(cluster,modelname,dirname,filelist,restart)% {{{
+		end
+		%}}}
+		function LaunchQueueJob(cluster,modelname,dirname,filelist,restart) % {{{
 
-			 disp('launching solution sequence on remote cluster');
-			 if ~isempty(restart)
-				 launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && qsub ' modelname '.queue '];
-			 else
-				 launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ...
-					 ' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz  && qsub ' modelname '.queue '];
-			 end
-			 issmssh(cluster.name,cluster.login,cluster.port,launchcommand);
-		 end %}}}
-		 function UploadQueueJob(cluster,modelname,dirname,filelist)% {{{
+			disp('launching solution sequence on remote cluster');
+			if ~isempty(restart)
+				launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && qsub ' modelname '.queue '];
+			else
+				launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ...
+					' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz  && qsub ' modelname '.queue '];
+			end
+			issmssh(cluster.name,cluster.login,cluster.port,launchcommand);
+		end %}}}
+		function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{
 
-			 %compress the files into one zip.
-			 compressstring=['tar -zcf ' dirname '.tar.gz '];
-			 for i=1:numel(filelist),
-				 compressstring = [compressstring ' ' filelist{i}];
-			 end
-			 if cluster.interactive,
-				 compressstring = [compressstring ' ' modelname '.errlog ' modelname '.outlog '];
-			 end
-			 system(compressstring);
+			%compress the files into one zip.
+			compressstring=['tar -zcf ' dirname '.tar.gz '];
+			for i=1:numel(filelist),
+				compressstring = [compressstring ' ' filelist{i}];
+			end
+			if cluster.interactive,
+				compressstring = [compressstring ' ' modelname '.errlog ' modelname '.outlog '];
+			end
+			system(compressstring);
 
-		 end %}}}
-		 function Download(cluster,dirname,filelist)% {{{
+		end %}}}
+		function Download(cluster,dirname,filelist) % {{{
 
-			 %copy files from cluster to current directory
-			 directory=[cluster.executionpath '/' dirname '/'];
-			 issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist);
+			%copy files from cluster to current directory
+			directory=[cluster.executionpath '/' dirname '/'];
+			issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist);
 
-		 end %}}}
+		end %}}}
 	end
 end
Index: /issm/trunk-jpl/src/m/classes/clusters/raijin.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/raijin.m	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/raijin.m	(revision 26332)
@@ -7,119 +7,121 @@
 
 classdef raijin
-    properties (SetAccess=public)  
-		 % {{{
-		 name='';
-		 login='';
-		 np=0;
-                 mem=0;
-                 time=0;
-                 project='';
-                 email='';
-		 port=0;
-		 queue='';
-		 codepath='';
-		 executionpath='';
-                 modules={};
-	 end
-	 %}}}
-	 methods
-		 function cluster=raijin(varargin) % {{{
+	properties (SetAccess=public)
+		% {{{
+		name='';
+		login='';
+		np=0;
+		mem=0;
+		time=0;
+		project='';
+		email='';
+		port=0;
+		queue='';
+		codepath='';
+		executionpath='';
+		modules={};
+	end
+	%}}}
+	methods
+		function cluster=raijin(varargin) % {{{
 
-			 %initialize cluster using default settings if provided
-			 if (exist('raijin_settings')==2), raijin_settings; end
+			%initialize cluster using default settings if provided
+			if (exist('raijin_settings')==2), raijin_settings; end
 
-			 %use provided options to change fields
-			 cluster=AssignObjectFields(pairoptions(varargin{:}),cluster);
-		 end
-		 %}}}
-		 function disp(cluster) % {{{
-			 %  display the object
-			 disp(sprintf('class ''%s'' object ''%s'' = ',class(cluster),inputname(1)));
-			 disp(sprintf('    name: %s',cluster.name));
-			 disp(sprintf('    login: %s',cluster.login));
-			 disp(sprintf('    port: %i',cluster.port));
-			 disp(sprintf('    mem: %i',cluster.mem));
-			 disp(sprintf('    time: %i',cluster.time));
-			 disp(sprintf('    np: %i',cluster.np));
-			 disp(sprintf('    queue: %s',cluster.queue));
-                         disp(sprintf('    project: %s',cluster.project));
-			 disp(sprintf('    codepath: %s',cluster.codepath));
-			 disp(sprintf('    executionpath: %s',cluster.executionpath));
-		 end
-		 %}}}
-		 function md = checkconsistency(cluster,md,solution,analyses) % {{{
+			%use provided options to change fields
+			cluster=AssignObjectFields(pairoptions(varargin{:}),cluster);
+		end
+		%}}}
+		function disp(cluster) % {{{
+			%  display the object
+			disp(sprintf('class ''%s'' object ''%s'' = ',class(cluster),inputname(1)));
+			disp(sprintf('    name: %s',cluster.name));
+			disp(sprintf('    login: %s',cluster.login));
+			disp(sprintf('    np: %i',cluster.np));
+			disp(sprintf('    mem: %i',cluster.mem));
+			disp(sprintf('    time: %i',cluster.time));
+			disp(sprintf('    project: %s',cluster.project));
+			disp(sprintf('    email: %s',cluster.email));
+			disp(sprintf('    port: %i',cluster.port));
+			disp(sprintf('    queue: %s',cluster.queue));
+			disp(sprintf('    codepath: %s',cluster.codepath));
+			disp(sprintf('    executionpath: %s',cluster.executionpath));
+			disp(sprintf('    modules: %s',strjoin(cluster.modules,', ')));
+		end
+		%}}}
+		function md = checkconsistency(cluster,md,solution,analyses) % {{{
 
-			 available_queues={'express', 'normal'};
-			 queue_requirements_time=[5*60 40*60];
-			 queue_requirements_np=[256 1024];
+			available_queues={'express', 'normal'};
+			queue_requirements_time=[5*60 40*60];
+			queue_requirements_np=[256 1024];
 
-			 QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.np,1)
+			QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.np,1)
 
-			 %Miscelaneous
-			 if isempty(cluster.login), md = checkmessage(md,'login empty'); end
-			 if isempty(cluster.codepath), md = checkmessage(md,'codepath empty'); end
-			 if isempty(cluster.executionpath), md = checkmessage(md,'executionpath empty'); end
+			%Miscellaneous
+			if isempty(cluster.login), md = checkmessage(md,'login empty'); end
+			if isempty(cluster.codepath), md = checkmessage(md,'codepath empty'); end
+			if isempty(cluster.executionpath), md = checkmessage(md,'executionpath empty'); end
 
-		 end
-		 %}}}
-		 function BuildQueueScript(cluster,dirname,modelname,solution,io_gather,isvalgrind,isgprof,isdakota,isoceancoupling) % {{{
-                     
-			 if(isvalgrind), disp('valgrind not supported by cluster, ignoring...'); end
-			 if(isgprof),    disp('gprof not supported by cluster, ignoring...'); end
+		end
+		%}}}
+		function BuildQueueScript(cluster,dirname,modelname,solution,io_gather,isvalgrind,isgprof,isdakota,isoceancoupling) % {{{
 
-			 %write queuing script 
-			 fid=fopen([modelname '.queue'],'w');
-                         fprintf(fid,'#PBS -S /bin/bash\n');
-                         fprintf(fid,'#PBS -P %s\n', cluster.project);
-                         fprintf(fid,'#PBS -q %s\n',cluster.queue);
-                         fprintf(fid,'#PBS -l ncpus=%i\n',cluster.np);
-                         fprintf(fid,'#PBS -l walltime=%i\n',cluster.time*60); % walltime is in seconds
-                         fprintf(fid,'#PBS -l mem=%igb\n', cluster.mem);
-                         fprintf(fid,'#PBS -M %s\n', cluster.email);
-                         fprintf(fid,'#PBS -o %s.outlog\n',(modelname));
-                         fprintf(fid,'#PBS -e %s.errlog\n',(modelname));
-                         fprintf(fid,'#PBS -l wd\n\n');
-                         fprintf(fid,'source ~/.bashrc\n');
-                         fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n');
-                         for i=1:numel(cluster.modules)
-                             fprintf(fid,'module load %s\n', cluster.modules{i});
-                         end
-			 fprintf(fid,'mpiexec -np %i %s/issm.exe %s %s %s\n',cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
-			 if ~io_gather, %concatenate the output files:
-				 fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname);
-			 end
-			 fclose(fid);
-		 end %}}}
-		 function UploadQueueJob(cluster,modelname,dirname,filelist)% {{{
+			if(isvalgrind), disp('valgrind not supported by cluster, ignoring...'); end
+			if(isgprof),    disp('gprof not supported by cluster, ignoring...'); end
 
-			 %compress the files into one zip.
-			 compressstring=['tar -zcf ' dirname '.tar.gz '];
-			 for i=1:numel(filelist),
-				 compressstring = [compressstring ' ' filelist{i}];
-			 end
-			 system(compressstring);
+			%write queuing script
+			fid=fopen([modelname '.queue'],'w');
+			fprintf(fid,'#PBS -S /bin/bash\n');
+			fprintf(fid,'#PBS -P %s\n', cluster.project);
+			fprintf(fid,'#PBS -q %s\n',cluster.queue);
+			fprintf(fid,'#PBS -l ncpus=%i\n',cluster.np);
+			fprintf(fid,'#PBS -l walltime=%i\n',cluster.time*60); % walltime is in seconds
+			fprintf(fid,'#PBS -l mem=%igb\n', cluster.mem);
+			fprintf(fid,'#PBS -M %s\n', cluster.email);
+			fprintf(fid,'#PBS -o %s.outlog\n',(modelname));
+			fprintf(fid,'#PBS -e %s.errlog\n',(modelname));
+			fprintf(fid,'#PBS -l wd\n\n');
+			fprintf(fid,'source ~/.bashrc\n');
+			fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n');
+			for i=1:numel(cluster.modules)
+				fprintf(fid,'module load %s\n', cluster.modules{i});
+			end
+			fprintf(fid,'mpiexec -np %i %s/issm.exe %s %s %s\n',cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
+			if ~io_gather, %concatenate the output files:
+				fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname);
+			end
+			fclose(fid);
+		end %}}}
+		function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{
 
-			 disp('uploading input file and queueing script');
-			 issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
+			%compress the files into one zip.
+			compressstring=['tar -zcf ' dirname '.tar.gz '];
+			for i=1:numel(filelist),
+				compressstring = [compressstring ' ' filelist{i}];
+			end
+			system(compressstring);
 
-		 end %}}}
-		 function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch)% {{{
-                         
-			 disp('launching solution sequence on remote cluster');
-			 if ~isempty(restart)
-				 launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && hostname && qsub ' modelname '.queue '];
-			 else
-				 launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ...
-					 ' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz  && hostname && qsub ' modelname '.queue '];
-			 end
-			 issmssh(cluster.name,cluster.login,cluster.port,launchcommand);
-		 end %}}}
-		 function Download(cluster,dirname,filelist)% {{{
+			disp('uploading input file and queueing script');
+			issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']});
 
-			 %copy files from cluster to current directory
-			 directory=[cluster.executionpath '/' dirname '/'];
-			 issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist);
+		end %}}}
+		function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{
+			
+			disp('launching solution sequence on remote cluster');
+			if ~isempty(restart)
+				launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && hostname && qsub ' modelname '.queue '];
+			else
+				launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ...
+					' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz  && hostname && qsub ' modelname '.queue '];
+			end
+			issmssh(cluster.name,cluster.login,cluster.port,launchcommand);
+		end %}}}
+		function Download(cluster,dirname,filelist) % {{{
 
-		 end %}}}
+			%copy files from cluster to current directory
+			directory=[cluster.executionpath '/' dirname '/'];
+			issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist);
+
+		end %}}}
 	end
 end
Index: /issm/trunk-jpl/src/m/classes/clusters/saga.py
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/saga.py	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/saga.py	(revision 26332)
@@ -15,10 +15,10 @@
 
 class saga(object):
-    """
-    Saga cluster class definition
+    """SAGA cluster class definition
+
     This is a SLURM queue
 
-       Usage:
-          cluster = saga()
+    Usage:
+        cluster = saga()
     """
 
@@ -44,9 +44,9 @@
         self.valgrind = '/cluster/software/Valgrind/3.16.1-gompi-2019b/bin/valgrind'
 
-    #use provided options to change fields
+        # Use provided options to change fields
         options = pairoptions(*args)
-    #initialize cluster using user settings if provided
+        # Initialize cluster using user settings if provided
         self = saga_settings(self)
-    #OK get other fields
+        # OK get other fields
         self = options.AssignObjectFields(self)
         self.np = self.numnodes * self.cpuspernode
@@ -54,5 +54,5 @@
 
     def __repr__(self):  # {{{
-        #  display the object
+        # Display the object
         s = "class vilje object:"
         s = "%s\n%s" % (s, fielddisplay(self, 'name', 'name of the cluster'))
@@ -72,5 +72,5 @@
 
     def checkconsistency(self, md, solution, analyses):  # {{{
-        #Queue dictionarry  gives queue name as key and max walltime, cpus and memory (GB) as var
+        # Queue dictionarry  gives queue name as key and max walltime, CPUs, and memory (GB) as var
         queuedict = {'normal': [7 * 24 * 60, 256, 8],
                      'bigmem': [14 * 24 * 60, 256, 10],
@@ -78,5 +78,5 @@
         QueueRequirements(queuedict, self.queue, self.np, self.time)
 
-    #Miscelaneous
+        # Miscellaneous
         if not self.login:
             md = md.checkmessage('login empty')
@@ -91,5 +91,4 @@
 
     def BuildQueueScript(self, dirname, modelname, solution, io_gather, isvalgrind, isgprof, isdakota, isoceancoupling):  # {{{
-
         executable = 'issm.exe'
         if isdakota:
@@ -100,5 +99,5 @@
         if isoceancoupling:
             executable = 'issm_ocean.exe'
-    #write queuing script
+        # Write queuing script
         shortname = modelname[0:min(12, len(modelname))]
         timeobj = datetime.timedelta(minutes=self.time)
@@ -146,17 +145,15 @@
     # }}}
     def UploadQueueJob(self, modelname, dirname, filelist):  # {{{
-        #compress the files into one zip.
+        # Compress the files into one zip
         compressstring = 'tar -zcf %s.tar.gz ' % dirname
         for file in filelist:
-            compressstring += ' %s' % file
+            compressstring += ' {}'.format(file)
         subprocess.call(compressstring, shell=True)
 
         print('uploading input file and queueing script')
         issmscpout(self.name, self.executionpath, self.login, self.port, [dirname + '.tar.gz'])
-
     # }}}
 
     def LaunchQueueJob(self, modelname, dirname, filelist, restart, batch):  # {{{
-
         print('launching solution sequence on remote cluster')
         if restart:
@@ -165,9 +162,8 @@
             launchcommand = 'cd %s && rm -rf ./%s && mkdir %s && cd %s && mv ../%s.tar.gz ./ && tar -zxf %s.tar.gz  && sbatch %s.queue' % (self.executionpath, dirname, dirname, dirname, dirname, dirname, modelname)
         issmssh(self.name, self.login, self.port, launchcommand)
-
     # }}}
 
     def Download(self, dirname, filelist):  # {{{
-        #copy files from cluster to current directory
+        # Copy files from cluster to current directory
         directory = '%s/%s/' % (self.executionpath, dirname)
         issmscpin(self.name, self.login, self.port, directory, filelist)
Index: /issm/trunk-jpl/src/m/classes/clusters/sherlock.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/sherlock.m	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/sherlock.m	(revision 26332)
@@ -36,8 +36,8 @@
 			disp(sprintf('    name: %s',cluster.name));
 			disp(sprintf('    login: %s',cluster.login));
-			disp(sprintf('    port: %i',cluster.port));
 			disp(sprintf('    numnodes: %i',cluster.numnodes));
 			disp(sprintf('    cpuspernode: %i',cluster.cpuspernode));
-			disp(sprintf('    np: %i',cluster.cpuspernode*cluster.numnodes));
+			disp(sprintf('    np: %i',cluster.nprocs()));
+			disp(sprintf('    port: %i',cluster.port));
 			disp(sprintf('    codepath: %s',cluster.codepath));
 			disp(sprintf('    executionpath: %s',cluster.executionpath));
@@ -54,5 +54,5 @@
 		function md = checkconsistency(cluster,md,solution,analyses) % {{{
 
-			%Miscelaneous
+			%Miscellaneous
 			if isempty(cluster.login), md = checkmessage(md,'login empty'); end
 			if isempty(cluster.codepath), md = checkmessage(md,'codepath empty'); end
@@ -79,5 +79,5 @@
 			fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n');       %FIXME
 			fprintf(fid,'cd %s/%s\n\n',cluster.executionpath,dirname);
-			fprintf(fid,'mpiexec -np %i %s/kriging.exe %s %s\n',cluster.np,cluster.codepath,[cluster.executionpath '/' modelname],modelname);
+			fprintf(fid,'mpiexec -np %i %s/kriging.exe %s %s\n',cluster.nprocs(),cluster.codepath,[cluster.executionpath '/' modelname],modelname);
 			if ~io_gather, %concatenate the output files:
 				fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname);
@@ -103,5 +103,5 @@
 			fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n');       %FIXME
 			fprintf(fid,'cd %s/%s\n\n',cluster.executionpath,dirname);
-			fprintf(fid,'mpiexec -n %i %s/issm.exe %s %s %s\n',cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
+			fprintf(fid,'mpiexec -n %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
 			if ~io_gather, %concatenate the output files:
 				fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname);
@@ -112,5 +112,5 @@
 			if cluster.interactive,
 				fid=fopen([modelname '.run'],'w');
-				fprintf(fid,'mpiexec -n %i %s/issm.exe %s %s %s\n',cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
+				fprintf(fid,'mpiexec -n %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
 				if ~io_gather, %concatenate the output files:
 					fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname);
Index: /issm/trunk-jpl/src/m/classes/clusters/tetralith.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/tetralith.m	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/tetralith.m	(revision 26332)
@@ -38,14 +38,15 @@
 			disp(sprintf('    name: %s',cluster.name));
 			disp(sprintf('    login: %s',cluster.login));
-			disp(sprintf('    accountname: %s',cluster.accountname));
 			disp(sprintf('    numnodes: %i',cluster.numnodes));
 			disp(sprintf('    cpuspernode: %i',cluster.cpuspernode));
-			disp(sprintf('    np: %i', cluster.cpuspernode*cluster.numnodes));
+			disp(sprintf('    np: %i',cluster.nprocs()));
+			disp(sprintf('    memory: %i',cluster.mem));
 			disp(sprintf('    queue: %s',cluster.queue));
+			disp(sprintf('    time: %i',cluster.time));
 			disp(sprintf('    codepath: %s',cluster.codepath));
 			disp(sprintf('    executionpath: %s',cluster.executionpath));
 			disp(sprintf('    interactive: %i',cluster.interactive));
-			disp(sprintf('    time: %i',cluster.time));
-			disp(sprintf('    memory: %i',cluster.mem));
+			disp(sprintf('    port: %s',cluster.port));
+			disp(sprintf('    accountname: %s',cluster.accountname));
 		end
 		%}}}
@@ -56,7 +57,7 @@
 			queue_requirements_np=[1024 2*32];
 
-			QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.np,1)
-
-			%Miscelaneous
+			QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.nprocs(),1)
+
+			%Miscellaneous
 			if isempty(cluster.login), md = checkmessage(md,'login empty'); end
 			if isempty(cluster.accountname), md = checkmessage(md,'accountname empty'); end
@@ -78,5 +79,5 @@
 			%compute number of processors
 % 			cluster.np=cluster.numnodes*cluster.cpuspernode;
-			nprocs(cluster);%=cluster.numnodes*cluster.cpuspernode;
+%			nprocs(cluster);%=cluster.numnodes*cluster.cpuspernode;
 
 			%write queuing script 
@@ -104,8 +105,8 @@
 			fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n');       %FIXME
 			fprintf(fid,'cd %s/%s\n\n',cluster.executionpath,dirname);
-% 			fprintf(fid,'mpiexec -np %i %s/%s %s %s %s\n',cluster.np,cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname);
+% 			fprintf(fid,'mpiexec -np %i %s/%s %s %s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname);
 % 			fprintf(fid,'mpiexec_mpt -np %i %s/%s %s %s %s\n',cluster.np,cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname);
-			fprintf(fid,'mpiexec -np %i %s/issm.exe %s %s %s\n',cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
-% 			fprintf(fid,'mpirun -np %i %s/issm.exe %s %s %s\n',cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
+			fprintf(fid,'mpiexec -np %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
+% 			fprintf(fid,'mpirun -np %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
 			if ~io_gather, %concatenate the output files:
 				fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname);
@@ -159,8 +160,8 @@
 			fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n');       %FIXME
 			fprintf(fid,'cd %s/%s\n\n',cluster.executionpath,dirname);
-% 			fprintf(fid,'mpiexec -np %i %s/%s %s %s %s\n',cluster.np,cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname);
-			fprintf(fid,'mpiexec -np %i %s/issm.exe %s %s %s\n',cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
-% 			fprintf(fid,'mpirun -np %i %s/issm.exe %s %s %s\n',cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
-% 			fprintf(fid,'mpiexec_mpt -np %i %s/%s %s %s %s\n',cluster.np,cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname);
+% 			fprintf(fid,'mpiexec -np %i %s/%s %s %s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname);
+			fprintf(fid,'mpiexec -np %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
+% 			fprintf(fid,'mpirun -np %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
+% 			fprintf(fid,'mpiexec_mpt -np %i %s/%s %s %s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname);
 
 			if ~io_gather, %concatenate the output files:
@@ -172,5 +173,5 @@
 			if cluster.interactive,
 				fid=fopen([modelname '.run'],'w');
-				fprintf(fid,'mpiexec_mpt -np %i %s/issm.exe %s %s %s\n',cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
+				fprintf(fid,'mpiexec_mpt -np %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname);
 				if ~io_gather, %concatenate the output files:
 					fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname);
Index: /issm/trunk-jpl/src/m/classes/clusters/yellowstone.m
===================================================================
--- /issm/trunk-jpl/src/m/classes/clusters/yellowstone.m	(revision 26331)
+++ /issm/trunk-jpl/src/m/classes/clusters/yellowstone.m	(revision 26332)
@@ -38,10 +38,9 @@
 			disp(sprintf('    name: %s',cluster.name));
 			disp(sprintf('    login: %s',cluster.login));
-			modules=''; for i=1:length(cluster.modules), modules=[modules cluster.modules{i} ',']; end; modules=modules(1:end-1); 
-			disp(sprintf('    modules: %s',modules));
-			disp(sprintf('    port: %i',cluster.port));
+			disp(sprintf('    modules: %s',strjoin(cluster.modules,', ')));
 			disp(sprintf('    numnodes: %i',cluster.numnodes));
 			disp(sprintf('    cpuspernode: %i',cluster.cpuspernode));
-			disp(sprintf('    np: %i',cluster.cpuspernode*cluster.numnodes));
+			disp(sprintf('    np: %i',cluster.nprocs()));
+			disp(sprintf('    port: %i',cluster.port));
 			disp(sprintf('    queue: %s',cluster.queue));
 			disp(sprintf('    time: %i',cluster.time));
@@ -63,7 +62,7 @@
 			queue_requirements_np=[16384 16384];
 
-			QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.np,cluster.time)
+			QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.nprocs(),cluster.time)
 
-			%Miscelaneous
+			%Miscellaneous
 			if isempty(cluster.login), md = checkmessage(md,'login empty'); end
 			if isempty(cluster.codepath), md = checkmessage(md,'codepath empty'); end
@@ -92,5 +91,5 @@
 			fprintf(fid,'#BSUB -P %s\n',cluster.grouplist);
 			fprintf(fid,'#BSUB -W %i:%i\n',floor(cluster.time/60),cluster.time-floor(cluster.time/60)*60);
-			fprintf(fid,'#BSUB -n %i\n',cluster.np);
+			fprintf(fid,'#BSUB -n %i\n',cluster.nprocs());
 			fprintf(fid,'#BSUB -J %s\n',modelname);
 			fprintf(fid,'#BSUB -o %s.outlog \n',[cluster.executionpath '/' dirname '/' modelname]);
@@ -138,5 +137,5 @@
 		function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{
 
-			%lauch command, to be executed via ssh
+			%launch command, to be executed via ssh
 			launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ...
 						' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz  && bsub < ' modelname '.queue '];
Index: /issm/trunk-jpl/src/m/dev/ISSM.py
===================================================================
--- /issm/trunk-jpl/src/m/dev/ISSM.py	(revision 26331)
+++ /issm/trunk-jpl/src/m/dev/ISSM.py	(revision 26332)
@@ -4,5 +4,4 @@
 import scipy.io as spio
 from model import *
-from socket import gethostname
 from triangle import *
 from setmask import *
@@ -10,5 +9,6 @@
 from setflowequation import *
 from solve import *
-from IssmConfing import *
+from IssmConfig import *
+from MatlabFuncs import *
 
 #Secondary imports
Index: /issm/trunk-jpl/src/m/miscellaneous/MatlabFuncs.py
===================================================================
--- /issm/trunk-jpl/src/m/miscellaneous/MatlabFuncs.py	(revision 26331)
+++ /issm/trunk-jpl/src/m/miscellaneous/MatlabFuncs.py	(revision 26332)
@@ -1,2 +1,11 @@
+"""
+A collection of functions that replicate the behavior of MATLAB built-in
+functions of the same, respective name.
+
+Where possible, users are encouraged to use native and/or the most efficient 
+methods in Python, but we provide these functions as a way to make translations 
+from the MATLAB to the Python ISSM API more seamless.
+"""
+
 def acosd(X): #{{{
     """ function acosd - Inverse cosine in degrees
@@ -55,4 +64,20 @@
 #}}}
 
+def find(*args): #{{{
+    nargs = len(args)
+    if nargs >= 1 or nargs <= 2:
+        X = args[0]
+        n = len(args[0])
+        if nargs == 2:
+            n = args[1]
+        indices=[]
+        for i in range(n):
+            if X[i] != 0:
+                indices.push(i)
+        return indices
+    else:
+        raise Exception('find: must have 1 or 2 arguments')
+#}}}
+
 def heaviside(x): #{{{
     import numpy as np
@@ -105,4 +130,8 @@
 #}}}
 
+def mod(a, m): #{{{
+    return a % m
+#}}}
+
 def oshostname(): #{{{
     import socket
@@ -141,4 +170,15 @@
 #}}}
 
+def strjoin(*args): #{{{
+    nargs = len(args)
+    if nargs >= 1 or nargs <= 2:
+        sep = ' '
+        if nargs == 2:
+            sep = args[1]
+        return sep.join(args[0])
+    else:
+        raise Exception('strjoin: must have 1 or 2 arguments')
+#}}}
+
 def strncmp(s1, s2, n): #{{{
     if s1[0:n] == s2[0:n]:
Index: /issm/trunk-jpl/src/m/os/issmscpin.py
===================================================================
--- /issm/trunk-jpl/src/m/os/issmscpin.py	(revision 26331)
+++ /issm/trunk-jpl/src/m/os/issmscpin.py	(revision 26332)
@@ -1,17 +1,17 @@
-from socket import gethostname
-import subprocess
 import os
 import shutil
-import MatlabFuncs as m
+import subprocess
+from MatlabFuncs import *
 
 
 def issmscpin(host, login, port, path, packages):
-    """
-    ISSMSCPIN get packages from host, using scp on unix, and pscp on windows
-       usage: issmscpin(host, packages, path)
+    """ISSMSCPIN get packages from host, using scp on unix, and pscp on windows
+
+    Usage:
+        issmscpin(host, packages, path)
     """
 
     #first get hostname
-    hostname = gethostname()
+    hostname = oshostname()
     #first be sure packages are not in the current directory, this could conflict with pscp on windows.
     #remove warnings in case the files do not exist
@@ -29,5 +29,5 @@
                 pass
     else:
-        if m.ispc():
+        if ispc():
             #use the putty project pscp.exe: it should be in the path.
             #get ISSM_DIR variable
Index: /issm/trunk-jpl/src/m/os/issmscpout.m
===================================================================
--- /issm/trunk-jpl/src/m/os/issmscpout.m	(revision 26331)
+++ /issm/trunk-jpl/src/m/os/issmscpout.m	(revision 26332)
@@ -9,5 +9,5 @@
 hostname=oshostname();
 
-%are we dis-allowing symbolic links? 
+%are we disallowing symbolic links? 
 if nargin==6,
 	no_symlinks=1;
Index: /issm/trunk-jpl/src/m/os/issmscpout.py
===================================================================
--- /issm/trunk-jpl/src/m/os/issmscpout.py	(revision 26331)
+++ /issm/trunk-jpl/src/m/os/issmscpout.py	(revision 26332)
@@ -1,17 +1,17 @@
+import os
 from socket import gethostname
 import subprocess
-import os
-import MatlabFuncs as m
+from MatlabFuncs import *
 
 
 def issmscpout(host, path, login, port, packages):
-    """
-    ISSMSCPOUT send packages to a host, using scp on unix, and pscp on windows
+    """ISSMSCPOUT send packages to a host, using scp on unix, and pscp on windows
 
-       usage: issmscpout(host, path, packages)
+    Usage:
+        issmscpout(host, path, packages)
     """
 
     #get hostname
-    hostname = gethostname()
+    hostname = oshostname()
 
     #if hostname and host are the same, do a simple copy
@@ -28,5 +28,5 @@
             os.chdir(here)
     else:
-        if m.ispc():
+        if ispc():
             #use the putty project pscp.exe: it should be in the path.
             #get ISSM_DIR variable
Index: /issm/trunk-jpl/src/m/os/issmssh.py
===================================================================
--- /issm/trunk-jpl/src/m/os/issmssh.py	(revision 26331)
+++ /issm/trunk-jpl/src/m/os/issmssh.py	(revision 26332)
@@ -1,25 +1,23 @@
-from socket import gethostname
+import os
+import subprocess
 from sys import platform as _platform
-import subprocess
-import os
-import MatlabFuncs as m
+from MatlabFuncs import *
 
 
 def issmssh(host, login, port, command):
-    """
-    ISSMSSH - wrapper for OS independent ssh command.
+    """ISSMSSH - wrapper for OS independent ssh command.
 
-       usage:
-          issmssh(host, command)
+    Usage:
+        issmssh(host, command)
     """
 
     #first get hostname
-    hostname = gethostname()
+    hostname = oshostname()
 
     #if same as host, just run the command.
-    if m.strcmpi(host, hostname):
+    if strcmpi(host, hostname):
         subprocess.call(command, shell=True)
     else:
-        if m.ispc():
+        if ispc():
             #use the putty project plink.exe: it should be in the path.
             #get ISSM_DIR variable
Index: /issm/trunk-jpl/src/m/solve/loadresultsfromcluster.py
===================================================================
--- /issm/trunk-jpl/src/m/solve/loadresultsfromcluster.py	(revision 26331)
+++ /issm/trunk-jpl/src/m/solve/loadresultsfromcluster.py	(revision 26332)
@@ -1,7 +1,6 @@
 import os
-import socket
 from helpers import *
 from loadresultsfromdisk import loadresultsfromdisk
-from MatlabFuncs import ispc
+from MatlabFuncs import *
 from pairoptions import pairoptions
 
@@ -63,5 +62,5 @@
 
     # Erase input file if run was carried out on same platform
-    hostname = socket.gethostname()
+    hostname = oshostname()
     if hostname == cluster.name:
         remove(md.miscellaneous.name + '.bin')
Index: /issm/trunk-jpl/src/m/solve/waitonlock.py
===================================================================
--- /issm/trunk-jpl/src/m/solve/waitonlock.py	(revision 26331)
+++ /issm/trunk-jpl/src/m/solve/waitonlock.py	(revision 26332)
@@ -1,17 +1,14 @@
 import os
-from socket import gethostname
 import time
-import MatlabFuncs as m
-
+from MatlabFuncs import *
 
 def waitonlock(md):
-    """
-    WAITONLOCK - wait for a file
+    """WAITONLOCK - wait for a file
 
-       This routine will return when a file named 'filename' is written to disk.
-       If the time limit given in input is exceeded, return 0
+    This routine will return when a file named 'filename' is written to disk.
+    If the time limit given in input is exceeded, return 0
 
-       Usage:
-          flag = waitonlock(md)
+    Usage:
+        flag = waitonlock(md)
     """
 
@@ -23,9 +20,9 @@
 
     #waitonlock will work if the lock is on the same machine only:
-    if not m.strcmpi(gethostname(), cluster):
+    if not strcmpi(oshostname(), cluster):
 
         print('solution launched on remote cluster. log in to detect job completion.')
         choice = eval(input('Is the job successfully completed? (y / n) '))
-        if not m.strcmp(choice, 'y'):
+        if not strcmp(choice, 'y'):
             print('Results not loaded... exiting')
             flag = 0
@@ -35,5 +32,4 @@
     #job is running on the same machine
     else:
-
         if 'interactive' in vars(md.cluster) and md.cluster.interactive:
             #We are in interactive mode, no need to check for job completion
