%
%  write a Dakota .m file for the Matlab direct or external
%  driver.
%
%  []=dakota_m_write(md,method,dvar,dresp,filem,params,package)
%
function []=dakota_m_write(md,method,dvar,dresp,filem,params,package)

if ~nargin
    help dakota_m_write
    return
end

%  process the input parameters

if ~exist('params','var')
    params=[];
end
if ~isfield(params,'npart')
    params.npart=10;
end

if ~exist('filem' ,'var') || isempty(filem)
    filem=input('Matlab m-file to write?  ','s');
end
[pathstr,name,ext,versn] = fileparts(filem);
if isempty(ext)
    ext='.m';
end
filem2=fullfile(pathstr,[name ext versn]);

display(sprintf('Opening Matlab m-file ''%s''.',filem2));
fidm=fopen(sprintf('%s',filem2),'w');
if (fidm < 0)
    error('''%s'' could not be opened.',filem2);
end

%  write beginning of the Matlab m-file

begin_write(fidm,name,params);

%  write variables into the Matlab m-file

variables_write(md,fidm,method,dvar);

%  write solution into the Matlab m-file

solution_write(fidm,package);

%  write responses into the Matlab m-file

responses_write(fidm,method,params,dresp);

%  write end of the Matlab m-file

end_write(fidm,name);

fclose(fidm);
display('End of file successfully written.');

end

%%  function to write beginning of the Matlab m-file

function []=begin_write(fidm,name,params)

display('Writing beginning of Matlab m-file.');

fprintf(fidm,'%%\n');
if strcmpi(params.analysis_driver,'matlab')
    fprintf(fidm,'%%  Run the specified input variables and return the output responses.\n');
    fprintf(fidm,'%%\n');
    fprintf(fidm,'function Dakota=%s(Dakota)\n\n',name);
    fprintf(fidm,'\tclk=clock;\n');
    fprintf(fidm,'\tcpu=cputime;\n\n');
    fprintf(fidm,'%%\tDakota\n\n');
    fprintf(fidm,'\tinfile=''%s'';\n','Qmu.model');
else
    fprintf(fidm,'%%  Run the specified input file and return the output file.\n');
    fprintf(fidm,'%%\n');
    fprintf(fidm,'function %s(infile,outfile)\n\n',name);
    fprintf(fidm,'\tclk=clock;\n');
    fprintf(fidm,'\tcpu=cputime;\n\n');
end
fprintf(fidm,'\tloadmodel(infile);\n\n');
fprintf(fidm,'\tmd=qmuname(md);\n\n');

end

%%  function to write design variables into the Matlab m-file

function []=variables_write(md,fidm,method,dvar)

display('Writing variables for Matlab m-file.');

fprintf(fidm,'%%  Apply the design variables.\n\n');
ixc=0;

%  variables vary by method

switch method
%     case {'dot_bfgs','dot_frcg','dot_mmfd','dot_slp','dot_sqp'}
%     case {'npsol_sqp'}
    case {'conmin_frcg','conmin_mfd'}
        ixc=vsets_write(md,fidm,ixc,dvar,'cdv','csv');
%     case {'optpp_cg','optpp_q_newton','optpp_fd_newton',...
%             'optpp_newton','optpp_pds'}
%     case {'asynch_pattern_search'}
%     case {'coliny_cobyla','coliny_direct','coliny_ea',...
%             'coliny_pattern_search','coliny_solis_wets'}
%     case {'ncsu_direct'}
%     case {'moga','soga'}
%     case {'nl2sol','nlssol_sqp','optpp_g_newton'}
    case {'nond_sampling'}
        ixc=vsets_write(md,fidm,ixc,dvar,'nuv','csv');
    case {'nond_local_reliability'}
        ixc=vsets_write(md,fidm,ixc,dvar,'nuv','csv');
%     case {'dace','fsu_quasi_mc','fsu_cvt'}
%     case {'vector_parameter_study','list_parameter_study',...
%             'centered parameter_study','multidim_parameter_study'}
end

end

%%  function to write variable sets into the Matlab m-file

function [ixc]=vsets_write(md,fidm,ixc,dvar,varargin)

for i=1:length(varargin)
    if isfield(dvar,varargin{i})
        ixc=vlist_write(md,fidm,ixc,varargin{i},dvar.(varargin{i}));
    end
end

end

%%  function to write variable list into the Matlab m-file

function [ixc]=vlist_write(md,fidm,ixc,vtype,dvar)

disp(sprintf('  Writing %d %s variables.',length(dvar),class(dvar)));

for i=1:length(dvar)

	%first find descriptor, without sample number on it.
	descriptor=discardnum(dvar(i).descriptor);

	%is there a lock on this variable? We don't want to update the variable twice!
	if exist([descriptor '_lock'],'var'),
		%lock is in place, do not update! continue;
		continue;
	else
		%first things first, put lock in place
		eval([descriptor '_lock=1;']);

		%now, we need a string to put in the matlab file, which will update all the design variables 
		%for  this descriptor.
		[string,ixc]=QmuUpdateFunctions(md,ixc,descriptor,dvar,i);

		%dump this string in the matlab file.
        fprintf(fidm,'%s',string);
	end
end

end

%%  function to write solution into the Matlab m-file

function []=solution_write(fidm,package)

display('Writing solution for Matlab m-file.');
fprintf(fidm,'%%  Run the solution.\n\n');

fprintf(fidm,['\tmd=solve(md,''diagnostic'',''' package ''');\n\n']);

end

%%  function to write responses into the Matlab m-file

function []=responses_write(fidm,method,params,dresp)

display('Writing responses for Matlab m-file.');

fprintf(fidm,'%%  Calculate the response functions.\n\n');
ifnvals=0;

if ~strcmpi(params.analysis_driver,'matlab')
    fprintf(fidm,'\tfid=fopen(outfile,''w'');\n\n');
end

%  responses vary by method

switch method
%     case {'dot_bfgs','dot_frcg','dot_mmfd','dot_slp','dot_sqp'}
%     case {'npsol_sqp'}
    case {'conmin_frcg','conmin_mfd'}
        ifnvals=rsets_write(fidm,ifnvals,params,dresp,'of','nic','nec');
%     case {'optpp_cg','optpp_q_newton','optpp_fd_newton',...
%             'optpp_newton','optpp_pds'}
%     case {'asynch_pattern_search'}
%     case {'coliny_cobyla','coliny_direct','coliny_ea',...
%             'coliny_pattern_search','coliny_solis_wets'}
%     case {'ncsu_direct'}
%     case {'moga','soga'}
%     case {'nl2sol','nlssol_sqp','optpp_g_newton'}
    case {'nond_sampling'}
        ifnvals=rsets_write(fidm,ifnvals,params,dresp,'rf');
    case {'nond_local_reliability'}
        ifnvals=rsets_write(fidm,ifnvals,params,dresp,'rf');
%     case {'dace','fsu_quasi_mc','fsu_cvt'}
%     case {'vector_parameter_study','list_parameter_study',...
%             'centered parameter_study','multidim_parameter_study'}
end

fprintf(fidm,'\n');
if ~strcmpi(params.analysis_driver,'matlab')
    fprintf(fidm,'\tstatus=fclose(fid);\n\n');
end

end

%%  function to write response sets into the Matlab m-file

function [ifnvals]=rsets_write(fidm,ifnvals,params,dresp,varargin)

for i=1:length(varargin)
    if isfield(dresp,varargin{i})
        ifnvals=rlist_write(fidm,ifnvals,params,varargin{i},dresp.(varargin{i}));
    end
end

end

%%  function to write response list into the Matlab m-file

function [ifnvals]=rlist_write(fidm,ifnvals,params,rtype,dresp)

disp(sprintf('  Writing %d %s responses.',length(dresp),class(dresp)));

for i=1:length(dresp)
    ifnvals=ifnvals+1;
    if strcmpi(params.analysis_driver,'matlab')
        fprintf(fidm,'\tDakota.fnVals(%d)=QmuResponseValue(md,''%s'');\n',ifnvals,dresp(i).descriptor);
    else
        fprintf(fidm,'\tfprintf(fid,''%%f\\n'',QmuResponseValue(md,''%s''));\n',dresp(i).descriptor);
    end
end

end

%%  function to write end of the Matlab m-file

function []=end_write(fidm,name)

display('Writing end of Matlab m-file.');

fprintf(fidm,'\tdisp(sprintf(''%s -- %%f CPU seconds; %%f clock seconds\\n'',...\n',name);
fprintf(fidm,'\t    cputime-cpu,etime(clock,clk)))\n\n');
fprintf(fidm,'end\n\n');

end
