function md=solve(md,solutionenum,varargin)
%SOLVE - apply solution sequence for this model
%
%   Usage:
%      md=solve(md,solutionenum,varargin)
%      where varargin is a lit of paired arguments of string OR enums
%
%   solution types available comprise:
%		 - StressbalanceSolutionEnum
%		 - MasstransportSolutionEnum
%		 - ThermalSolutionEnum
%		 - SteadystateSolutionEnum
%		 - TransientSolutionEnum...
%		 - BalancethicknessSolutionEnum
%		 - BedSlopeSolutionEnum
%		 - SurfaceSlopeSolutionEnum
%		 - HydrologySolutionEnum
%		 - FlaimSolutionEnum
%
%  extra options:
%      - loadonly    : does not solve. only load results
%      - runtimename : true or false (default is true), makes name unique
%
%   Examples:
%      md=solve(md,StressbalanceSolutionEnum);

%recover and process solve options
options=pairoptions(varargin{:},'solution_type',solutionenum);
options=process_solve_options(options);

%recover some fields
md.private.solution=options.solution_type;
cluster=md.cluster;

%check model consistency
if md.verbose.solution,
	disp('checking model consistency');
end
if (solutionenum == FlaimSolutionEnum())
	md.private.isconsistent=true;
	md=checkconsistency(md.mesh,md,solutionenum);
	md=checkconsistency(md.flaim,md,solutionenum);
	if md.private.isconsistent==false,
		error('Model not consistent, see messages above');
	end
else
	ismodelselfconsistent(md),
end

%First, build a runtime name that is unique
if options.runtimename,
	c=clock;
	md.private.runtimename=sprintf('%s-%02i-%02i-%04i-%02i-%02i-%02i-%i',md.miscellaneous.name,c(2),c(3),c(1),c(4),c(5),floor(c(6)),feature('GetPid'));
else
	md.private.runtimename=md.miscellaneous.name;
end

%if running qmu analysis, some preprocessing of dakota files using models
%fields needs to be carried out. 
if md.qmu.isdakota,
	md=preqmu(md,options);
end

%flaim analysis
if (options.solution_type == FlaimSolutionEnum())
	md=flaim_sol(md,options);
	md.private.solution=EnumToString(options.solution_type);
	return;
end

%Do we load results only?
if options.loadonly,  
	md=loadresultsfromcluster(md);
	return;
end

%Write all input files
marshall(md);                                          % bin file
ToolkitsFile(md.toolkits,[md.miscellaneous.name '.toolkits']); % toolkits file
BuildQueueScript(cluster,md.private.runtimename,md.miscellaneous.name,md.private.solution,md.settings.io_gather,md.debug.valgrind,md.debug.gprof); % queue file

%Stop here if batch mode
if strcmpi(options.batch,'yes')
	if md.verbose.solution,
		disp('batch mode requested: not launching job interactively');
		disp('launch solution sequence on remote cluster by hand');
	end
	return;
end

%Launch job
modelname = md.miscellaneous.name;
filelist  = {[modelname '.bin '] [modelname '.toolkits ']};
if ispc,
	filelist{end+1}=[modelname '.bat '];
else
	filelist{end+1}=[modelname '.queue '];
end

if md.qmu.isdakota,
	filelist{end+1} = [modelname '.qmu.in'];
end
LaunchQueueJob(cluster,md.miscellaneous.name,md.private.runtimename,filelist);

%did we even try to run? if so, wait on lock
if strcmpi(options.upload,'on'),
	if md.verbose.solution,
		disp('solve done uploading test decks');
	end
	return;
end

%wait on lock
if isnan(md.settings.waitonlock),
	%load when user enters 'y'
	disp('solution launched on remote cluster. log in to detect job completion.');
	choice=input('Is the job successfully completed? (y/n)','s');
	if ~strcmp(choice,'y'), 
		disp('Results not loaded... exiting'); 
	else
		md=loadresultsfromcluster(md);
	end
elseif md.settings.waitonlock>0,
	%we wait for the done file
	done=waitonlock(md);
	if md.verbose.solution,
		disp('loading results from cluster');
	end
	md=loadresultsfromcluster(md);
elseif md.settings.waitonlock==0,
	 disp('Model results must be loaded manually with md=loadresultsfromcluster(md);');
end

%post processes qmu results if necessary
if md.qmu.isdakota,
	if ~strncmpi(options.keep,'y',1)
		system(['rm -rf qmu' num2str(feature('GetPid'))]);
	end
end
