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:
%		 - DiagnosticSolutionEnum
%		 - PrognosticSolutionEnum
%		 - ThermalSolutionEnum
%		 - SteadystateSolutionEnum
%		 - TransientSolutionEnum...
%		 - BalancethicknessSolutionEnum
%		 - BedSlopeSolutionEnum
%		 - SurfaceSlopeSolutionEnum
%		 - HydrologySolutionEnum
%		 - FlaimSolutionEnum
%
%  extra options:
%      - loadonly : does not solve. only load results
%
%   Examples:
%      md=solve(md,DiagnosticSolutionEnum);

%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
disp('checking model consistency');
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
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'));

%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

%we need to make sure we have PETSC support, otherwise, we run with only one cpu: 
if ~ispetsc(),
	disp('PETSc support not included, running on 1 cpu only!');
	cluster.np=1;
end

%Write all input files
marshall(md);                                          % bin file
PetscFile(md.solver,[md.miscellaneous.name '.petsc']); % petsc 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')
	disp('batch mode requested: not launching job interactively');
	disp('launch solution sequence on remote cluster by hand');
	return;
end

%Launch job
modelname = md.miscellaneous.name;
filelist  = {[modelname '.bin '] [modelname '.petsc '] [modelname '.queue ']};
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'),
	disp('solve done uploading test decks');
	return;
end

%wait on lock
if md.settings.waitonlock>0,
	%we wait for the done file
	islock=waitonlock(md);
	if islock==0, %no results to be loaded
		disp('The results must be loaded manually with md=loadresultsfromcluster(md).');
	else          %load results
		disp('loading results from cluster');
		md=loadresultsfromcluster(md);
	end
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
