0001 function [studyinfo, cmd] = dsCreateBatch(base_model,modifications_set,varargin)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 options=dsCheckOptions(varargin,{...
0038 'compile_flag',0,{0,1},...
0039 'parallel_flag',0,{0,1},...
0040 'num_cores',4,[],...
0041 'sims_per_job',1,[],...
0042 'memory_limit','8G',[],...
0043 'batch_dir',[],[],...
0044 'simulator_options',[],[],...
0045 'verbose_flag',0,{0,1},...
0046 'overwrite_flag',0,{0,1},...
0047 'process_id',[],[],...
0048 'qsub_mode','loop',{'loop','array'},...
0049 'one_solve_file_flag',0,{0,1},...
0050 'solver','rk4',{'euler','rk1','rk2','rk4','modified_euler','rungekutta','rk','ode23','ode45',...
0051 'ode1','ode2','ode3','ode4','ode5','ode8','ode113','ode15s','ode23s','ode23t','ode23tb'},...
0052 'auto_gen_test_data_flag',0,{0,1},...
0053 'unit_test_flag',0,{0,1},...
0054 },false);
0055
0056
0057 if options.auto_gen_test_data_flag
0058 varargs = varargin;
0059 varargs{find(strcmp(varargs, 'auto_gen_test_data_flag'))+1} = 0;
0060 varargs(end+1:end+2) = {'unit_test_flag',1};
0061 argin = [{base_model},{modifications_set}, varargs];
0062 end
0063
0064
0065
0066 [studyinfo,options.simulator_options]=dsSetupStudy(base_model,'modifications_set',modifications_set,'simulator_options',options.simulator_options,'process_id',options.process_id);
0067 study_file=fullfile(studyinfo.study_dir,'studyinfo.mat');
0068 num_simulations=length(modifications_set);
0069
0070
0071
0072 [~,s]=dsMonitorStudy(studyinfo.study_dir,'verbose_flag',0,'process_id',options.process_id);
0073 if s==1
0074 if options.verbose_flag
0075 fprintf('Study already finished. Not creating new batch.\n');
0076 end
0077
0078 studyinfo=dsCheckStudyinfo(studyinfo.study_dir,'process_id',options.process_id, varargin{:});
0079
0080 return;
0081 end
0082
0083
0084
0085 if isa(options.simulator_options.experiment,'function_handle') && options.compile_flag
0086 options.compile_flag=0;
0087 options.simulator_options.compile_flag=0;
0088 wprintf('solver compilation is not available for experiments run on the cluster.');
0089 end
0090
0091
0092 solve_file = dsGetSolveFile(base_model,studyinfo,options.simulator_options);
0093
0094
0095
0096 if options.compile_flag
0097
0098 [fpath,fname]=fileparts2(solve_file);
0099
0100
0101 D=dir(fpath);
0102
0103
0104 tmp=regexp({D.name},[fname '\.(\w+)$'],'tokens','once');
0105 tmp=unique([tmp{:}]);
0106
0107
0108 if ~any(strcmp(options.solver, {'ode113','ode15s','ode23s','ode23t','ode23tb'}))
0109 full_solve_file=[solve_file '.' tmp{1}];
0110
0111
0112 solve_file=regexp(solve_file,'(.+)_mex$','tokens','once');
0113 solve_file=solve_file{1};
0114 else
0115 full_solve_file=solve_file;
0116 end
0117 else
0118 full_solve_file=solve_file;
0119 end
0120 studyinfo.base_solve_file=solve_file;
0121
0122
0123
0124
0125
0126
0127 [~,home]=system('echo $HOME');
0128
0129
0130 study_dir_full_path = fileparts2(studyinfo.study_dir);
0131 [~, study_dir_name, study_dir_suffix] = fileparts(study_dir_full_path);
0132 study_dir_name=[study_dir_name study_dir_suffix];
0133
0134 if ~options.auto_gen_test_data_flag && ~options.unit_test_flag
0135 main_batch_dir = fullfile(strtrim(home),'batchdirs');
0136
0137
0138 if ~exist(main_batch_dir,'dir')
0139 mkdir(main_batch_dir);
0140 end
0141
0142 batch_dir = fullfile(main_batch_dir,study_dir_name);
0143
0144 else
0145 study_dir = fileparts2(studyinfo.study_dir);
0146 [~, rel_study_dir] = fileparts(study_dir);
0147 batch_dir = fullfile(rel_study_dir,'batchdirs',study_dir_name);
0148 end
0149
0150 if options.verbose_flag
0151 fprintf('\nPREPARING BATCH:\n');
0152 end
0153
0154
0155 if ~exist(batch_dir,'dir')
0156 if options.verbose_flag
0157 fprintf('Creating batch jobs directory: %s\n',batch_dir);
0158 end
0159 mkdir(batch_dir);
0160 end
0161
0162
0163 [success,msg]=copyfile(study_file,batch_dir);
0164 if ~success
0165 error(msg)
0166 end
0167
0168
0169 dynasim_path = dsGetRootPath();
0170 dynasim_functions=fullfile(dynasim_path,'functions');
0171
0172
0173 [mech_paths,mech_files]=dsLocateModelFiles(base_model);
0174
0175
0176 studyinfo.paths.dynasim_functions = dynasim_functions;
0177 studyinfo.paths.mechanisms = mech_paths;
0178 studyinfo.paths.batch_dir = batch_dir;
0179
0180
0181 options.simulator_options.parallel_flag = 0;
0182 options.simulator_options.cluster_flag = 0;
0183 options.simulator_options.verbose_flag = 1;
0184
0185
0186
0187
0188 addpaths=cat(2,dynasim_path,regexp(genpath(dynasim_functions),':','split'));
0189
0190
0191
0192
0193 addpaths=cat(2,addpaths,fullfile(dynasim_path,'models'));
0194
0195 if ~isempty(mech_paths)
0196 addpaths=cat(2,addpaths,mech_paths);
0197 addpaths=unique(addpaths);
0198 end
0199
0200
0201 jobs={};
0202 skip_sims=[];
0203 sim_cnt=0;
0204 num_jobs=ceil(num_simulations/options.sims_per_job);
0205
0206 if options.verbose_flag && ~options.one_solve_file_flag
0207 fprintf('Creating %g cluster jobs in batch directory for %g simulations...\n',num_jobs,num_simulations);
0208 end
0209
0210 if ~options.one_solve_file_flag
0211 for k = 1:num_jobs
0212 job_file=fullfile(batch_dir,sprintf('sim_job%g.m',k));
0213 sim_ids=sim_cnt+(1:options.sims_per_job);
0214 sim_ids=sim_ids(sim_ids<=num_simulations);
0215 sim_cnt=sim_cnt+options.sims_per_job;
0216
0217
0218 proc_sims=[];
0219 for j=1:length(sim_ids)
0220 if (options.simulator_options.save_data_flag && ~exist(studyinfo.simulations(sim_ids(j)).data_file,'file')) || ...
0221 (options.simulator_options.save_results_flag && ~exist(studyinfo.simulations(sim_ids(j)).result_files{1},'file')) || ...
0222 options.overwrite_flag
0223 proc_sims=[proc_sims sim_ids(j)];
0224 end
0225 end
0226
0227 if isempty(proc_sims)
0228 skip_sims=[skip_sims sim_ids];
0229 continue;
0230 else
0231 skip_sims=[skip_sims setdiff(sim_ids,proc_sims)];
0232 end
0233
0234 WriteSimJob(proc_sims,job_file);
0235
0236 jobs{end+1}=job_file;
0237
0238
0239 for j=1:length(proc_sims)
0240 studyinfo.simulations(proc_sims(j)).job_file=job_file;
0241 end
0242
0243 end
0244 else
0245 job_file=fullfile(batch_dir, 'sim_job.m');
0246
0247 WriteSimJob([], job_file);
0248
0249
0250
0251
0252
0253
0254
0255 [studyinfo.simulations.job_file] = deal(job_file);
0256 end
0257
0258
0259
0260
0261
0262
0263 if numel(skip_sims)==num_simulations
0264 if options.verbose_flag
0265 fprintf('Data exists for all simulations in study. nothing to do.\n');
0266 end
0267
0268 return;
0269 end
0270
0271
0272 if strcmp(options.qsub_mode, 'loop')
0273 script_filename = fullfile(batch_dir,'scriptlist.txt');
0274 if options.verbose_flag
0275 fprintf('Creating file listing jobs in batch directory: %s\n',script_filename);
0276 end
0277
0278
0279 fScript=fopen(script_filename,'wt');
0280
0281 for j=1:length(jobs)
0282 [~,thisFilename]=fileparts2(jobs{j});
0283 fprintf(fScript,'%s\n',thisFilename);
0284 end
0285
0286 fclose(fScript);
0287 end
0288
0289 if ~options.one_solve_file_flag
0290
0291
0292 if options.verbose_flag
0293 fprintf('Creating distinct solver sub-directories for %g simulations...\n',num_simulations);
0294 end
0295
0296 [solve_path,solve_name,solve_ext]=fileparts2(full_solve_file);
0297
0298
0299 for sim=1:num_simulations
0300 if ismember(sim,skip_sims)
0301 continue;
0302 end
0303
0304 this_solve_path=fullfile(solve_path,['sim' num2str(sim)]);
0305
0306 if ~exist(this_solve_path,'dir')
0307
0308
0309
0310 mkdir(this_solve_path);
0311 end
0312
0313 [success,msg]=copyfile(full_solve_file,this_solve_path);
0314
0315 if ~success, error(msg); end
0316
0317
0318 this_solve_file=fullfile(this_solve_path,[solve_name solve_ext]);
0319 studyinfo.simulations(sim).solve_file=this_solve_file;
0320 studyinfo.simulations(sim).batch_dir=batch_dir;
0321 studyinfo.simulations(sim).simulator_options=options.simulator_options;
0322
0323
0324 if isa(options.simulator_options.experiment,'function_handle')
0325 studyinfo.simulations(sim).simulator_options.solve_file=[];
0326 else
0327 studyinfo.simulations(sim).simulator_options.solve_file=this_solve_file;
0328 end
0329
0330
0331 studyinfo.simulations(sim).simulator_options.vary=[];
0332 studyinfo.simulations(sim).simulator_options.sim_id=studyinfo.simulations(sim).sim_id;
0333 studyinfo.simulations(sim).error_log='';
0334
0335 end
0336
0337
0338 for sim=1:num_simulations
0339 this_study_file=fullfile(batch_dir,sprintf('studyinfo_%g.mat',sim));
0340
0341 if sim==1
0342 try
0343 save(this_study_file,'studyinfo','-v7');
0344 if ~strcmp(reportUI,'matlab')
0345 [wrn_msg,wrn_id] = lastwarn;
0346 if strcmp(wrn_msg,'save: wrong type argument ''function handle''')
0347 error('save: wrong type argument ''function handle''');
0348 end
0349 end
0350 catch
0351 fprintf('Data is not ''-v7'' compatible. Saving in hdf5 format.\n')
0352 save(this_study_file,'studyinfo','-hdf5');
0353 end
0354 first_study_file=this_study_file;
0355 else
0356
0357 [success,msg]=copyfile(first_study_file,this_study_file);
0358
0359 if ~success, error(msg); end
0360 end
0361 end
0362
0363 else
0364
0365 [studyinfo.simulations.solve_file] = deal(full_solve_file);
0366 [studyinfo.simulations.batch_dir] = deal(batch_dir);
0367 [studyinfo.simulations.simulator_options] = deal(options.simulator_options);
0368
0369
0370 for iSim = 1:num_simulations
0371 studyinfo.simulations(iSim).simulator_options.vary = [];
0372 studyinfo.simulations(iSim).simulator_options.sim_id = studyinfo.simulations(iSim).sim_id;
0373 end
0374 [studyinfo.simulations.error_log] = deal('');
0375
0376
0377 batch_study_file = fullfile(batch_dir,'studyinfo.mat');
0378 try
0379 save(batch_study_file,'studyinfo','-v7');
0380 if ~strcmp(reportUI,'matlab')
0381 [wrn_msg,wrn_id] = lastwarn;
0382 if strcmp(wrn_msg,'save: wrong type argument ''function handle''')
0383 error('save: wrong type argument ''function handle''');
0384 end
0385 end
0386 catch
0387 fprintf('Data is not ''-v7'' compatible. Saving in hdf5 format.\n')
0388 save(batch_study_file,'studyinfo','-hdf5');
0389 end
0390 end
0391
0392
0393 dsStudyinfoIO(studyinfo,study_file,options.simulator_options.sim_id,options.verbose_flag);
0394
0395
0396
0397
0398 [status,result]=system('which qsub');
0399
0400 if options.auto_gen_test_data_flag || options.unit_test_flag
0401 status = 0;
0402 result = 1;
0403 end
0404
0405 if isempty(result)
0406 [~,host] = system('hostname');
0407 fprintf('qsub not found on host (%s).\n',strtrim(host));
0408 fprintf('Jobs NOT submitted to cluster queue.\n');
0409 else
0410
0411
0412 [~,s]=dsMonitorStudy(studyinfo.study_dir,'verbose_flag',0);
0413
0414 if s~=1
0415
0416 if options.auto_gen_test_data_flag || options.unit_test_flag
0417 batch_dir = rel_study_dir;
0418 end
0419
0420 [batch_dir_path,batch_dir_name,batch_suffix]=fileparts(batch_dir);
0421 batch_dir_name=[batch_dir_name batch_suffix];
0422
0423 if ~options.auto_gen_test_data_flag && ~options.unit_test_flag
0424 dsFnPath = fileparts(mfilename('fullpath'));
0425 else
0426 dsFnPath = 'dsFnPath';
0427 end
0428
0429 if options.parallel_flag
0430 warning('jobs in the cluster use a single thread')
0431 end
0432
0433 if strcmp(options.qsub_mode, 'array') && ~options.one_solve_file_flag
0434
0435 cmd = sprintf('echo ''%s/qsub_jobs_array %s sim_job'' | qsub -V -hard -l ''h_vmem=%s'' -wd %s -N %s_sim_job -t 1-%i',...
0436 dsFnPath, batch_dir, options.memory_limit, batch_dir, batch_dir_name, num_jobs);
0437 elseif strcmp(options.qsub_mode, 'array') && options.one_solve_file_flag
0438 [~, job_filename] = fileparts2(job_file);
0439 cmd = sprintf('echo ''%s/qsub_jobs_array_one_file %s %s'' | qsub -V -hard -l ''h_vmem=%s'' -wd %s -N %s_sim_job -t 1-%i:%i',...
0440 dsFnPath, batch_dir, job_filename, options.memory_limit, batch_dir, batch_dir_name, num_simulations, options.sims_per_job);
0441
0442
0443 elseif strcmp(options.qsub_mode, 'loop')
0444 if strcmp(reportUI,'matlab')
0445 ui_command = '"matlab -nodisplay -singleCompThread -r"';
0446 l_directives = ['-l mem_total=',options.memory_limit];
0447 else
0448 ui_command = '"octave-cli --eval"';
0449 l_directives = ['-l centos7=TRUE -l mem_total=',options.memory_limit];
0450 end
0451 cmd = sprintf('%s/qsub_jobs_loop %s ''%s'' ''%s''',dsFnPath,batch_dir_name,ui_command,l_directives);
0452 end
0453
0454
0455 setenv('PATH', [getenv('PATH') ':' dynasim_functions ':' fullfile(dynasim_functions, 'internal')]);
0456
0457 if options.verbose_flag
0458 fprintf('Submitting cluster jobs with shell command: "%s"\n',cmd);
0459 end
0460
0461 if ~options.auto_gen_test_data_flag && ~options.unit_test_flag
0462 [status,result]=system(cmd);
0463 end
0464
0465 if status > 0
0466 if options.verbose_flag
0467 fprintf('Submit command failed: "%s"\n',cmd);
0468 disp(result);
0469 end
0470 return;
0471 else
0472 if options.verbose_flag
0473 fprintf('Submit command status: \n');
0474 disp(result);
0475 end
0476 end
0477
0478 if options.verbose_flag
0479
0480 fprintf('%g jobs successfully submitted!\n',num_jobs);
0481 end
0482 elseif s==1
0483 if options.verbose_flag
0484 fprintf('Study already finished. not submitting jobs.\n');
0485 end
0486 end
0487 end
0488
0489
0490 if options.auto_gen_test_data_flag
0491 dirIn = studyinfo.study_dir;
0492 removeStudyinfo()
0493
0494 if ~isempty(studyinfo)
0495 studyinfo = [];
0496 end
0497 argout = {studyinfo, cmd};
0498
0499 dsUnitSaveAutoGenTestDir(argin, argout, [], dirIn);
0500 end
0501
0502
0503 if options.unit_test_flag
0504
0505 removeStudyinfo()
0506 if ~isempty(studyinfo)
0507 studyinfo = [];
0508 end
0509 end
0510
0511
0512
0513
0514 function WriteSimJob(sim_ids,job_file)
0515
0516
0517
0518 fjob=fopen(job_file,'wt');
0519
0520
0521
0522
0523
0524 [~, job_filename] = fileparts(job_file);
0525
0526 if ~options.one_solve_file_flag
0527
0528 fprintf(fjob, 'function %s\n\n', job_filename);
0529
0530
0531 fprintf(fjob,'SimIDs=[%s]\n',num2str(sim_ids));
0532 else
0533
0534 fprintf(fjob, 'function %s(simIDstart, simIDstep, simIDlast)\n\n', job_filename);
0535
0536 if options.compile_flag
0537 fprintf(fjob, 'assert(isa(simIDstart, ''double''));\n');
0538 fprintf(fjob, 'assert(isa(simIDstep, ''double''));\n');
0539 fprintf(fjob, 'assert(isa(simIDlast, ''double''));\n');
0540 end
0541
0542
0543 fprintf(fjob,'SimIDs = simIDstart:min(simIDlast,simIDstart+simIDstep-1);\n');
0544 end
0545
0546
0547 for p=1:length(addpaths)
0548 if ~isempty(addpaths{p})
0549 fprintf(fjob,'addpath %s\n',addpaths{p});
0550 end
0551 end
0552
0553
0554 if options.parallel_flag
0555
0556
0557
0558 fprintf(fjob,'c=parcluster;\nsaveAsProfile(c,''local_%g'');\nparpool(c,%g);\n',k,options.num_cores);
0559
0560
0561 fprintf(fjob,'parfor s=1:length(SimIDs)\n');
0562 else
0563
0564 fprintf(fjob,'for s=1:length(SimIDs)\n');
0565 end
0566
0567 fprintf(fjob,'\tSimID=SimIDs(s);\n');
0568
0569
0570 fprintf(fjob,'\ttry\n');
0571
0572
0573 if ~options.one_solve_file_flag
0574 fprintf(fjob,'\t\tload(fullfile(''%s'',sprintf(''studyinfo_%%g.mat'',SimID)),''studyinfo'');\n',batch_dir);
0575 else
0576 fprintf(fjob,'\t\tload(fullfile(''%s'',''studyinfo.mat''),''studyinfo'');\n',batch_dir);
0577 end
0578
0579 fprintf(fjob,'\t\t[valid,message]=dsCheckHostPaths(studyinfo);\n');
0580
0581 if ~options.one_solve_file_flag
0582 fprintf(fjob,'\t\tif ~valid\n\t\t lasterr(message);\n\t\t for s=1:length(SimIDs), dsUpdateStudy(studyinfo.study_dir,''sim_id'',SimIDs(s),''status'',''failed''); end\n\t\t continue;\n\t\tend\n');
0583 end
0584
0585
0586 fprintf(fjob,'\t\tsiminfo=studyinfo.simulations(SimID);\n');
0587 fprintf(fjob,'\t\toptions=rmfield(siminfo.simulator_options,{''modifications'',''studyinfo'',''analysis_functions'',''plot_functions'',''sim_id''});\n');
0588 fprintf(fjob,'\t\tkeyvals=dsOptions2Keyval(options);\n');
0589 fprintf(fjob,'\t\tfprintf(''-----------------------------------------------------\\n'');\n');
0590 fprintf(fjob,'\t\tfprintf(''Processing simulation %%g (%%g of %%g in this job)...\\n'',SimID,s,length(SimIDs));\n');
0591 fprintf(fjob,'\t\tfprintf(''-----------------------------------------------------\\n'');\n');
0592 fprintf(fjob,'\t\tdata=dsSimulate(studyinfo.base_model,''modifications'',siminfo.modifications,''studyinfo'',studyinfo,''sim_id'',SimID,keyvals{:});\n');
0593 fprintf(fjob,'\t\tfor i=1:length(siminfo.result_functions)\n');
0594 fprintf(fjob,'\t\t\tdsAnalyze(data,siminfo.result_functions{i},''result_file'',siminfo.result_files{i},''save_data_flag'',1,siminfo.result_options{i}{:});\n');
0595 fprintf(fjob,'\t\tend\n');
0596
0597
0598 fprintf(fjob,'\tcatch err\n');
0599
0600
0601 fprintf(fjob,'\t\tdisplayError(err);\n');
0602 fprintf(fjob,'\tend\n');
0603
0604
0605 fprintf(fjob,'end\n');
0606 if options.parallel_flag
0607
0608 fprintf(fjob,'delete(gcp)\n');
0609 end
0610
0611
0612 [status,result]=system('which qsub');
0613 if ~isempty(result)
0614 fprintf(fjob,'exit\n');
0615 end
0616
0617
0618 fclose(fjob);
0619 end
0620
0621 function removeStudyinfo()
0622
0623
0624
0625 studyDirFiles = rls(studyinfo.study_dir);
0626 studyinfoFiles = studyDirFiles(~cellfun(@isempty, strfind(studyDirFiles, 'studyinfo')));
0627 for k = 1:length(studyinfoFiles)
0628 thisFile = studyinfoFiles{k};
0629 delete(thisFile)
0630 end
0631 end
0632
0633 end
0634
0635
0636
0637
0638
0639
0640
0641
0642
0643
0644
0645