├── .gitattributes ├── .gitignore ├── LICENSE ├── README ├── apm ├── apm.m ├── apm_app.m ├── apm_arx.m ├── apm_details.m ├── apm_get.m ├── apm_id.m ├── apm_info.m ├── apm_linear.m ├── apm_linprog.m ├── apm_load.m ├── apm_lti.m ├── apm_meas.m ├── apm_option.m ├── apm_quadprog.m ├── apm_sol.m ├── apm_solve.m ├── apm_tag.m ├── apm_web.m ├── apm_web_root.m ├── apm_web_var.m ├── csv_data.m ├── csv_element.m ├── csv_load.m ├── csv_lookup.m ├── parse.m ├── t0_load.m └── urlread_apm.m ├── demo ├── README.txt ├── apm.py ├── demo.apm ├── demo.csv ├── main.m └── main.py ├── example_4tank ├── 4tank.apm ├── 4tank_nlc.apm ├── control.csv ├── control.m ├── control_h[1].png ├── control_h[2].png ├── prbs.m ├── prbs.png ├── prbs.txt ├── prbs10.txt ├── prbs360.csv ├── prbs50.csv ├── solution_prbs.csv ├── solution_step.csv ├── step.csv ├── step.m └── step.png ├── example_cstr_seq ├── README.txt ├── cstr.apm ├── cstr.csv ├── cstr.jpg ├── cstr1.m ├── main.m ├── matlab_results.png └── solution_nlc.csv ├── example_cstr_simul ├── README.txt ├── cstr.apm ├── cstr.csv ├── cstr.jpg ├── cstr1.m ├── main.m ├── matlab_results.png └── solution_nlc.csv ├── example_cstr_steps ├── README.txt ├── cstr.apm ├── cstr.jpg ├── cstr1.csv ├── cstr1.m ├── cstr2.csv ├── main.m └── matlab_results.png ├── example_distillation ├── distill.apm ├── distill_pid.apm ├── horizon_ctl.csv ├── horizon_sim.csv ├── main_nlc.m ├── main_pid.m ├── replay_ctl.csv ├── replay_sim.csv └── test.m ├── example_hs71 ├── hs71.apm ├── hs71.gif ├── main.m └── solution_trial.csv ├── example_id ├── myTest.m ├── test_data.csv └── test_data.xlsx ├── example_lti ├── linear.apm ├── linear_test.m ├── lti_test.m └── solution_lintest.csv ├── example_lti_regression ├── data_no_headers.csv └── lti_regression.m ├── example_minlp ├── minlp.apm └── minlp.m ├── example_nlc ├── data.csv ├── main.m ├── matlab_ctrl.png └── model.apm ├── example_pendulum ├── pendulum.apm ├── pendulum.m ├── plot_all.m ├── replay.csv └── test.m ├── example_sbml_erbb ├── erbb.apm ├── erbb.csv └── main.m ├── example_sbml_vaccine ├── main.m ├── results.png ├── vaccine.apm ├── vaccine_0.7.csv └── vaccine_0.9.csv ├── example_thermostat ├── heater.apm ├── heater.csv └── main.m └── test_all.m /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2012 APMonitor. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are 4 | permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of 7 | conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 10 | of conditions and the following disclaimer in the documentation and/or other materials 11 | provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY APMONITOR ''AS IS'' AND ANY EXPRESS OR IMPLIED 14 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 15 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APMONITOR OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 17 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 18 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 19 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 21 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | The views and conclusions contained in the software and documentation are those of the 24 | authors and should not be interpreted as representing official policies, either expressed 25 | or implied, of APMonitor. -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | APMonitor Optimization Suite 2 | 3 | The APMonitor Modeling Language is optimization software for mixed-integer and differential algebraic equations. It is coupled with large-scale solvers for linear, quadratic, nonlinear, and mixed integer programming (LP, QP, NLP, MILP, MINLP). Modes of operation include data reconciliation, real-time optimization, dynamic simulation, and nonlinear predictive control. It is freely available through MATLAB, Python, or from a web browser interface. -------------------------------------------------------------------------------- /apm/apm.m: -------------------------------------------------------------------------------- 1 | % APM Web-Interface Command 2 | % 3 | % response = apm(server,app,command) 4 | % 5 | % This function sends a command to the APM server with 6 | % the following arguments: 7 | % 8 | % server = address of server 9 | % app = application name 10 | % command = instruction or line sent 11 | % 12 | % Some commands are: 13 | % solve : solve the model on the server 14 | % clear all : clear the application and all files 15 | % clear apm : clear just the model file (apm) 16 | % clear csv : clear just the data file (csv) 17 | % info {FV,MV,SV,CV}, {name} : create interface to variable 18 | % ss.t0 {values} : load ss.t0 (restart file) 19 | % csva {contents} : add contents to the data file (csv) 20 | % csv {line} : add one line to the data file (csv) 21 | % apm {contents} : add to apm file without carriage return 22 | % {otherwise} : add line to apm file 23 | function response = apm(server,app,aline) 24 | 25 | % Web-server URL base 26 | url_base = [deblank(server) '/online/apm_line.php']; 27 | app = lower(deblank(app)); 28 | params = ['?p=' urlencode(app) '&a=' urlencode(aline)]; 29 | url = [url_base params]; 30 | % Send request to web-server 31 | response = urlread_apm(url); 32 | 33 | % remove newline characters from response 34 | newline = sprintf('\r'); 35 | response = strrep(response,newline,''); 36 | -------------------------------------------------------------------------------- /apm/apm_app.m: -------------------------------------------------------------------------------- 1 | % APM Load Application 2 | % 3 | % app = apm_app(server,name) 4 | % 5 | % Function apm_app loads a model file (apm) and optionally 6 | % a data file (csv) to the APM server with the 7 | % following arguments: 8 | % 9 | % app = application name 10 | % server = address of server 11 | % name = loads name.apm and name.csv 12 | % 13 | function [app] = apm_app(server,name) 14 | 15 | % model name with .apm extension 16 | app_model = [name '.apm']; 17 | 18 | % data file with .csv extension (optional) 19 | app_data = [name '.csv']; 20 | 21 | % application name, use random number to avoid ip conflicts 22 | app = [name '_' int2str(rand()*10000)]; 23 | app = lower(deblank(app)); 24 | 25 | % clear previous application 26 | apm(server,app,'clear all'); 27 | 28 | % check that model file exists (required) 29 | if (~exist(app_model,'file')), 30 | disp(['Error: file ' app_model ' does not exist']); 31 | app = []; 32 | return 33 | else 34 | % load model file 35 | apm_load(server,app,app_model); 36 | end 37 | 38 | % check if data file exists (optional) 39 | if (exist(app_data,'file')), 40 | % load data file 41 | csv_load(server,app,app_data); 42 | end 43 | -------------------------------------------------------------------------------- /apm/apm_arx.m: -------------------------------------------------------------------------------- 1 | function msg = apm_arx(p,m,ny,nu,alpha,beta,gamma,name) 2 | 3 | if nargin <= 6, 4 | error('apm_arx: Input ARX Model') 5 | end 6 | if nargin == 7, 7 | name = 'arx'; 8 | end 9 | if nargin == 8, 10 | % trim whitespace 11 | filename = strtrim(name); 12 | % parse file name and extension 13 | [path,name,ext] = fileparts(name); 14 | end 15 | filename = [name '.apm']; 16 | 17 | % check sizes for alpha 18 | [alpha_ny,alpha_p] = size(alpha); 19 | if (alpha_ny~=ny), 20 | disp(['input ny: ', num2str(ny)]) 21 | disp(['alpha ny: ', num2str(alpha_ny)]) 22 | error('ARX Size mismatch for alpha') 23 | end 24 | if (alpha_p~=p), 25 | disp(['input p: ', num2str(p)]) 26 | disp(['alpha p: ', num2str(alpha_p)]) 27 | error('ARX Size mismatch for alpha') 28 | end 29 | 30 | % check sizes for beta 31 | [beta_nu,beta_m,beta_p] = size(beta); 32 | if (beta_m~=m), 33 | disp(['input m: ', num2str(m)]) 34 | disp(['beta m: ', num2str(beta_m)]) 35 | error('ARX Size mismatch for beta') 36 | end 37 | if (beta_nu~=nu), 38 | disp(['input nu: ', num2str(nu)]) 39 | disp(['beta nu: ', num2str(beta_nu)]) 40 | error('ARX Size mismatch for beta') 41 | end 42 | if (beta_p~=p), 43 | disp(['input p: ', num2str(p)]) 44 | disp(['beta p: ', num2str(beta_p)]) 45 | error('ARX Size mismatch for alpha') 46 | end 47 | 48 | fid = fopen(filename,'w'); 49 | fprintf( fid,'\n'); 50 | fprintf( fid,'Objects \n'); 51 | fprintf( fid,[' ' name ' = arx\n']); 52 | fprintf( fid,'End Objects \n'); 53 | fprintf( fid,'\n'); 54 | fprintf( fid,'Connections\n'); 55 | fprintf( fid,[' u[1:%d] = ' name '.u[1:%d]\n'],m,m); 56 | fprintf( fid,[' y[1:%d] = ' name '.y[1:%d]\n'],p,p); 57 | fprintf( fid,'End Connections\n'); 58 | fprintf( fid,'\n'); 59 | fprintf( fid,'Model \n'); 60 | fprintf( fid,' Parameters \n'); 61 | if (m==1) 62 | fprintf( fid,' u = 0\n'); 63 | else 64 | fprintf( fid,' u[1:%d] = 0\n',m); 65 | end 66 | fprintf( fid,' End Parameters \n'); 67 | fprintf( fid,'\n'); 68 | fprintf( fid,' Variables \n'); 69 | if (p==1) 70 | fprintf( fid,' y = 0\n'); 71 | else 72 | fprintf( fid,' y[1:%d] = 0\n',p); 73 | end 74 | fprintf( fid,' End Variables \n'); 75 | fprintf( fid,'\n'); 76 | fprintf( fid,' Equations \n'); 77 | fprintf( fid,' ! add any additional equations here \n'); 78 | fprintf( fid,' End Equations \n'); 79 | fprintf( fid,'End Model \n'); 80 | fprintf( fid,'\n'); 81 | fprintf( fid,['File ' name '.txt\n']); 82 | fprintf( fid,' %d ! m=number of inputs\n',m); 83 | fprintf( fid,' %d ! p=number of outputs\n',p); 84 | fprintf( fid,' %d ! nu=number of input terms\n',nu); 85 | fprintf( fid,' %d ! ny=number of output terms\n',ny); 86 | fprintf( fid,'End File\n'); 87 | fprintf( fid,'\n'); 88 | fprintf( fid,'! Alpha matrix (ny x p)\n'); 89 | fprintf( fid,['File ' name '.alpha.txt \n']); 90 | for i = 1:ny 91 | for j = 1:p 92 | fprintf( fid,' '); 93 | if j<=p-1 94 | fprintf( fid,'%d , ', alpha(i,j)); 95 | else 96 | fprintf( fid,'%d ', alpha(i,j)); % no comma 97 | end 98 | end 99 | fprintf( fid,'\n'); 100 | end 101 | fprintf( fid,'End File \n'); 102 | fprintf( fid,'\n'); 103 | fprintf( fid,'! Beta matrix (p x (nu x m))\n'); 104 | fprintf( fid,['File ' name '.beta.txt \n']); 105 | for i = 1:p 106 | for j = 1:nu 107 | fprintf( fid,' '); 108 | for k = 1:m 109 | if k<=m-1 110 | fprintf( fid,'%d , ', beta(j,k,i)); 111 | else 112 | fprintf( fid,'%d ', beta(j,k,i)); 113 | end 114 | end 115 | fprintf( fid,'\n'); 116 | end 117 | end 118 | fprintf( fid,'End File \n'); 119 | fprintf( fid,'\n'); 120 | fprintf( fid,'! Gamma vector (p x 1)\n'); 121 | fprintf( fid,['File ' name '.gamma.txt \n']); 122 | for i = 1:p 123 | fprintf( fid,'%d ', gamma(i)); 124 | fprintf( fid,'\n'); 125 | end 126 | fprintf( fid,'End File \n'); 127 | fclose(fid); 128 | 129 | msg = ['Created ARX (Auto-Regressive eXogenous inputs) Model: ' filename]; 130 | 131 | end -------------------------------------------------------------------------------- /apm/apm_details.m: -------------------------------------------------------------------------------- 1 | % APM Report Problem Details 2 | % 3 | % y = apm_details(server,app,x,lam) 4 | % 5 | % This function reports the details of a problem 6 | % located on the APM server with the following arguments: 7 | % 8 | % server = address of server 9 | % app = application name 10 | % x = values of all variables 11 | % lam = Lagrange multipliers 12 | % y = structure with problem information 13 | % 14 | % Reports model details such as values, multipliers, residuals, 15 | % first derivatives, and second derivatives 16 | % 17 | % y.nvar = number of variables 18 | % y.var.lb = variable lower bounds 19 | % y.var.val = variable values 20 | % y.var.ub = variable upper bounds 21 | % y.obj = objective value 22 | % y.obj_grad = objective gradient 23 | % y.neqn = number of equations 24 | % y.eqn.lb = equation lower bounds 25 | % y.eqn.res = equation residuals 26 | % y.eqn.ub = equation upper bounds 27 | % y.jac = jacobian (1st derivatives) 28 | % y.lam = lagrange multipliers 29 | % y.hes_obj = second derivative of the objective 30 | % y.hes_eqn{i} = second derivatives of equation {i} 31 | % y.hes = full Hessian 32 | % 33 | function y = apm_details(server,app,x,lam) 34 | 35 | persistent sol_prev sol_count 36 | 37 | % initialize sol_count 38 | if (isempty(sol_count)), 39 | sol_count = 0; 40 | end 41 | 42 | % condition application name 43 | app = lower(deblank(app)); 44 | 45 | % tolerance for checking if the values are the same 46 | % as the previous call 47 | tol = 1e-10; 48 | 49 | % optionally load solution vector of variables 50 | if (nargin>=3), 51 | % create 'warm' as a column vector 52 | if (size(x,1)==1), 53 | warm = x'; 54 | else 55 | warm = x; 56 | end 57 | 58 | % see if the values are the same as a previous call 59 | warm_sum = sum(warm); 60 | for i = 1:sol_count, 61 | % check summation of warm first 62 | if (abs(sol_prev(i).y.sumx-warm_sum) <= tol), 63 | % check individual elements next 64 | if (abs(sol_prev(i).y.var.val-warm) <= tol), 65 | % return previous solution if values haven't changed 66 | y = sol_prev(i).y; 67 | return 68 | end 69 | end 70 | end 71 | 72 | % load warm.t0 to the server 73 | fid = fopen('warm.t0','w'); 74 | fprintf(fid,'%20.12e\n',warm); 75 | fclose(fid); 76 | 77 | t0_load(server,app,'warm.t0'); 78 | delete('warm.t0'); 79 | end 80 | 81 | % optionally load lagrange multipliers to server 82 | if (nargin>=4), 83 | % create 'lam' as a column vector 84 | if (size(lam,1)==1), 85 | lam = lam'; 86 | end 87 | 88 | fid = fopen('lam.t0','w'); 89 | fprintf(fid,'%20.12e\n',lam); 90 | fclose(fid); 91 | 92 | t0_load(server,app,'lam.t0'); 93 | delete('lam.t0'); 94 | end 95 | 96 | % compute details on server 97 | output = apm(server,app,'solve'); 98 | 99 | % retrieve variables and bounds 100 | apm_get(server,app,'apm_var.txt'); 101 | load apm_var.txt 102 | delete('apm_var.txt'); 103 | y.nvar = size(apm_var,1); % get number of variables 104 | y.var.lb = apm_var(:,1); 105 | y.var.val = apm_var(:,2); 106 | y.var.ub = apm_var(:,3); 107 | 108 | % retrieve objective function value 109 | apm_get(server,app,'apm_obj.txt'); 110 | load apm_obj.txt 111 | delete('apm_obj.txt'); 112 | y.obj = apm_obj; 113 | 114 | % retrieve objective gradient 115 | apm_get(server,app,'apm_obj_grad.txt'); 116 | load apm_obj_grad.txt 117 | delete('apm_obj_grad.txt'); 118 | y.obj_grad = apm_obj_grad; 119 | 120 | % retrieve equation residuals and bounds 121 | apm_get(server,app,'apm_eqn.txt'); 122 | load apm_eqn.txt 123 | delete('apm_eqn.txt'); 124 | y.neqn = size(apm_eqn,1); % get number of equations 125 | y.eqn.lb = apm_eqn(:,1); 126 | y.eqn.res = apm_eqn(:,2); 127 | y.eqn.ub = apm_eqn(:,3); 128 | 129 | % retrieve jacobian 130 | apm_get(server,app,'apm_jac.txt'); 131 | load apm_jac.txt 132 | delete('apm_jac.txt'); 133 | jac = apm_jac; 134 | y.jac = sparse(jac(:,1),jac(:,2),jac(:,3),y.neqn,y.nvar); 135 | 136 | % retrieve lagrange multipliers 137 | apm_get(server,app,'apm_lam.txt'); 138 | load apm_lam.txt 139 | delete('apm_lam.txt'); 140 | y.lam = apm_lam; 141 | 142 | % retrieve hessian of the objective only 143 | apm_get(server,app,'apm_hes_obj.txt'); 144 | load apm_hes_obj.txt 145 | delete('apm_hes_obj.txt'); 146 | hs = apm_hes_obj; 147 | y.hes_obj = sparse(hs(:,1),hs(:,2),hs(:,3),y.nvar,y.nvar); 148 | 149 | % retrieve hessian of the equations only 150 | apm_get(server,app,'apm_hes_eqn.txt'); 151 | load apm_hes_eqn.txt 152 | delete('apm_hes_eqn.txt'); 153 | hs = apm_hes_eqn; 154 | nhs = size(apm_hes_eqn,1); 155 | i1(1:y.neqn)=0; 156 | i2(1:y.neqn)=0; 157 | % equations listed in sequential order 158 | for i = 1:nhs, 159 | if(i1(hs(i,1))==0), 160 | i1(hs(i,1)) = i; 161 | end 162 | i2(hs(i,1)) = i; 163 | end 164 | for i = 1:y.neqn, 165 | if (i1(i)==0), 166 | y.hes_eqn{i} = sparse(y.nvar,y.nvar); 167 | else 168 | y.hes_eqn{i} = sparse(hs(i1(i):i2(i),2),hs(i1(i):i2(i),3),hs(i1(i):i2(i),4),y.nvar,y.nvar); 169 | end 170 | end 171 | 172 | % construct hessian from obj, lam, and eqn portions 173 | y.hes = y.hes_obj; 174 | for i = 1:y.neqn, 175 | y.hes = y.hes + y.lam(i) * y.hes_eqn{i}; 176 | end 177 | 178 | % store values 179 | sol_count = sol_count + 1; 180 | sol_prev(sol_count).y = y; 181 | sol_prev(sol_count).y.sumx = sum(y.var.val); -------------------------------------------------------------------------------- /apm/apm_get.m: -------------------------------------------------------------------------------- 1 | % APM Retrieve File From Server 2 | % 3 | % [] = apm_get(server,app,filename) 4 | % 5 | % Function apm_get retrieves the file from the web-server 6 | % with the following arguments: 7 | % 8 | % server = address of server 9 | % app = application name 10 | % filename = filename to retrieve 11 | % 12 | % A list of all file names that are accessible can be 13 | % obtained by issuing the command apm_web_root(server,app) 14 | % 15 | function [] = apm_get(server,app,filename) 16 | % get ip address for web-address lookup 17 | app = lower(deblank(app)); 18 | ip = deblank(urlread_apm([deblank(server) '/ip.php'])); 19 | url = [deblank(server) '/online/' ip '_' app '/' filename]; 20 | response = urlread_apm(url); 21 | % write file 22 | fid = fopen(filename,'w'); 23 | fwrite(fid,response); 24 | fclose(fid); 25 | -------------------------------------------------------------------------------- /apm/apm_id.m: -------------------------------------------------------------------------------- 1 | % Function apm_id for identification of a linear model 2 | % Inputs 3 | % data = data set with time, inputs, outputs 4 | % ni = number of inputs (others are outputs) 5 | % nu = number of input terms (numerator) 6 | % ny = number of output terms (denominator) 7 | % 8 | % Outputs 9 | % sysd = discrete transfer function estimated from data 10 | function sysd = apm_id(data,ni,nu,ny) 11 | 12 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 13 | % Configuration 14 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 15 | % include plots and other analysis if it does not need to be fast 16 | fast = false; 17 | obj_scale = 1; 18 | 19 | % size of data 20 | [n,p] = size(data); 21 | no = p - ni - 1; 22 | if (no<=0) 23 | error('Data file needs additional columns for outputs') 24 | end 25 | m = max(ny,nu); 26 | 27 | % time 28 | time = data(:,1); 29 | % time step 30 | dt = time(2) - time(1); 31 | % input 32 | u_ss = data(1,2:1+ni); 33 | u = data(:,2:1+ni); 34 | % output 35 | y_ss = data(1,2+ni:1+ni+no); 36 | y = data(:,2+ni:1+ni+no); 37 | for i = 1:size(y,1), 38 | u(i,:) = u(i,:) - u_ss; 39 | y(i,:) = y(i,:) - y_ss; 40 | end 41 | 42 | %% write model 43 | fid = fopen('myModel.apm','w'); 44 | fprintf(fid,'Objects\n'); 45 | fprintf(fid,' sum_a[1:no] = sum(%i)\n',ny); 46 | fprintf(fid,' sum_b[1:ni][1::no] = sum(%i)\n',nu); 47 | fprintf(fid,'End Objects\n'); 48 | fprintf(fid,' \n'); 49 | fprintf(fid,'Connections\n'); 50 | fprintf(fid,' a[1:ny][1::no] = sum_a[1::no].x[1:ny]\n'); 51 | fprintf(fid,' b[1:nu][1::ni][1:::no] = sum_b[1::ni][1:::no].x[1:nu]\n'); 52 | fprintf(fid,' sum_a[1:no] = sum_a[1:no].y\n'); 53 | fprintf(fid,' sum_b[1:ni][1::no] = sum_b[1:ni][1::no].y\n'); 54 | fprintf(fid,'End Connections\n'); 55 | fprintf(fid,' \n'); 56 | fprintf(fid,'Constants\n'); 57 | fprintf(fid,' n = %s\n',int2str(n)); 58 | fprintf(fid,' ni = %s\n',int2str(ni)); 59 | fprintf(fid,' no = %s\n',int2str(no)); 60 | fprintf(fid,' ny = %s\n',int2str(ny)); 61 | fprintf(fid,' nu = %s\n',int2str(nu)); 62 | fprintf(fid,' m = %s\n',int2str(m)); 63 | fprintf(fid,' \n'); 64 | fprintf(fid,'Parameters\n'); 65 | fprintf(fid,' a[1:ny][1::no] = 0 >= -1 <= 1\n'); 66 | fprintf(fid,' b[1:nu][1::ni][1:::no] = 0\n'); 67 | fprintf(fid,' c[1:no] = 0\n'); 68 | fprintf(fid,' u[1:n][1::ni]\n'); 69 | fprintf(fid,' y[1:m][1::no]\n'); 70 | fprintf(fid,' z[1:n][1::no]\n'); 71 | fprintf(fid,' \n'); 72 | fprintf(fid,'Variables\n'); 73 | fprintf(fid,' y[m+1:n][1::no] = 0\n'); 74 | fprintf(fid,' sum_a[1:no] = 0 , <= 1\n'); 75 | fprintf(fid,' sum_b[1:ni][1::no] = 0\n'); 76 | fprintf(fid,' K[1:ni][1::no] = 0 >= 0 <= 10\n'); 77 | fprintf(fid,' \n'); 78 | fprintf(fid,'Equations\n'); 79 | fprintf(fid,' y[m+1:n][1::no] = a[1][1::no]*y[m:n-1][1::no]'); 80 | for j = 1:ni 81 | fprintf(fid,' + b[1][%i][1::no]*u[m:n-1][%i]',j,j); 82 | for i = 2:nu 83 | fprintf(fid, ' + b[%i][%i][1::no]*u[m-%i:n-%i][%i]',i,j,i-1,i,j); 84 | end 85 | end 86 | for i = 2:ny 87 | fprintf(fid, ' + a[%i][1::no]*y[m-%i:n-%i][1::no]',i,i-1,i); 88 | end 89 | fprintf(fid,'\n'); 90 | % K(i,j) = sum(beta(:,j,i)) / (1-sum(alpha(:,i))); 91 | fprintf(fid,' K[1:ni][1::no] * (1 - sum_a[1::no]) = sum_b[1:ni][1::no]\n'); 92 | fprintf(fid,' minimize %12.8f * (y[m+1:n][1::no] - z[m+1:n][1::no])^2\n',obj_scale); 93 | fclose(fid); 94 | 95 | %% write data 96 | fid = fopen('myData.csv','w'); 97 | for j = 1:ni 98 | for i = 1:n 99 | fprintf(fid,'u[%i][%i], %12.8f\n', i,j,u(i,j)); 100 | end 101 | end 102 | for k = 1:no 103 | for i = 1:n 104 | fprintf(fid,'z[%i][%i], %12.8f\n', i,k,y(i,k)); 105 | end 106 | end 107 | for k = 1:no 108 | for i = 1:n 109 | fprintf(fid,'y[%i][%i], %12.8f\n', i,k,y(i,k)); 110 | end 111 | end 112 | fclose(fid); 113 | 114 | %% set up 115 | addpath('apm'); 116 | s = 'http://byu.apmonitor.com'; 117 | a = 'apm_id'; 118 | apm(s,a,'clear all'); 119 | apm_load(s,a,'myModel.apm'); 120 | csv_load(s,a,'myData.csv'); 121 | 122 | apm_option(s,a,'nlc.solver',3); 123 | apm_option(s,a,'nlc.imode',2); 124 | apm_option(s,a,'nlc.max_iter',100); 125 | 126 | % estimate nominal steady state conditions 127 | % c = y0 - sum_(i=1)^ny (ai * y0) - sum_(i=1)^nu (bi * u0) 128 | for i = 1:no 129 | name = ['c[' int2str(i) ']']; 130 | apm_info(s,a,'FV',name); 131 | apm_option(s,a,[name '.status'],0); 132 | end 133 | 134 | % estimate alphas 135 | for k = 1:no 136 | for i = 1:ny 137 | name = ['a[' int2str(i) '][' int2str(k) ']']; 138 | apm_info(s,a,'FV',name); 139 | apm_option(s,a,[name '.status'],1); 140 | end 141 | end 142 | % estimate betas 143 | for k = 1:no 144 | for j = 1:ni 145 | for i = 1:nu 146 | name = ['b[' int2str(i) '][' int2str(j) '][' int2str(k) ']']; 147 | apm_info(s,a,'FV',name); 148 | apm_option(s,a,[name '.status'],1); 149 | end 150 | end 151 | end 152 | %% solve 153 | output = apm(s,a,'solve'); 154 | disp(output); 155 | 156 | 157 | %% retrieve and visualize solution 158 | sol = apm_sol(s,a); 159 | for j = 1:no 160 | for i = 1:n 161 | eval(['ypred(' int2str(i) ',' int2str(j) ') = sol.x.y' int2str(i) int2str(j) ';']); 162 | end 163 | end 164 | for j = 1:no 165 | for i = 1:ny 166 | name = ['a[' int2str(i) '][' int2str(j) ']']; 167 | alpha(i,j) = apm_tag(s,a,[name '.newval']); 168 | end 169 | end 170 | for k = 1:no 171 | for j = 1:ni 172 | for i = 1:nu 173 | name = ['b[' int2str(i) '][' int2str(j) '][' int2str(k) ']']; 174 | beta(i,j,k) = apm_tag(s,a,[name '.newval']); 175 | end 176 | end 177 | end 178 | for i = 1:no 179 | name = ['c[' int2str(i) ']']; 180 | gamma(i) = apm_tag(s,a,[name '.newval']); 181 | end 182 | 183 | for i = 1:no 184 | for j = 1:ni 185 | K(i,j) = sum(beta(:,j,i)) / (1-sum(alpha(:,i))); 186 | end 187 | end 188 | 189 | if (~fast), 190 | disp('alpha:') 191 | disp(alpha) 192 | disp('beta:') 193 | disp(beta) 194 | disp('gamma:') 195 | disp(gamma) 196 | disp('K') 197 | disp(K) 198 | 199 | % plot results 200 | figure(1) 201 | 202 | subplot(2,1,1) 203 | plot(time,u(:,1),'r-','LineWidth',2); 204 | 205 | subplot(2,1,2) 206 | plot(time,y,'b--','LineWidth',2); 207 | hold on 208 | plot(time,ypred); 209 | 210 | apm_web(s,a); 211 | end 212 | 213 | % generate ARX model 214 | apm_arx(no,ni,ny,nu,alpha,beta,gamma,'sysa'); 215 | 216 | % generate different model forms 217 | % MATLAB doesn't like zero roots 218 | for i = 1:ny, 219 | for j = 1:no, 220 | if (abs(alpha(i,j))<1e-5), 221 | alpha(i,j) = 1e-5; 222 | end 223 | end 224 | end 225 | % create LTI model, discrete transfer function 226 | for i = 1:no, 227 | for j = 1:ni, 228 | sysd(i,j) = tf([0 beta(:,j,i)'],[1 -alpha(:,i)'],dt,'Variable','z^-1'); 229 | end 230 | end 231 | 232 | % generate APMonitor model files (sysc.apm and sysd.apm) 233 | % discrete state space models 234 | apm_lti(sysd,'sysd'); 235 | if (~fast) 236 | % generate continuous state space form 237 | sysc = d2c(sysd); 238 | apm_lti(sysd,'sysc'); 239 | figure(2) 240 | step(sysd,sysc) 241 | end 242 | 243 | return -------------------------------------------------------------------------------- /apm/apm_info.m: -------------------------------------------------------------------------------- 1 | % APM Variable Classification 2 | % class = FV, MV, SV, CV 3 | % F or FV = Fixed value - parameter may change to a new value every cycle 4 | % M or MV = Manipulated variable - independent variable over time horizon 5 | % S or SV = State variable - model variable for viewing 6 | % C or CV = Controlled variable - model variable for control 7 | function response = apm_info(server,app,class,name) 8 | app = lower(deblank(app)); 9 | aline = ['info ' deblank(char(class)) ', ' deblank(char(name))]; 10 | response = apm(server,app,aline); 11 | -------------------------------------------------------------------------------- /apm/apm_linear.m: -------------------------------------------------------------------------------- 1 | function msg = apm_linear(A,b,type,name) 2 | 3 | filename = [name '.apm']; 4 | 5 | % extract A, b in sparse form 6 | [mA,nA] = size(A); 7 | if isempty(b), 8 | b = zeros(mA,1); 9 | mB = mA; 10 | else 11 | if size(b,1)==1, 12 | b = b'; 13 | end 14 | [mB,nB] = size(b); 15 | end 16 | if (mA~=mB), 17 | error('Rows of A and b must agree'); 18 | end 19 | % convert to sparse form 20 | [ai,aj,av] = find(sparse(A)); 21 | a = [ai,aj,av]'; 22 | [bi,bj,bv] = find(sparse(b)); 23 | b = [bi,bj,bv]'; 24 | if(size(b,2)==0), 25 | b = [1,1,0]'; 26 | end 27 | br = [b(1,:); b(3,:)]; 28 | 29 | fid = fopen(filename,'w'); 30 | fprintf( fid,'\n'); 31 | fprintf( fid,'Objects \n'); 32 | fprintf( fid,[' ' name ' = axb\n']); 33 | fprintf( fid,'End Objects \n'); 34 | fprintf( fid,'\n'); 35 | fprintf( fid,'Connections\n'); 36 | fprintf( fid,[' x[1:%d] = ' name '.x[1:%d]\n'],nA,nA); 37 | fprintf( fid,'End Connections\n'); 38 | fprintf( fid,'\n'); 39 | fprintf( fid,'Model \n'); 40 | fprintf( fid,' Variables \n'); 41 | fprintf( fid,' x[1:%d] = 0\n',nA); 42 | fprintf( fid,' End Variables \n'); 43 | fprintf( fid,'\n'); 44 | fprintf( fid,' Equations \n'); 45 | fprintf( fid,' ! add any additional equations here \n'); 46 | fprintf( fid,' End Equations \n'); 47 | fprintf( fid,'End Model \n'); 48 | fprintf( fid,'\n'); 49 | fprintf( fid,['File ' name '.txt\n']); 50 | form = ['Ax' strtrim(type) 'b']; 51 | fprintf( fid,[' sparse, ' form ' ! dense or sparse, Ax=b or Axb\n']); 52 | fprintf( fid,' %d ! m=number of rows in A and b \n',mA); 53 | fprintf( fid,' %d ! n=number of columns in A or variables x\n',nA); 54 | fprintf( fid,'End File\n'); 55 | fprintf( fid,'\n'); 56 | fprintf( fid,['File ' name '.a.txt \n']); 57 | fprintf( fid,' %d %d %f\n', a ); 58 | fprintf( fid,'End File \n'); 59 | fprintf( fid,'\n'); 60 | fprintf( fid,['File ' name '.b.txt \n']); 61 | fprintf( fid,' %d %f\n', br ); 62 | fprintf( fid,'End File \n'); 63 | fclose(fid); 64 | 65 | msg = ['Created Linear (Axb) Model: ' filename]; 66 | 67 | end -------------------------------------------------------------------------------- /apm/apm_linprog.m: -------------------------------------------------------------------------------- 1 | function y = apm_linprog(f,A,b,Aeq,beq,lb,ub,x0) 2 | %apm_linprog Linear programming. 3 | % y = apm_linprog(f,A,b,Aeq,beq,LB,UB,X0) writes a linear 4 | % programming model in APMonitor Modeling Language and attempts 5 | % to solve the linear programming problem: 6 | % 7 | % min f'*x subject to: A*x <= b, Aeq*x = beq 8 | % x 9 | % 10 | % lb and ub are a set of lower and upper bounds on the design variables, 11 | % x, so that the solution is in the range lb <= x <= ub. Use empty 12 | % matrices for any of the arguments. Set lb(i) = -1e20 if x(i) has no 13 | % lower limit and set ub(i) = 1e20 if x(i) has no upper limit. x0 is 14 | % the initial guess and starting point to x. This is similar to the 15 | % Matlab linprog solver but uses different solvers such as IPOPT, 16 | % APOPT, and BPOPT to solve the LP. Additional nonlinear constraints 17 | % can be added to the lp.apm model for nonlinear programming solution 18 | % with support for possible mixed-integer variables. 19 | % 20 | % The solution is returned in the structure y with y.names (variable 21 | % names), y.values (variable values), y.nvar (number of variables), 22 | % and y.x (a structure containing each variable and value). 23 | % 24 | % Example usage is below: 25 | % 26 | % clear all; close all; clc 27 | % addpath('apm') 28 | % 29 | % % example Linear program 30 | % f = [-5; -4; -6]; 31 | % A = [1 -1 1 32 | % 3 2 4 33 | % 3 2 0]; 34 | % b = [20; 42; 30]; 35 | % Aeq = []; 36 | % beq = []; 37 | % lb = zeros(3,1); 38 | % ub = []; 39 | % x0 = []; 40 | % 41 | % % generate and solve APMonitor LP model 42 | % y1 = apm_linprog(f,A,b,Aeq,beq,lb,ub,x0); 43 | % 44 | % % compare solution to linprog (MATLAB) 45 | % y2 = linprog(f,A,b,Aeq,beq,lb,ub,x0); 46 | % 47 | % disp('Validate Results with MATLAB linprog') 48 | % for i = 1:max(size(f)), 49 | % disp(['x[' int2str(i) ']: ' num2str(y1.values(i)) ' = ' num2str(y2(i))]) 50 | % end 51 | 52 | 53 | %% filename to write 54 | filename = ['lp.apm']; 55 | 56 | % extract f in sparse form 57 | if ~isempty(f), 58 | nf = max(size(f)); 59 | if size(f,1)==1, 60 | f = f'; 61 | end 62 | H = zeros(1,1); 63 | 64 | % convert to sparse form 65 | [hi,hj,hv] = find(sparse(H)); 66 | h = [hi,hj,hv]'; 67 | [fi,fj,fv] = find(sparse(f)); 68 | f = [fi,fj,fv]'; 69 | if(size(f,2)==0), 70 | f = [1,1,0]'; 71 | end 72 | fr = [f(1,:); f(3,:)]; 73 | end 74 | 75 | % extract A and b in sparse form 76 | if ~isempty(A), 77 | [mA,nA] = size(A); 78 | if isempty(b), 79 | b = zeros(mA,1); 80 | mB = mA; 81 | else 82 | if size(b,1)==1, 83 | b = b'; 84 | end 85 | [mB,nB] = size(b); 86 | end 87 | if (mA~=mB), 88 | error('Rows of A and b must agree'); 89 | end 90 | 91 | % convert to sparse form 92 | [ai,aj,av] = find(sparse(A)); 93 | if (mA==1), 94 | a = [ai;aj;av]; 95 | else 96 | a = [ai,aj,av]'; 97 | end 98 | [bi,bj,bv] = find(sparse(b)); 99 | b = [bi,bj,bv]'; 100 | if(size(b,2)==0), 101 | b = [1,1,0]'; 102 | end 103 | br = [b(1,:); b(3,:)]; 104 | end 105 | 106 | % extract Aeq and beq in sparse form 107 | if ~isempty(Aeq), 108 | [mAeq,nAeq] = size(Aeq); 109 | if isempty(beq), 110 | beq = zeros(mAeq,1); 111 | mBeq = mAeq; 112 | else 113 | if size(beq,1)==1, 114 | beq = beq'; 115 | end 116 | [mBeq,nBeq] = size(beq); 117 | end 118 | if (mAeq~=mBeq), 119 | error('Rows of Aeq and beq must agree'); 120 | end 121 | 122 | % convert to sparse form 123 | [aeqi,aeqj,aeqv] = find(sparse(Aeq)); 124 | if (mAeq==1), 125 | aeq = [aeqi;aeqj;aeqv]; 126 | else 127 | aeq = [aeqi,aeqj,aeqv]'; 128 | end 129 | [beqi,beqj,beqv] = find(sparse(beq)); 130 | beq = [beqi,beqj,beqv]'; 131 | if(size(beq,2)==0), 132 | beq = [1,1,0]'; 133 | end 134 | beqr = [beq(1,:); beq(3,:)]; 135 | end 136 | 137 | disp('Creating Linear Programming Model lp.apm'); 138 | fid = fopen(filename,'w'); 139 | fprintf( fid,'\n'); 140 | fprintf( fid,'Objects \n'); 141 | if ~isempty(f), 142 | fprintf( fid,[' h = qobj\n']); 143 | end 144 | if ~isempty(A), 145 | fprintf( fid,[' a = axb\n']); 146 | end 147 | if ~isempty(Aeq), 148 | fprintf( fid,[' aeq = axb\n']); 149 | end 150 | fprintf( fid,'End Objects \n'); 151 | fprintf( fid,'\n'); 152 | fprintf( fid,'Connections\n'); 153 | sz = -1; 154 | if ~isempty(f), 155 | fprintf( fid,[' x[1:%d] = h.x[1:%d]\n'],nf,nf); 156 | sz = nf; 157 | end 158 | if ~isempty(A), 159 | fprintf( fid,[' x[1:%d] = a.x[1:%d]\n'],nA,nA); 160 | if (sz>=0), 161 | if (nA~=sz), 162 | error('Variables in Ax < b model must be consistent'); 163 | end 164 | end 165 | end 166 | if ~isempty(Aeq), 167 | fprintf( fid,[' x[1:%d] = aeq.x[1:%d]\n'],nAeq,nAeq); 168 | if (sz>=0), 169 | if (nAeq~=sz), 170 | error('Variables in Ax = b model must be consistent'); 171 | end 172 | end 173 | end 174 | fprintf( fid,'End Connections\n'); 175 | fprintf( fid,'\n'); 176 | fprintf( fid,'Model \n'); 177 | fprintf( fid,' Variables \n'); 178 | if (isempty(x0)&&isempty(lb)&&isempty(ub)), 179 | % default initial conditions 180 | fprintf( fid,' x[1:%d] = 0\n',nH); 181 | else 182 | % create default values 183 | if (isempty(x0)), 184 | x0 = zeros(nf,1); 185 | end 186 | if (isempty(lb)), 187 | lb = -1e10 * ones(nf,1); 188 | end 189 | if (isempty(ub)), 190 | ub = 1e10 * ones(nf,1); 191 | end 192 | % generate initial conditions and bounds 193 | for i = 1:nf, 194 | fprintf( fid,' x[%i] > %d = %d < %d\n',i,lb(i),x0(i),ub(i)); 195 | end 196 | end 197 | fprintf( fid,' End Variables \n'); 198 | fprintf( fid,'\n'); 199 | fprintf( fid,' Equations \n'); 200 | fprintf( fid,' ! add any additional equations here \n'); 201 | fprintf( fid,' End Equations \n'); 202 | fprintf( fid,'End Model \n'); 203 | fprintf( fid,'\n'); 204 | 205 | if ~isempty(f), 206 | fprintf( fid,'\n'); 207 | fprintf( fid,['File h.txt\n']); 208 | fprintf( fid,[' sparse, minimize ! dense or sparse, minimize or maximize\n']); 209 | fprintf( fid,' %d ! n=number of variables \n',nf); 210 | fprintf( fid,'End File\n'); 211 | fprintf( fid,'\n'); 212 | fprintf( fid,'File h.a.txt \n'); 213 | fprintf( fid,' 1 1 0\n'); 214 | fprintf( fid,'End File \n'); 215 | fprintf( fid,'\n'); 216 | fprintf( fid,['File h.b.txt \n']); 217 | fprintf( fid,' %d %f\n', fr ); 218 | fprintf( fid,'End File \n'); 219 | end 220 | 221 | if ~isempty(A), 222 | fprintf( fid,'\n'); 223 | fprintf( fid,['File a.txt\n']); 224 | fprintf( fid,[' sparse, Ax0), 21 | discrete = true; 22 | else 23 | discrete = false; 24 | end 25 | 26 | % extract A, B, C, D matrices in sparse form 27 | [n,m] = size(sys.B); 28 | [p,m] = size(sys.D); 29 | 30 | [ai,aj,av] = find(sparse(sys.A)); 31 | a = [ai,aj,av]'; 32 | [bi,bj,bv] = find(sparse(sys.B)); 33 | b = [bi,bj,bv]'; 34 | [ci,cj,cv] = find(sparse(sys.C)); 35 | if (size(sys.C,1)==1), 36 | c = [ci;cj;cv]; 37 | else 38 | c = [ci,cj,cv]'; 39 | end 40 | [di,dj,dv] = find(sparse(sys.D)); 41 | d = [di,dj,dv]'; 42 | if(size(d,2)==0), 43 | d = [1,1,0]'; 44 | end 45 | 46 | fid = fopen(filename,'w'); 47 | fprintf( fid,'\n'); 48 | fprintf( fid,'Objects \n'); 49 | fprintf( fid,[' ' name ' = lti\n']); 50 | fprintf( fid,'End Objects \n'); 51 | fprintf( fid,'\n'); 52 | fprintf( fid,'Connections\n'); 53 | fprintf( fid,[' u[1:%d] = ' name '.u[1:%d]\n'],m,m); 54 | fprintf( fid,[' x[1:%d] = ' name '.x[1:%d]\n'],n,n); 55 | fprintf( fid,[' y[1:%d] = ' name '.y[1:%d]\n'],p,p); 56 | fprintf( fid,'End Connections\n'); 57 | fprintf( fid,'\n'); 58 | fprintf( fid,'Model \n'); 59 | fprintf( fid,' Parameters \n'); 60 | fprintf( fid,' u[1:%d] = 0\n',m); 61 | fprintf( fid,' End Parameters \n'); 62 | fprintf( fid,'\n'); 63 | fprintf( fid,' Variables \n'); 64 | fprintf( fid,' x[1:%d] = 0\n',n); 65 | fprintf( fid,' y[1:%d] = 0\n',p); 66 | fprintf( fid,' End Variables \n'); 67 | fprintf( fid,'\n'); 68 | fprintf( fid,' Equations \n'); 69 | fprintf( fid,' ! add any additional equations here \n'); 70 | fprintf( fid,' End Equations \n'); 71 | fprintf( fid,'End Model \n'); 72 | fprintf( fid,'\n'); 73 | fprintf( fid,'! dimensions\n'); 74 | fprintf( fid,'! (nx1) = (nxn)*(nx1) + (nxm)*(mx1)\n'); 75 | fprintf( fid,'! (px1) = (pxn)*(nx1) + (pxm)*(mx1)\n'); 76 | fprintf( fid,'!\n'); 77 | if discrete, 78 | fprintf( fid,'! discrete form with sampling time = %f\n',sys.Ts); 79 | fprintf( fid,'! x[k+1] = A * x[k] + B * u[k]\n'); 80 | fprintf( fid,'! y[k] = C * x[k] + D * u[k]\n'); 81 | else 82 | fprintf( fid,'! continuous form\n'); 83 | fprintf( fid,'! dx/dt = A * x + B * u\n'); 84 | fprintf( fid,'! y = C * x + D * u\n'); 85 | end 86 | fprintf( fid,['File ' name '.txt\n']); 87 | if discrete, 88 | fprintf( fid,' sparse, discrete ! dense/sparse, continuous/discrete\n'); 89 | else 90 | fprintf( fid,' sparse, continuous ! dense/sparse, continuous/discrete\n'); 91 | end 92 | fprintf( fid,' %d ! m=number of inputs\n',m); 93 | fprintf( fid,' %d ! n=number of states\n',n); 94 | fprintf( fid,' %d ! p=number of outputs\n',p); 95 | fprintf( fid,'End File\n'); 96 | fprintf( fid,'\n'); 97 | fprintf( fid,['File ' name '.a.txt \n']); 98 | fprintf( fid,' %d %d %f\n', a ); 99 | fprintf( fid,'End File \n'); 100 | fprintf( fid,'\n'); 101 | fprintf( fid,['File ' name '.b.txt \n']); 102 | fprintf( fid,' %d %d %f\n', b ); 103 | fprintf( fid,'End File \n'); 104 | fprintf( fid,'\n'); 105 | fprintf( fid,['File ' name '.c.txt \n']); 106 | fprintf( fid,' %d %d %f\n', c ); 107 | fprintf( fid,'End File \n'); 108 | fprintf( fid,'\n'); 109 | fprintf( fid,['File ' name '.d.txt \n']); 110 | fprintf( fid,' %d %d %f\n', d ); 111 | fprintf( fid,'End File \n'); 112 | fclose(fid); 113 | 114 | msg = ['Created Linear Time Invariant (LTI) Model: ' filename]; 115 | 116 | end -------------------------------------------------------------------------------- /apm/apm_meas.m: -------------------------------------------------------------------------------- 1 | % APM Input Measured Value 2 | % 3 | % response = apm_meas(server,app,name,value) 4 | % 5 | % Function apm_meas sends a measurement to the APM server 6 | % with the following arguments: 7 | % 8 | % server = address of server 9 | % app = application name 10 | % name = parameter or variable name 11 | % value = measurement value 12 | % 13 | % A response is returned indicating whether the measurement 14 | % was successfully recorded 15 | % 16 | function response = apm_meas(server,app,name,value) 17 | 18 | % Web-server URL base 19 | app = lower(deblank(app)); 20 | name = strcat(name,'.meas'); 21 | params = ['?p=' urlencode(app) '&n=' urlencode(name) '&v=' urlencode(num2str(value))]; 22 | url = [deblank(server) '/online/meas.php' params]; 23 | 24 | % Send request to web-server 25 | response = urlread_apm(url); 26 | -------------------------------------------------------------------------------- /apm/apm_option.m: -------------------------------------------------------------------------------- 1 | % APM Specify Options 2 | % 3 | % response = apm_option(server,app,name,value) 4 | % 5 | % Function apm_option sends an option specification 6 | % to the APM server with the following arguments: 7 | % 8 | % server = address of server 9 | % app = application name 10 | % name = option name 11 | % value = option value 12 | % 13 | % A response is returned indicating whether the option 14 | % was successfully recorded 15 | % 16 | % Either global options (NLC.option_name) or parameter/variable 17 | % options (NAME.option_name) are able to be specified with this 18 | % function. A full list of available options with their default 19 | % values are available here: 20 | % 21 | % Global Options: 22 | % http://apmonitor.com/wiki/index.php/Main/DbsGlobal 23 | % 24 | % Variable Options: 25 | % http://apmonitor.com/wiki/index.php/Main/DbsVariable 26 | % 27 | function response = apm_option(server,app,name,value) 28 | app = lower(deblank(app)); 29 | aline = ['option ' deblank(char(name)) ' = ' num2str(value)]; 30 | response = apm(server,app,aline); 31 | 32 | -------------------------------------------------------------------------------- /apm/apm_quadprog.m: -------------------------------------------------------------------------------- 1 | function y = apm_quadprog(H,f,A,b,Aeq,beq,lb,ub,x0) 2 | %apm_quadprog Quadratic programming. 3 | % y = apm_quadprog(H,f,A,b,Aeq,beq,LB,UB,X0) writes a quadratic 4 | % programming model in APMonitor Modeling Language and attempts 5 | % to solve the quadratic programming problem: 6 | % 7 | % min 0.5*x'*H*x + f'*x subject to: A*x <= b, Aeq*x = beq 8 | % x 9 | % 10 | % lb and ub are a set of lower and upper bounds on the design variables, 11 | % x, so that the solution is in the range lb <= x <= ub. Use empty 12 | % matrices for any of the arguments. Set lb(i) = -1e20 if x(i) has no 13 | % lower limit and set ub(i) = 1e20 if x(i) has no upper limit. x0 is 14 | % the initial guess and starting point to x. This is similar to the 15 | % Matlab quadprog solver but uses different solvers such as IPOPT, 16 | % APOPT, and BPOPT to solve the QP. Additional nonlinear constraints 17 | % can be added to the qp.apm model for nonlinear programming solution 18 | % with support for possible mixed-integer variables. 19 | % 20 | % The solution is returned in the structure y with y.names (variable 21 | % names), y.values (variable values), y.nvar (number of variables), 22 | % and y.x (a structure containing each variable and value). 23 | % 24 | % Example usage is below: 25 | % 26 | % clear all; close all; clc 27 | % disp('APM MATLAB available for download at http://apmonitor.com') 28 | % addpath('apm') 29 | % 30 | % %% example Quadratic program 31 | % H = [1 -1; -1 2]; 32 | % f = [-2; -6]; 33 | % A = [1 1; -1 2; 2 1]; 34 | % b = [2; 2; 3]; 35 | % Aeq = []; 36 | % beq = []; 37 | % lb = zeros(2,1); 38 | % ub = []; 39 | % x0 = []; 40 | % 41 | % %% generate APMonitor QP model 42 | % y1 = apm_quadprog(H,f,A,b,Aeq,beq,lb,ub,x0); 43 | % 44 | % %% compare solution to quadprog (MATLAB) 45 | % y2 = quadprog(H,f,A,b,Aeq,beq,lb,ub,x0) 46 | % 47 | % disp('Validate Results with MATLAB linprog') 48 | % for i = 1:nx, 49 | % disp(['x[' int2str(i) ']: ' num2str(y1.values(i)) ' = ' num2str(y2(i))]) 50 | % end 51 | 52 | 53 | % filename to write 54 | filename = ['qp.apm']; 55 | 56 | % extract H and f in sparse form 57 | if ~isempty(H), 58 | [mH,nH] = size(H); 59 | if (mH~=nH), 60 | error('H must be a square matrix'); 61 | end 62 | if isempty(f), 63 | f = zeros(mH,1); 64 | mf = mH; 65 | else 66 | if size(f,1)==1, 67 | f = f'; 68 | end 69 | [mf,nf] = size(f); 70 | end 71 | if (mH~=mf), 72 | error('Rows of H and f must agree'); 73 | end 74 | 75 | % convert to sparse form 76 | [hi,hj,hv] = find(sparse(H)); 77 | h = [hi,hj,hv]'; 78 | [fi,fj,fv] = find(sparse(f)); 79 | f = [fi,fj,fv]'; 80 | if(size(f,2)==0), 81 | f = [1,1,0]'; 82 | end 83 | fr = [f(1,:); f(3,:)]; 84 | end 85 | 86 | % extract A and b in sparse form 87 | if ~isempty(A), 88 | [mA,nA] = size(A); 89 | if isempty(b), 90 | b = zeros(mA,1); 91 | mB = mA; 92 | else 93 | if size(b,1)==1, 94 | b = b'; 95 | end 96 | [mB,nB] = size(b); 97 | end 98 | if (mA~=mB), 99 | error('Rows of A and b must agree'); 100 | end 101 | 102 | % convert to sparse form 103 | [ai,aj,av] = find(sparse(A)); 104 | if (mA==1), 105 | a = [ai;aj;av]; 106 | else 107 | a = [ai,aj,av]'; 108 | end 109 | [bi,bj,bv] = find(sparse(b)); 110 | b = [bi,bj,bv]'; 111 | if(size(b,2)==0), 112 | b = [1,1,0]'; 113 | end 114 | br = [b(1,:); b(3,:)]; 115 | end 116 | 117 | % extract Aeq and beq in sparse form 118 | if ~isempty(Aeq), 119 | [mAeq,nAeq] = size(Aeq); 120 | if isempty(beq), 121 | beq = zeros(mAeq,1); 122 | mBeq = mAeq; 123 | else 124 | if size(beq,1)==1, 125 | beq = beq'; 126 | end 127 | [mBeq,nBeq] = size(beq); 128 | end 129 | if (mAeq~=mBeq), 130 | error('Rows of Aeq and beq must agree'); 131 | end 132 | 133 | % convert to sparse form 134 | [aeqi,aeqj,aeqv] = find(sparse(Aeq)); 135 | if (mAeq==1), 136 | aeq = [aeqi;aeqj;aeqv]; 137 | else 138 | aeq = [aeqi,aeqj,aeqv]'; 139 | end 140 | [beqi,beqj,beqv] = find(sparse(beq)); 141 | beq = [beqi,beqj,beqv]'; 142 | if(size(beq,2)==0), 143 | beq = [1,1,0]'; 144 | end 145 | beqr = [beq(1,:); beq(3,:)]; 146 | end 147 | 148 | disp('Creating Quadratic Programming Model qp.apm'); 149 | fid = fopen(filename,'w'); 150 | fprintf( fid,'\n'); 151 | fprintf( fid,'Objects \n'); 152 | if ~isempty(H), 153 | fprintf( fid,[' h = qobj\n']); 154 | end 155 | if ~isempty(A), 156 | fprintf( fid,[' a = axb\n']); 157 | end 158 | if ~isempty(Aeq), 159 | fprintf( fid,[' aeq = axb\n']); 160 | end 161 | fprintf( fid,'End Objects \n'); 162 | fprintf( fid,'\n'); 163 | fprintf( fid,'Connections\n'); 164 | sz = -1; 165 | if ~isempty(H), 166 | fprintf( fid,[' x[1:%d] = h.x[1:%d]\n'],nH,nH); 167 | sz = nH; 168 | end 169 | if ~isempty(A), 170 | fprintf( fid,[' x[1:%d] = a.x[1:%d]\n'],nA,nA); 171 | if (sz>=0), 172 | if (nA~=sz), 173 | error('Variables in Ax < b model must be consistent'); 174 | end 175 | end 176 | end 177 | if ~isempty(Aeq), 178 | fprintf( fid,[' x[1:%d] = aeq.x[1:%d]\n'],nAeq,nAeq); 179 | if (sz>=0), 180 | if (nAeq~=sz), 181 | error('Variables in Ax = b model must be consistent'); 182 | end 183 | end 184 | end 185 | fprintf( fid,'End Connections\n'); 186 | fprintf( fid,'\n'); 187 | fprintf( fid,'Model \n'); 188 | fprintf( fid,' Variables \n'); 189 | if (isempty(x0)&&isempty(lb)&&isempty(ub)), 190 | % default initial conditions 191 | fprintf( fid,' x[1:%d] = 0\n',nH); 192 | else 193 | % create default values 194 | if (isempty(x0)), 195 | x0 = zeros(nH,1); 196 | end 197 | if (isempty(lb)), 198 | lb = -1e10 * ones(nH,1); 199 | end 200 | if (isempty(ub)), 201 | ub = 1e10 * ones(nH,1); 202 | end 203 | % generate initial conditions and bounds 204 | for i = 1:nH, 205 | fprintf( fid,' x[%i] > %d = %d < %d\n',i,lb(i),x0(i),ub(i)); 206 | end 207 | end 208 | fprintf( fid,' End Variables \n'); 209 | fprintf( fid,'\n'); 210 | fprintf( fid,' Equations \n'); 211 | fprintf( fid,' ! add any additional equations here \n'); 212 | fprintf( fid,' End Equations \n'); 213 | fprintf( fid,'End Model \n'); 214 | fprintf( fid,'\n'); 215 | 216 | if ~isempty(H), 217 | fprintf( fid,'\n'); 218 | fprintf( fid,['File h.txt\n']); 219 | fprintf( fid,[' sparse, minimize ! dense or sparse, minimize or maximize\n']); 220 | fprintf( fid,' %d ! n=number of variables \n',mH); 221 | fprintf( fid,'End File\n'); 222 | fprintf( fid,'\n'); 223 | fprintf( fid,['File h.a.txt \n']); 224 | fprintf( fid,' %d %d %f\n', h ); 225 | fprintf( fid,'End File \n'); 226 | fprintf( fid,'\n'); 227 | fprintf( fid,['File h.b.txt \n']); 228 | fprintf( fid,' %d %f\n', fr ); 229 | fprintf( fid,'End File \n'); 230 | end 231 | 232 | if ~isempty(A), 233 | fprintf( fid,'\n'); 234 | fprintf( fid,['File a.txt\n']); 235 | fprintf( fid,[' sparse, Ax--- Launch APM Web Interface ---']) 26 | %%disp([' ' url]) -------------------------------------------------------------------------------- /apm/apm_web_root.m: -------------------------------------------------------------------------------- 1 | % APM Open Web Root Folder in Internet Browser 2 | % 3 | % stat = apm_web_root(server,app) 4 | % 5 | % Function apm_web_root opens the default web-browser 6 | % and loads a list of files that can be selected for 7 | % download or viewing 8 | % 9 | % server = address of server 10 | % app = application name 11 | % stat = message returned when opening browser 12 | % 13 | function [stat] = apm_web_root(server,app) 14 | % get ip address for web-address lookup 15 | ip = deblank(urlread_apm([deblank(server) '/ip.php'])); 16 | app = lower(deblank(app)); 17 | url = [deblank(server) '/online/' ip '_' app '/']; 18 | 19 | % load web-interface in default browser 20 | stat = web(url,'-browser'); % doesn't work in some older MATLAB versions 21 | -------------------------------------------------------------------------------- /apm/apm_web_var.m: -------------------------------------------------------------------------------- 1 | % APM Open Web Page with Variable Values 2 | % 3 | % stat = apm_web_var(server,app) 4 | % 5 | % Function apm_web_var opens the default web-browser 6 | % and loads a table of variable values 7 | % 8 | % server = address of server 9 | % app = application name 10 | % stat = message returned when opening browser 11 | % 12 | function [stat] = apm_web_var(server,app) 13 | % get ip address for web-address lookup 14 | ip = deblank(urlread_apm([deblank(server) '/ip.php'])); 15 | app = lower(deblank(app)); 16 | url = [deblank(server) '/online/' ip '_' app '/' ip '_' app '_var.htm']; 17 | 18 | % load web-interface in default browser 19 | stat = web(url,'-browser'); % doesn't work in some older MATLAB versions 20 | 21 | % display web address and allow the user to click to open 22 | %%disp(['--- Launch APM Web Interface ---']) 23 | %%disp([' ' url]) -------------------------------------------------------------------------------- /apm/csv_data.m: -------------------------------------------------------------------------------- 1 | % Load CSV File into MATLAB 2 | % 3 | % A = csv_data(filename) 4 | % 5 | % Function csv_data extracts data from a comma 6 | % separated value (csv) file and returns it 7 | % to the matrix A 8 | % 9 | function [A] = csv_data(filename) 10 | % load data from csv file with header 11 | fid = fopen(filename, 'r'); 12 | aline = fgetl(fid); 13 | 14 | % Split header 15 | A(1,:) = deblank(parse(aline, ',')); 16 | 17 | % Parse and read rest of file 18 | ctr = 1; 19 | while(~feof(fid)) 20 | if ischar(aline) 21 | ctr = ctr + 1; 22 | aline = fgetl(fid); 23 | A(ctr,:) = parse(aline, ','); 24 | else 25 | break; 26 | end 27 | end 28 | fclose(fid); 29 | -------------------------------------------------------------------------------- /apm/csv_element.m: -------------------------------------------------------------------------------- 1 | % Retrieve CSV element 2 | % 3 | % value = csv_element(name,row,csv) 4 | % 5 | % This function looks up "name" in the cell 6 | % array "csv" and returns the value in row 7 | % number "row" 8 | % 9 | function value = csv_element(name,row,csv) 10 | % Size of CSV data 11 | [rows,cols] = size(csv); 12 | % Take last row if beyond max rows 13 | if (row>rows), 14 | row = rows-1; 15 | end 16 | % get column number 17 | col = csv_lookup(name,csv); 18 | if (col>=1), 19 | value = str2num(csv{row+1,col}); 20 | else 21 | value = NaN; 22 | end 23 | -------------------------------------------------------------------------------- /apm/csv_load.m: -------------------------------------------------------------------------------- 1 | % APM Load Data File 2 | % 3 | % response = csv_load(server,app,filename) 4 | % 5 | % Function csv_load uploads the data file (csv) to the web-server 6 | % with the following arguments: 7 | % 8 | % server = address of server 9 | % app = application name 10 | % filename = data filename 11 | % 12 | % A response is returned indicating whether the file was 13 | % uploaded successfully to the server 14 | % 15 | function [response] = csv_load(server,app,filename) 16 | % convert to lowercase and deblank 17 | app = lower(deblank(app)); 18 | 19 | % load model 20 | fid=fopen(filename,'r'); 21 | tline = []; 22 | while 1 23 | aline = fgets(fid); 24 | if ~ischar(aline), break, end 25 | % remove any double quote marks 26 | aline = [strrep(aline,'"',' ')]; 27 | tline = [tline aline]; 28 | end 29 | fclose(fid); 30 | 31 | % send to server once for every 2000 characters 32 | ts = size(tline,2); 33 | block = 2000; 34 | cycles = ceil(ts/block); 35 | for i = 1:cycles, 36 | if ilen(replay)): row = len(replay)-1 203 | # get column number 204 | col = csv_lookup(name,replay) 205 | if (col>=0): value = float(replay[row][col]) 206 | else: value = float('nan') 207 | return value 208 | 209 | def apm_tag(server,app,name): 210 | '''Retrieve options for FV, MV, SV, or CV \n \ 211 | server = address of server \n \ 212 | app = application name \n \ 213 | name = {FV,MV,SV,CV}.{MEAS,MODEL,NEWVAL} \n \n \ 214 | Valid name combinations \n \ 215 | {FV,MV,CV}.MEAS \n \ 216 | {SV,CV}.MODEL \n \ 217 | {FV,MV}.NEWVAL ''' 218 | # Web-server URL address 219 | url_base = string.strip(server) + '/online/get_tag.php' 220 | params = urllib.urlencode({'p':app,'n':name}) 221 | f = urllib.urlopen(url_base,params) 222 | # Send request to web-server 223 | value = eval(f.read()) 224 | return value 225 | 226 | def apm_meas(server,app,name,value): 227 | '''Transfer measurement to server for FV, MV, or CV \n \ 228 | server = address of server \n \ 229 | app = application name \n \ 230 | name = name of {FV,MV,CV} ''' 231 | # Web-server URL address 232 | url_base = string.strip(server) + '/online/meas.php' 233 | params = urllib.urlencode({'p':app,'n':name+'.MEAS','v':value}) 234 | f = urllib.urlopen(url_base,params) 235 | # Send request to web-server 236 | response = f.read() 237 | return response 238 | -------------------------------------------------------------------------------- /demo/demo.apm: -------------------------------------------------------------------------------- 1 | Model 2 | Parameters 3 | tau = 5 4 | K = 3 5 | u 6 | End Parameters 7 | 8 | Variables 9 | x = 0 10 | y = 0 11 | End Variables 12 | 13 | Equations 14 | tau * $x + x = K * u 15 | y = 2 * x 16 | End Equations 17 | End Model 18 | -------------------------------------------------------------------------------- /demo/demo.csv: -------------------------------------------------------------------------------- 1 | time, u 2 | 0, 0 3 | 0.5, 0 4 | 1, 1 5 | 2, 1 6 | 3, 1 7 | 5, 1 8 | 8, 1 9 | 12, 1 10 | 15, 1 11 | 18, 1 12 | 21, 1 13 | 22, 1 14 | 25, 1 15 | 28, 1 16 | 30, 1 17 | -------------------------------------------------------------------------------- /demo/main.m: -------------------------------------------------------------------------------- 1 | % Clear local variables and plots 2 | clc; clear all; close all 3 | 4 | % Add APM libraries to path for session 5 | addpath('../apm'); 6 | 7 | % Integrate model and return solution 8 | y = apm_solve('demo'); 9 | 10 | % Retrieve the results 11 | z = y.x; 12 | 13 | % Plot results 14 | figure(1) 15 | plot(z.time,z.x,'r-') 16 | hold on 17 | plot(z.time,z.y,'b--') 18 | legend('x','y') 19 | -------------------------------------------------------------------------------- /demo/main.py: -------------------------------------------------------------------------------- 1 | # load apm library 2 | from apm import * 3 | 4 | # specify s=server and a=application names 5 | s = 'http://xps.apmonitor.com' 6 | a = 'demo' 7 | 8 | # clear previous applicaiton by that name 9 | apm(s,a,'clear all') 10 | 11 | # load model and data files 12 | apm_load(s,a,'demo.apm') 13 | csv_load(s,a,'demo.csv') 14 | 15 | # change to dynamic simulation 16 | apm_option(s,a,'nlc.imode',7) 17 | 18 | # Solve model and return solution 19 | output = apm(s,a,'solve') 20 | print output 21 | 22 | # Plot results 23 | import matplotlib 24 | import matplotlib.pyplot as plt 25 | 26 | # retrieve solution 27 | (sol,ans) = apm_sol(s,a) 28 | 29 | # plot results 30 | plt.figure() 31 | plt.plot(ans['time'],ans['x'],'r-') 32 | plt.plot(ans['time'],ans['y'],'b--') 33 | plt.legend(['x','y']) 34 | plt.show() 35 | -------------------------------------------------------------------------------- /example_4tank/4tank.apm: -------------------------------------------------------------------------------- 1 | ! Four tank process 2 | ! K-H.Johansson: The Quadruple-Tank Process: 3 | ! A Multivariable Process with an Adjustable Zero, 4 | ! IEEE Transaction on control systems technology, 2000 5 | ! http://ieeexplore.ieee.org/xpl/freeabs_all.jsp?arnumber=845876 6 | ! http://www.s3.kth.se/~kallej/papers/quadtank_ieeecst00.pdf 7 | 8 | ! Further detail are given here: 9 | ! http://www.s3.kth.se/~kallej/grad_students/drca_thesis07.pdf 10 | 11 | Model 12 | Constants 13 | ! gravitational constant (cm/s^2) 14 | g = 981 15 | 16 | ! tank cross-sectional area (cm^2) 17 | Area[1] = 28 18 | Area[2] = 32 19 | Area[3] = 28 20 | Area[4] = 32 21 | 22 | ! cross section of the outlet hole (cm^2) 23 | !a[1] = 0.071 ! - 0.0650 ! - correction factor to match real data 24 | !a[2] = 0.057 ! - 0.0520 ! - correction factor to match real data 25 | !a[3] = 0.071 ! - 0.0650 ! - correction factor to match real data 26 | !a[4] = 0.057 ! - 0.0520 ! - correction factor to match real data 27 | 28 | ! relation of level to voltage measurement (V/cm) 29 | kc = 0.50 30 | End Constants 31 | 32 | Parameters 33 | ! relation of input voltage to pump flow rate (cm^3/sec / V) 34 | km = 10.0, >=3.0, <=20.0 ! slope 35 | kb = 0.0, >=-20.0, <=20.0 ! intercept 36 | 37 | ! correction factors to fit model to real data 38 | c13 = 0.071, >0.01, <=0.2 ! outlet flow corrections 39 | c24 = 0.057, >0.01, <=0.2 ! outlet flow corrections 40 | 41 | ! fractional split to tank 1 vs. tank 4 42 | gamma[1] = 0.43, >=0, <=1 43 | 44 | ! fractional split to tank 2 vs. tank 3 45 | gamma[2] = 0.34, >=0, <=1 46 | 47 | ! voltage to pump A 48 | v1 = 3, >=0, <=10 ! Volt 49 | 50 | ! voltage to pump B 51 | v2 = 3, >=0, <=10 ! Volt 52 | End Parameters 53 | 54 | Variables 55 | ! tank height - diameter = 6 cm, max height = 20 cm 56 | h[1] = 12.6, >=1e-5 57 | h[2] = 13.0, >=1e-5 58 | h[3] = 4.8 , >=1e-5 59 | h[4] = 4.9 , >=1e-5 60 | End Variables 61 | 62 | Intermediates 63 | ! correction factors 64 | c[1] = c13 65 | c[2] = c24 66 | c[3] = c13 67 | c[4] = c24 68 | 69 | ! pump flows 70 | qa = v1 * km + kb 71 | qb = v2 * km + kb 72 | 73 | ! inlet flows from pumps 74 | q[1] = gamma[1] * qa 75 | q[2] = gamma[2] * qb 76 | q[3] = (1-gamma[2]) * qb 77 | q[4] = (1-gamma[1]) * qa 78 | 79 | ! outlet flows 80 | out[1:4] = c[1:4] * sqrt(2*g*h[1:4]) 81 | 82 | ! total inlet flows 83 | in[1] = q[1] + out[3] 84 | in[2] = q[2] + out[4] 85 | in[3] = q[3] 86 | in[4] = q[4] 87 | End Intermediates 88 | 89 | Equations 90 | Area[1:4] * $h[1:4] = in[1:4] - out[1:4] 91 | End Equations 92 | End Model 93 | 94 | File *.plt 95 | New Trend 96 | v1 97 | v2 98 | New Trend 99 | v1 100 | v2 101 | h[1] 102 | h[2] 103 | End File -------------------------------------------------------------------------------- /example_4tank/4tank_nlc.apm: -------------------------------------------------------------------------------- 1 | ! Four tank process 2 | ! K-H.Johansson: The Quadruple-Tank Process: 3 | ! A Multivariable Process with an Adjustable Zero, 4 | ! IEEE Transaction on control systems technology, 2000 5 | ! http://ieeexplore.ieee.org/xpl/freeabs_all.jsp?arnumber=845876 6 | ! http://www.s3.kth.se/~kallej/papers/quadtank_ieeecst00.pdf 7 | 8 | ! Further detail are given here: 9 | ! http://www.s3.kth.se/~kallej/grad_students/drca_thesis07.pdf 10 | 11 | Model 12 | Constants 13 | ! gravitational constant (cm/s^2) 14 | g = 981 15 | 16 | ! tank cross-sectional area (cm^2) 17 | Area[1] = 28 18 | Area[2] = 32 19 | Area[3] = 28 20 | Area[4] = 32 21 | 22 | ! cross section of the outlet hole (cm^2) 23 | !a[1] = 0.071 ! - 0.0650 ! - correction factor to match real data 24 | !a[2] = 0.057 ! - 0.0520 ! - correction factor to match real data 25 | !a[3] = 0.071 ! - 0.0650 ! - correction factor to match real data 26 | !a[4] = 0.057 ! - 0.0520 ! - correction factor to match real data 27 | 28 | ! relation of level to voltage measurement (V/cm) 29 | kc = 0.50 30 | End Constants 31 | 32 | Parameters 33 | ! relation of input voltage to pump flow rate (cm^3/sec / V) 34 | km = 3.44407, >=3.0, <=20.0 ! slope 35 | kb = -0.809711, >=-20.0, <=20.0 ! intercept 36 | 37 | ! correction factors to fit model to real data 38 | c13 = 0.063045, >0.01, <=0.2 ! outlet flow corrections 39 | c24 = 0.058218, >0.01, <=0.2 ! outlet flow corrections 40 | 41 | ! fractional split to tank 1 vs. tank 4 42 | gamma[1] = 0.584603, >=0, <=1 43 | 44 | ! fractional split to tank 2 vs. tank 3 45 | gamma[2] = 0.548129, >=0, <=1 46 | 47 | ! voltage to pump A 48 | v1 = 3, >=0, <=10 ! Volt 49 | 50 | ! voltage to pump B 51 | v2 = 3, >=0, <=10 ! Volt 52 | End Parameters 53 | 54 | Variables 55 | ! tank height - diameter = 6 cm, max height = 20 cm 56 | h[1] = 12.6, >=1e-5 57 | h[2] = 13.0, >=1e-5 58 | h[3] = 4.8 , >=1e-5 59 | h[4] = 4.9 , >=1e-5 60 | End Variables 61 | 62 | Intermediates 63 | ! correction factors 64 | c[1] = c13 65 | c[2] = c24 66 | c[3] = c13 67 | c[4] = c24 68 | 69 | ! pump flows 70 | qa = v1 * km + kb 71 | qb = v2 * km + kb 72 | 73 | ! inlet flows from pumps 74 | q[1] = gamma[1] * qa 75 | q[2] = gamma[2] * qb 76 | q[3] = (1-gamma[2]) * qb 77 | q[4] = (1-gamma[1]) * qa 78 | 79 | ! outlet flows 80 | out[1:4] = c[1:4] * sqrt(2*g*h[1:4]) 81 | 82 | ! total inlet flows 83 | in[1] = q[1] + out[3] 84 | in[2] = q[2] + out[4] 85 | in[3] = q[3] 86 | in[4] = q[4] 87 | End Intermediates 88 | 89 | Equations 90 | Area[1:4] * $h[1:4] = in[1:4] - out[1:4] 91 | End Equations 92 | End Model 93 | 94 | File *.plt 95 | New Trend 96 | v1 97 | v2 98 | New Trend 99 | v1 100 | v2 101 | h[1] 102 | h[2] 103 | End File -------------------------------------------------------------------------------- /example_4tank/control.csv: -------------------------------------------------------------------------------- 1 | time 2 | 0 3 | 1 4 | 2 5 | 5 6 | 8 7 | 12 8 | 18 9 | 25 10 | 35 11 | 45 12 | 60 13 | 75 14 | 90 15 | 105 16 | 120 17 | -------------------------------------------------------------------------------- /example_4tank/control.m: -------------------------------------------------------------------------------- 1 | % Add path to APM libraries 2 | addpath('../apm'); 3 | 4 | % Clear MATLAB 5 | clear all 6 | close all 7 | 8 | % Select server 9 | server = 'http://byu.apmonitor.com'; 10 | 11 | % Application 12 | app = 'nlc'; 13 | 14 | % Clear previous application 15 | apm(server,app,'clear all'); 16 | 17 | % load model variables and equations 18 | apm_load(server,app,'4tank_nlc.apm'); 19 | 20 | % load data 21 | csv_load(server,app,'control.csv'); 22 | 23 | % Set up variable classifications for data flow 24 | 25 | % Feedforwards - measured process disturbances 26 | apm_info(server,app,'FV','gamma[1]'); 27 | apm_info(server,app,'FV','gamma[2]'); 28 | % Manipulated variables (for controller design) 29 | apm_info(server,app,'MV','v1'); 30 | apm_info(server,app,'MV','v2'); 31 | % State variables (for display only) 32 | apm_info(server,app,'SV','h[3]'); 33 | apm_info(server,app,'SV','h[4]'); 34 | % Controlled variables (for controller design) 35 | apm_info(server,app,'CV','h[1]'); 36 | apm_info(server,app,'CV','h[2]'); 37 | 38 | % solve here for steady state initialization 39 | % imode = 3, steady state mode 40 | apm_option(server,app,'nlc.imode',3); 41 | apm(server,app,'solve') 42 | 43 | % imode = 6, switch to dynamic control 44 | apm_option(server,app,'nlc.imode',6); 45 | % nodes = 3, internal nodes in the collocation structure (2-6) 46 | apm_option(server,app,'nlc.nodes',3); 47 | % time units 48 | apm_option(server,app,'nlc.ctrl_units',1); 49 | apm_option(server,app,'nlc.hist_units',2); 50 | % read csv file 51 | apm_option(server,app,'nlc.csv_read',1); 52 | 53 | % Manipulated variables 54 | apm_option(server,app,'v1.status',1); 55 | apm_option(server,app,'v1.upper',6); 56 | apm_option(server,app,'v1.lower',1); 57 | apm_option(server,app,'v1.dmax',1); 58 | apm_option(server,app,'v1.dcost',1); 59 | 60 | apm_option(server,app,'v2.status',1); 61 | apm_option(server,app,'v2.upper',6); 62 | apm_option(server,app,'v2.lower',1); 63 | apm_option(server,app,'v2.dmax',1); 64 | apm_option(server,app,'v2.dcost',1); 65 | 66 | % Controlled variables 67 | apm_option(server,app,'h[1].status',1); 68 | apm_option(server,app,'h[1].fstatus',0); 69 | apm_option(server,app,'h[1].sphi',10.1); 70 | apm_option(server,app,'h[1].splo',9.9); 71 | apm_option(server,app,'h[1].tau',10); 72 | 73 | apm_option(server,app,'h[2].status',1); 74 | apm_option(server,app,'h[2].fstatus',0); 75 | apm_option(server,app,'h[2].sphi',15.1); 76 | apm_option(server,app,'h[2].splo',14.9); 77 | apm_option(server,app,'h[2].tau',10); 78 | 79 | % Set controller mode 80 | apm_option(server,app,'nlc.reqctrlmode',3); 81 | 82 | % Run APMonitor 83 | apm(server,app,'solve') 84 | 85 | % Open web-viewer 86 | apm_web(server,app); 87 | 88 | % Retrieve solution (creates solution.csv locally) 89 | solution = apm_sol(server,app); 90 | cc = cell2mat(solution(2:end,:)); 91 | time = cc(:,1); 92 | v1 = cc(:,8); 93 | v2 = cc(:,9); 94 | h(:,1:4) = cc(:,10:13); 95 | 96 | figure(1) 97 | subplot(3,2,1) 98 | plot(time,v1,'b-'); 99 | ylabel('Pump Input (V)') 100 | legend('v_1'); 101 | 102 | subplot(3,2,2) 103 | plot(time,v2,'b-'); 104 | ylabel('Pump Input (V)') 105 | legend('v_2'); 106 | 107 | subplot(3,2,3) 108 | plot(time,h(:,3),'b-'); 109 | ylabel('Height (cm)') 110 | legend('h_3'); 111 | 112 | subplot(3,2,4) 113 | plot(time,h(:,4),'b-'); 114 | ylabel('Height (cm)') 115 | legend('h_4'); 116 | 117 | subplot(3,2,5) 118 | plot(time,h(:,1),'b-'); 119 | ylabel('Height (cm)') 120 | legend('h_1'); 121 | xlabel('Time (sec)') 122 | 123 | subplot(3,2,6) 124 | plot(time,h(:,2),'b-'); 125 | ylabel('Height (cm)') 126 | legend('h_2'); 127 | xlabel('Time (sec)') 128 | -------------------------------------------------------------------------------- /example_4tank/control_h[1].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/APMonitor/apm_matlab/ee47918ca71412ddf2f074b20b62eb693f1fcb6f/example_4tank/control_h[1].png -------------------------------------------------------------------------------- /example_4tank/control_h[2].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/APMonitor/apm_matlab/ee47918ca71412ddf2f074b20b62eb693f1fcb6f/example_4tank/control_h[2].png -------------------------------------------------------------------------------- /example_4tank/prbs.m: -------------------------------------------------------------------------------- 1 | % Add path to APM libraries 2 | addpath('../apm'); 3 | 4 | % Clear MATLAB 5 | clear all 6 | close all 7 | 8 | % Select server 9 | server = 'http://byu.apmonitor.com'; 10 | 11 | % Application 12 | app = 'prbs'; 13 | 14 | % Clear previous application 15 | apm(server,app,'clear all'); 16 | 17 | % load model variables and equations 18 | disp('Loading APM model file') 19 | apm_load(server,app,'4tank.apm'); 20 | 21 | % choose a data set for parameter estimation with PRBS signal data 22 | disp('Loading CSV data file') 23 | 24 | % load 10 second data - with 1 hour horizon 25 | csv_load(server,app,'prbs50.csv'); 26 | load prbs10.txt 27 | data = prbs10; 28 | 29 | % Set up variable classifications for data flow 30 | 31 | % Feedforwards - measured process disturbances 32 | apm_info(server,app,'FV','km'); 33 | apm_info(server,app,'FV','kb'); 34 | apm_info(server,app,'FV','gamma[1]'); 35 | apm_info(server,app,'FV','gamma[2]'); 36 | apm_info(server,app,'FV','c13'); 37 | apm_info(server,app,'FV','c24'); 38 | % Manipulated variables (for controller design) 39 | %apm_info(server,app,'MV','v1'); 40 | %apm_info(server,app,'MV','v2'); 41 | % State variables (for display only) 42 | apm_info(server,app,'SV','h[3]'); 43 | apm_info(server,app,'SV','h[4]'); 44 | % Controlled variables (for controller design) 45 | apm_info(server,app,'CV','h[1]'); 46 | apm_info(server,app,'CV','h[2]'); 47 | 48 | % imode (1=ss, 2=mpu, 3=rto, 4=sim, 5=est, 6=ctl) 49 | apm_option(server,app,'nlc.imode',5); 50 | % nodes = 3, internal nodes in the collocation structure (2-6) 51 | apm_option(server,app,'nlc.nodes',3); 52 | % simulation step size for every 'solve' command 53 | apm_option(server,app,'nlc.ctrl_time',0.25); 54 | % read csv file 55 | apm_option(server,app,'nlc.csv_read',1); 56 | % estimated variable error type 57 | apm_option(server,app,'nlc.ev_type',2); 58 | % time units (1=sec, 2=min, 3=hrs, 4=days, etc) 59 | apm_option(server,app,'nlc.ctrl_units',1); 60 | apm_option(server,app,'nlc.hist_units',2); 61 | 62 | % parameters to adjust 63 | apm_option(server,app,'km.status',1); 64 | apm_option(server,app,'km.lower',3); 65 | apm_option(server,app,'km.upper',20); 66 | 67 | apm_option(server,app,'kb.status',1); 68 | apm_option(server,app,'kb.lower',-2); 69 | apm_option(server,app,'kb.upper',2); 70 | 71 | apm_option(server,app,'gamma[1].status',1); 72 | apm_option(server,app,'gamma[1].lower',0.2); 73 | apm_option(server,app,'gamma[1].upper',0.8); 74 | 75 | apm_option(server,app,'gamma[2].status',1); 76 | apm_option(server,app,'gamma[2].lower',0.2); 77 | apm_option(server,app,'gamma[2].upper',0.8); 78 | 79 | apm_option(server,app,'c13.status',1); 80 | apm_option(server,app,'c13.lower',0.01); 81 | apm_option(server,app,'c13.upper',0.2); 82 | 83 | apm_option(server,app,'c24.status',1); 84 | apm_option(server,app,'c24.lower',0.01); 85 | apm_option(server,app,'c24.upper',0.2); 86 | 87 | % data to fit 88 | apm_option(server,app,'h[1].fstatus',1); 89 | apm_option(server,app,'h[2].fstatus',1); 90 | 91 | % solver 92 | apm_option(server,app,'nlc.solver',3); 93 | 94 | % Run APMonitor 95 | apm(server,app,'solve') 96 | 97 | % Open web-viewer 98 | apm_web(server,app); 99 | 100 | % Retrieve solution (creates solution.csv locally) 101 | y = apm_sol(server,app); 102 | cc = y.values; 103 | time = cc(:,1); 104 | v1 = cc(:,8); 105 | v2 = cc(:,9); 106 | h(:,1:4) = cc(:,10:13); 107 | 108 | m = size(time,1); 109 | hm(:,1:2) = data(1:m,4:5); 110 | 111 | figure(1) 112 | subplot(3,2,1) 113 | plot(time,v1,'b-'); 114 | ylabel('Pump Input (Volt)') 115 | legend('v_1'); 116 | 117 | subplot(3,2,2) 118 | plot(time,v2,'b-'); 119 | ylabel('Pump Input (Volt)') 120 | legend('v_2'); 121 | 122 | subplot(3,2,3) 123 | plot(time,h(:,3),'b-'); 124 | ylabel('Height (cm)') 125 | legend('h_3'); 126 | 127 | subplot(3,2,4) 128 | plot(time,h(:,4),'b-'); 129 | ylabel('Height (cm)') 130 | legend('h_4'); 131 | 132 | subplot(3,2,5) 133 | plot(time,h(:,1),'b-'); 134 | hold on; 135 | plot(time,hm(:,1),'r.'); 136 | ylabel('Height (cm)') 137 | legend('h_1 model','h_1 meas'); 138 | 139 | subplot(3,2,6) 140 | plot(time,h(:,2),'b-'); 141 | hold on; 142 | plot(time,hm(:,2),'r.'); 143 | ylabel('Height (cm)') 144 | legend('h_2 model','h_2 meas'); 145 | 146 | xlabel('Time (sec)') 147 | -------------------------------------------------------------------------------- /example_4tank/prbs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/APMonitor/apm_matlab/ee47918ca71412ddf2f074b20b62eb693f1fcb6f/example_4tank/prbs.png -------------------------------------------------------------------------------- /example_4tank/prbs50.csv: -------------------------------------------------------------------------------- 1 | time,v1,v2,h[1],h[2],h[1].fstatus,h[2].fstatus 2 | 0.0000E+00,3.0000E+00,3.0000E+00,1.2460E+01,1.2730E+01,1.0000E+00,1.0000E+00 3 | 4.5000E+00,3.0000E+00,3.0000E+00,1.2460E+01,1.2730E+01,1.0000E+00,1.0000E+00 4 | 1.4500E+01,3.0000E+00,3.0000E+00,1.2450E+01,1.2760E+01,1.0000E+00,1.0000E+00 5 | 2.4500E+01,3.2400E+00,2.7600E+00,1.2520E+01,1.2690E+01,1.0000E+00,1.0000E+00 6 | 3.4500E+01,3.3000E+00,2.7000E+00,1.2670E+01,1.2540E+01,1.0000E+00,1.0000E+00 7 | 4.4500E+01,3.3000E+00,2.7000E+00,1.2790E+01,1.2370E+01,1.0000E+00,1.0000E+00 8 | 5.4500E+01,3.3000E+00,2.7000E+00,1.2840E+01,1.2260E+01,1.0000E+00,1.0000E+00 9 | 6.4500E+01,3.3000E+00,2.7000E+00,1.2900E+01,1.2190E+01,1.0000E+00,1.0000E+00 10 | 7.4500E+01,3.3000E+00,2.7000E+00,1.2930E+01,1.2100E+01,1.0000E+00,1.0000E+00 11 | 8.4500E+01,3.3000E+00,3.1800E+00,1.3000E+01,1.2060E+01,1.0000E+00,1.0000E+00 12 | 9.4500E+01,3.3000E+00,3.3000E+00,1.3040E+01,1.2390E+01,1.0000E+00,1.0000E+00 13 | 1.0450E+02,3.3000E+00,3.3000E+00,1.3160E+01,1.2690E+01,1.0000E+00,1.0000E+00 14 | 1.1450E+02,3.3000E+00,3.3000E+00,1.3260E+01,1.2970E+01,1.0000E+00,1.0000E+00 15 | 1.2450E+02,3.3000E+00,3.3000E+00,1.3380E+01,1.3190E+01,1.0000E+00,1.0000E+00 16 | 1.3450E+02,3.3000E+00,3.3000E+00,1.3550E+01,1.3390E+01,1.0000E+00,1.0000E+00 17 | 1.4450E+02,2.8200E+00,2.8200E+00,1.3640E+01,1.3680E+01,1.0000E+00,1.0000E+00 18 | 1.5450E+02,2.7000E+00,2.7000E+00,1.3500E+01,1.3550E+01,1.0000E+00,1.0000E+00 19 | 1.6450E+02,2.7000E+00,2.7000E+00,1.3230E+01,1.3280E+01,1.0000E+00,1.0000E+00 20 | 1.7450E+02,2.7000E+00,2.7000E+00,1.2880E+01,1.3000E+01,1.0000E+00,1.0000E+00 21 | 1.8450E+02,2.7000E+00,2.7000E+00,1.2530E+01,1.2740E+01,1.0000E+00,1.0000E+00 22 | 1.9450E+02,2.7000E+00,2.7000E+00,1.2210E+01,1.2430E+01,1.0000E+00,1.0000E+00 23 | 2.0450E+02,3.1800E+00,3.1800E+00,1.2020E+01,1.2250E+01,1.0000E+00,1.0000E+00 24 | 2.1450E+02,3.3000E+00,3.3000E+00,1.2170E+01,1.2410E+01,1.0000E+00,1.0000E+00 25 | 2.2450E+02,3.3000E+00,3.3000E+00,1.2430E+01,1.2660E+01,1.0000E+00,1.0000E+00 26 | 2.3450E+02,3.3000E+00,3.3000E+00,1.2710E+01,1.2860E+01,1.0000E+00,1.0000E+00 27 | 2.4450E+02,3.3000E+00,3.3000E+00,1.2950E+01,1.3130E+01,1.0000E+00,1.0000E+00 28 | 2.5450E+02,3.3000E+00,3.3000E+00,1.3180E+01,1.3250E+01,1.0000E+00,1.0000E+00 29 | 2.6450E+02,3.3000E+00,2.8200E+00,1.3340E+01,1.3350E+01,1.0000E+00,1.0000E+00 30 | 2.7450E+02,3.3000E+00,2.7000E+00,1.3480E+01,1.3330E+01,1.0000E+00,1.0000E+00 31 | 2.8450E+02,3.3000E+00,2.7000E+00,1.3560E+01,1.3180E+01,1.0000E+00,1.0000E+00 32 | 2.9450E+02,3.3000E+00,2.7000E+00,1.3560E+01,1.3010E+01,1.0000E+00,1.0000E+00 33 | 3.0450E+02,3.3000E+00,2.7000E+00,1.3580E+01,1.2870E+01,1.0000E+00,1.0000E+00 34 | 3.1450E+02,3.3000E+00,2.7000E+00,1.3620E+01,1.2750E+01,1.0000E+00,1.0000E+00 35 | 3.2450E+02,2.8200E+00,3.1800E+00,1.3510E+01,1.2670E+01,1.0000E+00,1.0000E+00 36 | 3.3450E+02,2.7000E+00,3.3000E+00,1.3200E+01,1.2850E+01,1.0000E+00,1.0000E+00 37 | 3.4450E+02,2.7000E+00,3.3000E+00,1.2940E+01,1.3060E+01,1.0000E+00,1.0000E+00 38 | 3.5450E+02,2.7000E+00,3.3000E+00,1.2680E+01,1.3170E+01,1.0000E+00,1.0000E+00 39 | 3.6450E+02,2.7000E+00,3.3000E+00,1.2520E+01,1.3240E+01,1.0000E+00,1.0000E+00 40 | 3.7450E+02,2.7000E+00,3.3000E+00,1.2390E+01,1.3270E+01,1.0000E+00,1.0000E+00 41 | 3.8450E+02,3.1800E+00,3.3000E+00,1.2370E+01,1.3370E+01,1.0000E+00,1.0000E+00 42 | 3.9450E+02,3.3000E+00,3.3000E+00,1.2700E+01,1.3430E+01,1.0000E+00,1.0000E+00 43 | 4.0450E+02,3.3000E+00,3.3000E+00,1.2990E+01,1.3660E+01,1.0000E+00,1.0000E+00 44 | 4.1450E+02,3.3000E+00,3.3000E+00,1.3240E+01,1.3800E+01,1.0000E+00,1.0000E+00 45 | 4.2450E+02,3.3000E+00,3.3000E+00,1.3470E+01,1.3900E+01,1.0000E+00,1.0000E+00 46 | 4.3450E+02,3.3000E+00,3.3000E+00,1.3610E+01,1.4020E+01,1.0000E+00,1.0000E+00 47 | 4.4450E+02,3.3000E+00,3.3000E+00,1.3810E+01,1.4120E+01,1.0000E+00,1.0000E+00 48 | 4.5450E+02,3.3000E+00,3.3000E+00,1.3950E+01,1.4230E+01,1.0000E+00,1.0000E+00 49 | 4.6450E+02,3.3000E+00,3.3000E+00,1.4080E+01,1.4330E+01,1.0000E+00,1.0000E+00 50 | 4.7450E+02,3.3000E+00,3.3000E+00,1.4170E+01,1.4440E+01,1.0000E+00,1.0000E+00 51 | 4.8450E+02,3.3000E+00,3.3000E+00,1.4300E+01,1.4550E+01,1.0000E+00,1.0000E+00 52 | 4.9450E+02,3.3000E+00,3.3000E+00,1.4450E+01,1.4650E+01,1.0000E+00,1.0000E+00 53 | 5.0450E+02,2.8200E+00,2.8200E+00,1.4540E+01,1.4730E+01,1.0000E+00,1.0000E+00 54 | -------------------------------------------------------------------------------- /example_4tank/solution_step.csv: -------------------------------------------------------------------------------- 1 | time, 0.00 , 1.000000E+01, 2.000000E+01, 3.000000E+01, 4.000000E+01, 5.000000E+01, 6.000000E+01, 7.000000E+01, 8.000000E+01, 9.000000E+01, 1.000000E+02, 1.100000E+02, 1.200000E+02, 1.300000E+02, 1.400000E+02, 1.500000E+02, 1.600000E+02, 1.700000E+02, 1.800000E+02, 1.900000E+02, 2.000000E+02, 2.100000E+02, 2.200000E+02, 2.300000E+02, 2.400000E+02, 2.500000E+02, 2.600000E+02, 2.700000E+02, 2.800000E+02, 2.900000E+02, 3.000000E+02 2 | km, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00, 3.444070E+00 3 | kb, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01, -8.097110E-01 4 | c13, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02, 6.304500E-02 5 | c24, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02, 5.821800E-02 6 | gamma[1], 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01, 5.846030E-01 7 | gamma[2], 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01, 5.481290E-01 8 | v1, 3.000000E+00, 3.000000E+00, 3.000000E+00, 3.000000E+00, 3.000000E+00, 3.500000E+00, 3.500000E+00, 3.500000E+00, 3.500000E+00, 3.500000E+00, 3.500000E+00, 3.500000E+00, 3.500000E+00, 3.500000E+00, 3.500000E+00, 3.500000E+00, 3.500000E+00, 3.500000E+00, 3.500000E+00, 3.500000E+00, 3.500000E+00, 3.500000E+00, 3.500000E+00, 3.500000E+00, 3.500000E+00, 3.500000E+00, 3.500000E+00, 3.500000E+00, 3.500000E+00, 3.500000E+00, 3.500000E+00 9 | v2, 3.000000E+00, 3.000000E+00, 3.000000E+00, 3.000000E+00, 3.000000E+00, 3.000000E+00, 3.000000E+00, 3.000000E+00, 3.000000E+00, 3.000000E+00, 3.000000E+00, 2.500000E+00, 2.500000E+00, 2.500000E+00, 2.500000E+00, 2.500000E+00, 2.500000E+00, 2.500000E+00, 2.500000E+00, 2.500000E+00, 2.500000E+00, 2.500000E+00, 2.500000E+00, 2.500000E+00, 2.500000E+00, 2.500000E+00, 2.500000E+00, 2.500000E+00, 2.500000E+00, 2.500000E+00, 2.500000E+00 10 | h[1], 1.249161E+01, 1.249161E+01, 1.249161E+01, 1.249161E+01, 1.249161E+01, 1.266487E+01, 1.297748E+01, 1.324971E+01, 1.348710E+01, 1.369437E+01, 1.387553E+01, 1.402206E+01, 1.408829E+01, 1.409170E+01, 1.405495E+01, 1.399444E+01, 1.392159E+01, 1.384404E+01, 1.376672E+01, 1.369263E+01, 1.362344E+01, 1.355999E+01, 1.350254E+01, 1.345100E+01, 1.340507E+01, 1.336436E+01, 1.332841E+01, 1.329676E+01, 1.326896E+01, 1.324459E+01, 1.322324E+01 11 | h[2], 1.265946E+01, 1.265946E+01, 1.265946E+01, 1.265946E+01, 1.265946E+01, 1.266715E+01, 1.271450E+01, 1.279261E+01, 1.288974E+01, 1.299769E+01, 1.311069E+01, 1.308140E+01, 1.292964E+01, 1.280197E+01, 1.269426E+01, 1.260310E+01, 1.252574E+01, 1.245989E+01, 1.240369E+01, 1.235560E+01, 1.231435E+01, 1.227886E+01, 1.224826E+01, 1.222183E+01, 1.219893E+01, 1.217905E+01, 1.216177E+01, 1.214672E+01, 1.213358E+01, 1.212209E+01, 1.211203E+01 12 | h[3], 2.374272E+00, 2.374272E+00, 2.374272E+00, 2.374272E+00, 2.374272E+00, 2.374272E+00, 2.374272E+00, 2.374272E+00, 2.374272E+00, 2.374272E+00, 2.374272E+00, 2.247118E+00, 2.047251E+00, 1.905990E+00, 1.807395E+00, 1.739238E+00, 1.692457E+00, 1.660513E+00, 1.638779E+00, 1.624030E+00, 1.614039E+00, 1.607278E+00, 1.602707E+00, 1.599619E+00, 1.597532E+00, 1.596124E+00, 1.595173E+00, 1.594530E+00, 1.594097E+00, 1.593804E+00, 1.593607E+00 13 | h[4], 2.352963E+00, 2.352963E+00, 2.352963E+00, 2.352963E+00, 2.352963E+00, 2.457135E+00, 2.630262E+00, 2.765363E+00, 2.871440E+00, 2.955104E+00, 3.021315E+00, 3.073849E+00, 3.115613E+00, 3.148867E+00, 3.175377E+00, 3.196531E+00, 3.213423E+00, 3.226919E+00, 3.237709E+00, 3.246337E+00, 3.253238E+00, 3.258761E+00, 3.263180E+00, 3.266717E+00, 3.269548E+00, 3.271815E+00, 3.273630E+00, 3.275083E+00, 3.276246E+00, 3.277178E+00, 3.277924E+00 14 | -------------------------------------------------------------------------------- /example_4tank/step.csv: -------------------------------------------------------------------------------- 1 | time,v1,v2 2 | 0,3,3 3 | 10,3,3 4 | 20,3,3 5 | 30,3,3 6 | 40,3,3 7 | 50,3.5,3 8 | 60,3.5,3 9 | 70,3.5,3 10 | 80,3.5,3 11 | 90,3.5,3 12 | 100,3.5,3 13 | 110,3.5,2.5 14 | 120,3.5,2.5 15 | 130,3.5,2.5 16 | 140,3.5,2.5 17 | 150,3.5,2.5 18 | 160,3.5,2.5 19 | 170,3.5,2.5 20 | 180,3.5,2.5 21 | 190,3.5,2.5 22 | 200,3.5,2.5 23 | 210,3.5,2.5 24 | 220,3.5,2.5 25 | 230,3.5,2.5 26 | 240,3.5,2.5 27 | 250,3.5,2.5 28 | 260,3.5,2.5 29 | 270,3.5,2.5 30 | 280,3.5,2.5 31 | 290,3.5,2.5 32 | 300,3.5,2.5 33 | -------------------------------------------------------------------------------- /example_4tank/step.m: -------------------------------------------------------------------------------- 1 | % Add path to APM libraries 2 | addpath('../apm'); 3 | 4 | % Clear MATLAB 5 | clear all 6 | close all 7 | 8 | % Select server 9 | server = 'http://byu.apmonitor.com'; 10 | 11 | % Application 12 | app = 'step'; 13 | 14 | % Clear previous application 15 | apm(server,app,'clear all'); 16 | 17 | % load model variables and equations 18 | apm_load(server,app,'4tank_nlc.apm'); 19 | 20 | % load data 21 | csv_load(server,app,'step.csv'); 22 | 23 | % Set up variable classifications for data flow 24 | 25 | % Feedforwards - measured process disturbances 26 | apm_info(server,app,'FV','gamma[1]'); 27 | apm_info(server,app,'FV','gamma[2]'); 28 | % Manipulated variables (for controller design) 29 | apm_info(server,app,'MV','v1'); 30 | apm_info(server,app,'MV','v2'); 31 | % State variables (for display only) 32 | apm_info(server,app,'SV','h[3]'); 33 | apm_info(server,app,'SV','h[4]'); 34 | % Controlled variables (for controller design) 35 | apm_info(server,app,'CV','h[1]'); 36 | apm_info(server,app,'CV','h[2]'); 37 | 38 | % imode = 1, steady state mode 39 | apm_option(server,app,'nlc.imode',1); 40 | % solve here for steady state initialization 41 | apm(server,app,'solve') 42 | 43 | % imode = 4, switch to dynamic simulation 44 | apm_option(server,app,'nlc.imode',4); 45 | % nodes = 3, internal nodes in the collocation structure (2-6) 46 | apm_option(server,app,'nlc.nodes',3); 47 | % time units 48 | apm_option(server,app,'nlc.ctrl_units',1); 49 | apm_option(server,app,'nlc.hist_units',2); 50 | % read csv file 51 | apm_option(server,app,'nlc.csv_read',1); 52 | 53 | % Run APMonitor 54 | apm(server,app,'solve') 55 | 56 | % Open web-viewer 57 | apm_web(server,app); 58 | 59 | % Retrieve solution (creates solution.csv locally) 60 | solution = apm_sol(server,app); 61 | cc = cell2mat(solution(2:end,:)); 62 | time = cc(:,1); 63 | v1 = cc(:,8); 64 | v2 = cc(:,9); 65 | h(:,1:4) = cc(:,10:13); 66 | 67 | figure(1) 68 | subplot(3,2,1) 69 | plot(time,v1,'b-'); 70 | ylabel('Pump Input (V)') 71 | legend('v_1'); 72 | 73 | subplot(3,2,2) 74 | plot(time,v2,'b-'); 75 | ylabel('Pump Input (V)') 76 | legend('v_2'); 77 | 78 | subplot(3,2,3) 79 | plot(time,h(:,3),'b-'); 80 | ylabel('Height (cm)') 81 | legend('h_3'); 82 | 83 | subplot(3,2,4) 84 | plot(time,h(:,4),'b-'); 85 | ylabel('Height (cm)') 86 | legend('h_4'); 87 | 88 | subplot(3,2,5) 89 | plot(time,h(:,1),'b-'); 90 | ylabel('Height (cm)') 91 | legend('h_1'); 92 | xlabel('Time (sec)') 93 | 94 | subplot(3,2,6) 95 | plot(time,h(:,2),'b-'); 96 | ylabel('Height (cm)') 97 | legend('h_2'); 98 | xlabel('Time (sec)') 99 | -------------------------------------------------------------------------------- /example_4tank/step.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/APMonitor/apm_matlab/ee47918ca71412ddf2f074b20b62eb693f1fcb6f/example_4tank/step.png -------------------------------------------------------------------------------- /example_cstr_seq/README.txt: -------------------------------------------------------------------------------- 1 | Run main.m from the MATLAB console to see the results. This script runs the APM web interface for a simple CSTR model and ODE15s, MATLAB's built in DAE integrator. You must have an internet connection to run this script. 2 | 3 | This folder implements a series of sequential solutions to solve the model in a forward-stepping method over the time horizon. -------------------------------------------------------------------------------- /example_cstr_seq/cstr.apm: -------------------------------------------------------------------------------- 1 | Model 2 | Parameters 3 | Tc = 270 ! Temperature of cooling jacket (K) 4 | q = 100 ! Volumetric Flowrate (m^3/sec) 5 | V = 100 ! Volume of CSTR (m^3) 6 | rho = 1000 ! Density of A-B Mixture (kg/m^3) 7 | Cp = .239 ! Heat capacity of A-B Mixture (J/kg-K) 8 | mdelH = 5e4 ! Heat of reaction for A->B (J/mol) 9 | EoverR = 8750 ! EoverR = E/R = Activation energy / R (8.31451 J/mol-K) 10 | k0 = 7.2e10 ! Pre-exponential factor (1/sec) 11 | UA = 5e4 ! Overall Heat Transfer Coefficient (W/m^2-K) 12 | Caf = 1 ! Feed Concentration (mol/m^3) 13 | Tf = 350 ! Feed Temperature (K) 14 | End Parameters 15 | Variables 16 | Ca = 0.989 ! Concentration of A in CSTR (mol/m^3) 17 | T = 296.6 ! Temperature in CSTR (K) 18 | End Variables 19 | Equations 20 | V * $Ca = q*(Caf-Ca) - k0*V*exp(-EoverR/T)*Ca ! mole balance for species A 21 | rho*Cp*V * $T = q*rho*Cp*(Tf - T) + V*mdelH*k0*exp(-EoverR/T)*Ca + UA*(Tc-T) ! energy balance 22 | End Equations 23 | End Model -------------------------------------------------------------------------------- /example_cstr_seq/cstr.csv: -------------------------------------------------------------------------------- 1 | time,Tc 2 | 0,270 3 | 0.25,270 4 | 0.26,220 5 | 0.5,220 6 | 0.75,220 7 | 1,220 8 | 1.25,220 9 | 1.5,220 10 | 1.75,220 11 | 2,220 12 | 2.25,220 13 | 2.5,220 14 | 2.75,220 15 | 3,220 16 | 3.25,220 17 | 3.5,220 18 | 3.75,220 19 | 4,220 20 | 4.25,220 21 | 4.5,220 22 | 4.75,220 23 | 5,220 24 | -------------------------------------------------------------------------------- /example_cstr_seq/cstr.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/APMonitor/apm_matlab/ee47918ca71412ddf2f074b20b62eb693f1fcb6f/example_cstr_seq/cstr.jpg -------------------------------------------------------------------------------- /example_cstr_seq/cstr1.m: -------------------------------------------------------------------------------- 1 | % This model is used for comparison with ode15s 2 | % It isn't used by the APM code 3 | 4 | % CSTR model from 5 | % 6 | % Michael A. Henson and Dale E. Seborg. Nonlinear Process Control. 7 | % Prentice Hall PTR, Upper Saddle River, New Jersey, 1997. 8 | 9 | % Description: 10 | % Continuously Stirred Tank Reactor with energy balance and reaction A->B. 11 | % The temperature of the cooling jacket is the control. 12 | 13 | function xdot=cstr1(t,x) 14 | 15 | global u 16 | 17 | % Input (1): 18 | % Temperature of cooling jacket (K) 19 | Tc = u; 20 | 21 | % States (2): 22 | % Concentration of A in CSTR (mol/m^3) 23 | Ca = x(1,1); 24 | % Temperature in CSTR (K) 25 | T = x(2,1); 26 | 27 | % Parameters: 28 | % Volumetric Flowrate (m^3/sec) 29 | q = 100; 30 | % Volume of CSTR (m^3) 31 | V = 100; 32 | % Density of A-B Mixture (kg/m^3) 33 | rho = 1000; 34 | % Heat capacity of A-B Mixture (J/kg-K) 35 | Cp = .239; 36 | % Heat of reaction for A->B (J/mol) 37 | mdelH = 5e4; 38 | % E - Activation energy in the Arrhenius Equation (J/mol) 39 | % R - Universal Gas Constant = 8.31451 J/mol-K 40 | EoverR = 8750; 41 | % Pre-exponential factor (1/sec) 42 | k0 = 7.2e10; 43 | % U - Overall Heat Transfer Coefficient (W/m^2-K) 44 | % A - Area - this value is specific for the U calculation (m^2) 45 | UA = 5e4; 46 | % Feed Concentration (mol/m^3) 47 | Caf = 1; 48 | % Feed Temperature (K) 49 | Tf = 350; 50 | 51 | % Compute xdot: 52 | xdot(1,1) = (q/V*(Caf - Ca) - k0*exp(-EoverR/T)*Ca); 53 | xdot(2,1) = (q/V*(Tf - T) + mdelH/(rho*Cp)*k0*exp(-EoverR/T)*Ca + UA/V/rho/Cp*(Tc-T)); -------------------------------------------------------------------------------- /example_cstr_seq/main.m: -------------------------------------------------------------------------------- 1 | % Add path to APM libraries 2 | addpath('../apm'); 3 | 4 | % Clear MATLAB 5 | clear all 6 | close all 7 | 8 | % Select server 9 | server = 'http://byu.apmonitor.com'; 10 | 11 | % Application 12 | app = 'nlc'; 13 | 14 | % Clear previous application 15 | apm(server,app,'clear all'); 16 | 17 | % load model variables and equations 18 | apm_load(server,app,'cstr.apm'); 19 | 20 | % load data 21 | csv_load(server,app,'cstr.csv'); 22 | 23 | % Set up variable classifications for data flow 24 | 25 | % Feedforwards - measured process disturbances 26 | apm_info(server,app,'FV','Caf'); 27 | apm_info(server,app,'FV','Tf'); 28 | % Manipulated variables (for controller design) 29 | apm_info(server,app,'MV','tc'); 30 | % State variables (for display only) 31 | apm_info(server,app,'SV','Ca'); 32 | % Controlled variables (for controller design) 33 | apm_info(server,app,'CV','T'); 34 | 35 | % imode = 1, steady state mode 36 | apm_option(server,app,'nlc.imode',1); 37 | % solve here for steady state initialization 38 | apm(server,app,'solve') 39 | 40 | % imode = 7, switch to sequential simulation 41 | apm_option(server,app,'nlc.imode',7); 42 | % nodes = 3, internal nodes in the collocation structure (2-6) 43 | apm_option(server,app,'nlc.nodes',3); 44 | % simulation step size for every 'solve' command 45 | apm_option(server,app,'nlc.ctrl_time',0.25); 46 | % coldstart application 47 | apm_option(server,app,'nlc.coldstart',1); 48 | % read csv file 49 | apm_option(server,app,'nlc.csv_read',1); 50 | 51 | % Run APMonitor 52 | apm(server,app,'solve') 53 | 54 | % Retrieve solution (creates solution.csv locally) 55 | y = apm_sol(server,app); 56 | % Extract names 57 | names = y.names; 58 | % Extract values 59 | cc = y.values; 60 | 61 | % Time is always the first column or row 62 | time_apm = cc(:,1); 63 | 64 | % extract 'Ca' 65 | index = find(strcmpi('Ca',names)); 66 | Ca_apm = cc(:,index); 67 | 68 | % extract 'T' 69 | index = find(strcmpi('T',names)); 70 | T_apm = cc(:,index); 71 | 72 | % extract 'Tc' 73 | index = find(strcmpi('Tc',names)); 74 | Tc_apm = cc(:,index); 75 | 76 | % --------------------------------------------------------- 77 | % simulate with ode15s (for comparison) 78 | % Verify dynamic response of CSTR model 79 | 80 | global u 81 | 82 | % Steady State Initial Conditions for the States 83 | Ca_ss = 0.989; 84 | T_ss = 296.6; 85 | y_ss = [Ca_ss;T_ss]; 86 | 87 | % Open Loop Step Change 88 | u = 220; 89 | 90 | % Final Time (sec) 91 | tf = 5; 92 | 93 | [t_ode15s,y] = ode15s('cstr1',[0.25 tf],y_ss); 94 | 95 | % Parse out the state values 96 | Ca_ode15s = y(:,1); 97 | T_ode15s = y(:,2); 98 | % --------------------------------------------------------- 99 | 100 | 101 | figure(1) 102 | plot(time_apm,Ca_apm,'b-'); 103 | hold on; 104 | plot(t_ode15s,Ca_ode15s,'k--') 105 | xlabel('Time (min)') 106 | ylabel('Concentration') 107 | legend('APM','ODE15S'); 108 | 109 | figure(2) 110 | subplot(2,1,1); 111 | plot(time_apm,T_apm,'b-'); 112 | hold on; 113 | plot(t_ode15s,T_ode15s,'k--'); 114 | ylabel('Temp (K)'); 115 | legend('APM','ODE15S'); 116 | 117 | subplot(2,1,2); 118 | plot(time_apm,Tc_apm,'r-'); 119 | xlabel('Time (min)'); 120 | ylabel('Temp (K)'); 121 | legend('Jacket'); -------------------------------------------------------------------------------- /example_cstr_seq/matlab_results.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/APMonitor/apm_matlab/ee47918ca71412ddf2f074b20b62eb693f1fcb6f/example_cstr_seq/matlab_results.png -------------------------------------------------------------------------------- /example_cstr_seq/solution_nlc.csv: -------------------------------------------------------------------------------- 1 | time, 0.00 , 2.500000E-01, 2.600000E-01, 5.000000E-01, 7.500000E-01, 1.000000E+00, 1.250000E+00, 1.500000E+00, 1.750000E+00, 2.000000E+00, 2.250000E+00, 2.500000E+00, 2.750000E+00, 3.000000E+00, 3.250000E+00, 3.500000E+00, 3.750000E+00, 4.000000E+00, 4.250000E+00, 4.500000E+00, 4.750000E+00, 5.000000E+00 2 | tc, 2.700000E+02, 2.700000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02 3 | q, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02 4 | v, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02 5 | rho, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03 6 | cp, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01 7 | mdelh, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04 8 | eoverr, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03 9 | k0, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10 10 | ua, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04 11 | caf, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00 12 | tf, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02 13 | ca, 9.890069E-01, 9.890069E-01, 9.890083E-01, 9.905935E-01, 9.924746E-01, 9.940403E-01, 9.952881E-01, 9.962707E-01, 9.970405E-01, 9.976423E-01, 9.981120E-01, 9.984784E-01, 9.987641E-01, 9.989868E-01, 9.991603E-01, 9.992955E-01, 9.994009E-01, 9.994831E-01, 9.995470E-01, 9.995969E-01, 9.996357E-01, 9.996660E-01 14 | t, 2.966166E+02, 2.966166E+02, 2.960973E+02, 2.785317E+02, 2.697669E+02, 2.656621E+02, 2.637427E+02, 2.628456E+02, 2.624263E+02, 2.622304E+02, 2.621389E+02, 2.620962E+02, 2.620762E+02, 2.620668E+02, 2.620625E+02, 2.620604E+02, 2.620595E+02, 2.620591E+02, 2.620588E+02, 2.620588E+02, 2.620587E+02, 2.620587E+02 15 | -------------------------------------------------------------------------------- /example_cstr_simul/README.txt: -------------------------------------------------------------------------------- 1 | Run main.m from the MATLAB console to see the results. This script runs the APM web interface for a simple CSTR model and ODE15s, MATLAB's built in DAE integrator. You must have an internet connection to run this script. 2 | 3 | This folder implements a single simultaneous solution over the time horizon requested. -------------------------------------------------------------------------------- /example_cstr_simul/cstr.apm: -------------------------------------------------------------------------------- 1 | Model 2 | Parameters 3 | Tc = 270 ! Temperature of cooling jacket (K) 4 | q = 100 ! Volumetric Flowrate (m^3/sec) 5 | V = 100 ! Volume of CSTR (m^3) 6 | rho = 1000 ! Density of A-B Mixture (kg/m^3) 7 | Cp = .239 ! Heat capacity of A-B Mixture (J/kg-K) 8 | mdelH = 5e4 ! Heat of reaction for A->B (J/mol) 9 | EoverR = 8750 ! EoverR = E/R = Activation energy / R (8.31451 J/mol-K) 10 | k0 = 7.2e10 ! Pre-exponential factor (1/sec) 11 | UA = 5e4 ! Overall Heat Transfer Coefficient (W/m^2-K) 12 | Caf = 1 ! Feed Concentration (mol/m^3) 13 | Tf = 350 ! Feed Temperature (K) 14 | End Parameters 15 | Variables 16 | Ca = 0.989 ! Concentration of A in CSTR (mol/m^3) 17 | T = 296.6 ! Temperature in CSTR (K) 18 | End Variables 19 | Equations 20 | V * $Ca = q*(Caf-Ca) - k0*V*exp(-EoverR/T)*Ca ! mole balance for species A 21 | rho*Cp*V * $T = q*rho*Cp*(Tf - T) + V*mdelH*k0*exp(-EoverR/T)*Ca + UA*(Tc-T) ! energy balance 22 | End Equations 23 | End Model -------------------------------------------------------------------------------- /example_cstr_simul/cstr.csv: -------------------------------------------------------------------------------- 1 | time,Tc 2 | 0,270 3 | 0.25,270 4 | 0.26,220 5 | 0.5,220 6 | 0.75,220 7 | 1,220 8 | 1.25,220 9 | 1.5,220 10 | 1.75,220 11 | 2,220 12 | 2.25,220 13 | 2.5,220 14 | 2.75,220 15 | 3,220 16 | 3.25,220 17 | 3.5,220 18 | 3.75,220 19 | 4,220 20 | 4.25,220 21 | 4.5,220 22 | 4.75,220 23 | 5,220 24 | -------------------------------------------------------------------------------- /example_cstr_simul/cstr.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/APMonitor/apm_matlab/ee47918ca71412ddf2f074b20b62eb693f1fcb6f/example_cstr_simul/cstr.jpg -------------------------------------------------------------------------------- /example_cstr_simul/cstr1.m: -------------------------------------------------------------------------------- 1 | % This model is used for comparison with ode15s 2 | % It isn't used by the APM code 3 | 4 | % CSTR model from 5 | % 6 | % Michael A. Henson and Dale E. Seborg. Nonlinear Process Control. 7 | % Prentice Hall PTR, Upper Saddle River, New Jersey, 1997. 8 | 9 | % Description: 10 | % Continuously Stirred Tank Reactor with energy balance and reaction A->B. 11 | % The temperature of the cooling jacket is the control. 12 | 13 | function xdot=cstr1(t,x) 14 | 15 | global u 16 | 17 | % Input (1): 18 | % Temperature of cooling jacket (K) 19 | Tc = u; 20 | 21 | % States (2): 22 | % Concentration of A in CSTR (mol/m^3) 23 | Ca = x(1,1); 24 | % Temperature in CSTR (K) 25 | T = x(2,1); 26 | 27 | % Parameters: 28 | % Volumetric Flowrate (m^3/sec) 29 | q = 100; 30 | % Volume of CSTR (m^3) 31 | V = 100; 32 | % Density of A-B Mixture (kg/m^3) 33 | rho = 1000; 34 | % Heat capacity of A-B Mixture (J/kg-K) 35 | Cp = .239; 36 | % Heat of reaction for A->B (J/mol) 37 | mdelH = 5e4; 38 | % E - Activation energy in the Arrhenius Equation (J/mol) 39 | % R - Universal Gas Constant = 8.31451 J/mol-K 40 | EoverR = 8750; 41 | % Pre-exponential factor (1/sec) 42 | k0 = 7.2e10; 43 | % U - Overall Heat Transfer Coefficient (W/m^2-K) 44 | % A - Area - this value is specific for the U calculation (m^2) 45 | UA = 5e4; 46 | % Feed Concentration (mol/m^3) 47 | Caf = 1; 48 | % Feed Temperature (K) 49 | Tf = 350; 50 | 51 | % Compute xdot: 52 | xdot(1,1) = (q/V*(Caf - Ca) - k0*exp(-EoverR/T)*Ca); 53 | xdot(2,1) = (q/V*(Tf - T) + mdelH/(rho*Cp)*k0*exp(-EoverR/T)*Ca + UA/V/rho/Cp*(Tc-T)); -------------------------------------------------------------------------------- /example_cstr_simul/main.m: -------------------------------------------------------------------------------- 1 | % Add path to APM libraries 2 | addpath('../apm'); 3 | 4 | % Clear MATLAB 5 | clear all 6 | close all 7 | 8 | % Select server 9 | server = 'http://byu.apmonitor.com'; 10 | 11 | % Application 12 | app = 'nlc'; 13 | 14 | % Clear previous application 15 | apm(server,app,'clear all'); 16 | 17 | % load model variables and equations 18 | apm_load(server,app,'cstr.apm'); 19 | 20 | % load data 21 | csv_load(server,app,'cstr.csv'); 22 | 23 | % Set up variable classifications for data flow 24 | 25 | % Feedforwards - measured process disturbances 26 | apm_info(server,app,'FV','Caf'); 27 | apm_info(server,app,'FV','Tf'); 28 | % Manipulated variables (for controller design) 29 | apm_info(server,app,'MV','tc'); 30 | % State variables (for display only) 31 | apm_info(server,app,'SV','Ca'); 32 | % Controlled variables (for controller design) 33 | apm_info(server,app,'CV','T'); 34 | 35 | % imode = 1, steady state mode 36 | apm_option(server,app,'nlc.imode',1); 37 | % solve here for steady state initialization 38 | apm(server,app,'solve') 39 | 40 | % imode = 4, switch to simultaneous simulation 41 | apm_option(server,app,'nlc.imode',4); 42 | % nodes = 3, internal nodes in the collocation structure (2-6) 43 | apm_option(server,app,'nlc.nodes',3); 44 | % simulation step size for every 'solve' command 45 | apm_option(server,app,'nlc.ctrl_time',0.25); 46 | % coldstart application 47 | apm_option(server,app,'nlc.coldstart',1); 48 | % read csv file 49 | apm_option(server,app,'nlc.csv_read',1); 50 | 51 | % Run APMonitor 52 | apm(server,app,'solve') 53 | 54 | % Retrieve solution (creates solution.csv locally) 55 | y = apm_sol(server,app); 56 | % Extract names 57 | names = y.names; 58 | % Extract values 59 | cc = y.values; 60 | 61 | % Time is always the first column or row 62 | time_apm = cc(:,1); 63 | 64 | % extract 'Ca' 65 | index = find(strcmpi('Ca',names)); 66 | Ca_apm = cc(:,index); 67 | 68 | % extract 'T' 69 | index = find(strcmpi('T',names)); 70 | T_apm = cc(:,index); 71 | 72 | % extract 'Tc' 73 | index = find(strcmpi('Tc',names)); 74 | Tc_apm = cc(:,index); 75 | 76 | % --------------------------------------------------------- 77 | % simulate with ode15s (for comparison) 78 | % Verify dynamic response of CSTR model 79 | 80 | global u 81 | 82 | % Steady State Initial Conditions for the States 83 | Ca_ss = 0.989; 84 | T_ss = 296.6; 85 | y_ss = [Ca_ss;T_ss]; 86 | 87 | % Open Loop Step Change 88 | u = 220; 89 | 90 | % Final Time (sec) 91 | tf = 5; 92 | 93 | [t_ode15s,y] = ode15s('cstr1',[0.25 tf],y_ss); 94 | 95 | % Parse out the state values 96 | Ca_ode15s = y(:,1); 97 | T_ode15s = y(:,2); 98 | % --------------------------------------------------------- 99 | 100 | 101 | figure(1) 102 | plot(time_apm,Ca_apm,'b-'); 103 | hold on; 104 | plot(t_ode15s,Ca_ode15s,'k--') 105 | xlabel('Time (min)') 106 | ylabel('Concentration') 107 | legend('APM','ODE15S'); 108 | 109 | figure(2) 110 | subplot(2,1,1); 111 | plot(time_apm,T_apm,'b-'); 112 | hold on; 113 | plot(t_ode15s,T_ode15s,'k--'); 114 | ylabel('Temp (K)'); 115 | legend('APM','ODE15S'); 116 | 117 | subplot(2,1,2); 118 | plot(time_apm,Tc_apm,'r-'); 119 | xlabel('Time (min)'); 120 | ylabel('Temp (K)'); 121 | legend('Jacket'); -------------------------------------------------------------------------------- /example_cstr_simul/matlab_results.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/APMonitor/apm_matlab/ee47918ca71412ddf2f074b20b62eb693f1fcb6f/example_cstr_simul/matlab_results.png -------------------------------------------------------------------------------- /example_cstr_simul/solution_nlc.csv: -------------------------------------------------------------------------------- 1 | time, 0.00 , 2.500000E-01, 2.600000E-01, 5.000000E-01, 7.500000E-01, 1.000000E+00, 1.250000E+00, 1.500000E+00, 1.750000E+00, 2.000000E+00, 2.250000E+00, 2.500000E+00, 2.750000E+00, 3.000000E+00, 3.250000E+00, 3.500000E+00, 3.750000E+00, 4.000000E+00, 4.250000E+00, 4.500000E+00, 4.750000E+00, 5.000000E+00 2 | tc, 2.700000E+02, 2.700000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02, 2.200000E+02 3 | q, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02 4 | v, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02, 1.000000E+02 5 | rho, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03, 1.000000E+03 6 | cp, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01, 2.390000E-01 7 | mdelh, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04 8 | eoverr, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03, 8.750000E+03 9 | k0, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10, 7.200000E+10 10 | ua, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04, 5.000000E+04 11 | caf, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00, 1.000000E+00 12 | tf, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02, 3.500000E+02 13 | ca, 9.890069E-01, 9.890069E-01, 9.890083E-01, 9.905935E-01, 9.924746E-01, 9.940403E-01, 9.952881E-01, 9.962707E-01, 9.970405E-01, 9.976423E-01, 9.981120E-01, 9.984784E-01, 9.987641E-01, 9.989867E-01, 9.991603E-01, 9.992955E-01, 9.994009E-01, 9.994830E-01, 9.995470E-01, 9.995969E-01, 9.996357E-01, 9.996660E-01 14 | t, 2.966166E+02, 2.966166E+02, 2.960973E+02, 2.785317E+02, 2.697669E+02, 2.656621E+02, 2.637427E+02, 2.628456E+02, 2.624263E+02, 2.622304E+02, 2.621389E+02, 2.620962E+02, 2.620762E+02, 2.620668E+02, 2.620625E+02, 2.620604E+02, 2.620595E+02, 2.620591E+02, 2.620588E+02, 2.620588E+02, 2.620587E+02, 2.620587E+02 15 | -------------------------------------------------------------------------------- /example_cstr_steps/README.txt: -------------------------------------------------------------------------------- 1 | Run main.m from the MATLAB console to see the results. This script runs the APM web interface for a simple CSTR model and ODE15s, MATLAB's built in DAE integrator. You must have an internet connection to run this script. 2 | 3 | This folder implements a single simultaneous solution over the time horizon requested. -------------------------------------------------------------------------------- /example_cstr_steps/cstr.apm: -------------------------------------------------------------------------------- 1 | Model 2 | Parameters 3 | Tc = 270 ! Temperature of cooling jacket (K) 4 | q = 100 ! Volumetric Flowrate (m^3/sec) 5 | V = 100 ! Volume of CSTR (m^3) 6 | rho = 1000 ! Density of A-B Mixture (kg/m^3) 7 | Cp = .239 ! Heat capacity of A-B Mixture (J/kg-K) 8 | mdelH = 5e4 ! Heat of reaction for A->B (J/mol) 9 | EoverR = 8750 ! EoverR = E/R = Activation energy / R (8.31451 J/mol-K) 10 | k0 = 7.2e10 ! Pre-exponential factor (1/sec) 11 | UA = 5e4 ! Overall Heat Transfer Coefficient (W/m^2-K) 12 | Caf = 1 ! Feed Concentration (mol/m^3) 13 | Tf = 350 ! Feed Temperature (K) 14 | End Parameters 15 | Variables 16 | Ca = 0.989 ! Concentration of A in CSTR (mol/m^3) 17 | T = 296.6 ! Temperature in CSTR (K) 18 | End Variables 19 | Equations 20 | V * $Ca = q*(Caf-Ca) - k0*V*exp(-EoverR/T)*Ca ! mole balance for species A 21 | rho*Cp*V * $T = q*rho*Cp*(Tf - T) + V*mdelH*k0*exp(-EoverR/T)*Ca + UA*(Tc-T) ! energy balance 22 | End Equations 23 | End Model -------------------------------------------------------------------------------- /example_cstr_steps/cstr.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/APMonitor/apm_matlab/ee47918ca71412ddf2f074b20b62eb693f1fcb6f/example_cstr_steps/cstr.jpg -------------------------------------------------------------------------------- /example_cstr_steps/cstr1.csv: -------------------------------------------------------------------------------- 1 | time,Tc 2 | 0,270 3 | 0.25,270 4 | 0.26,220 5 | 0.5,220 6 | 0.75,220 7 | 1,220 8 | 9 | -------------------------------------------------------------------------------- /example_cstr_steps/cstr1.m: -------------------------------------------------------------------------------- 1 | % This model is used for comparison with ode15s 2 | % It isn't used by the APM code 3 | 4 | % CSTR model from 5 | % 6 | % Michael A. Henson and Dale E. Seborg. Nonlinear Process Control. 7 | % Prentice Hall PTR, Upper Saddle River, New Jersey, 1997. 8 | 9 | % Description: 10 | % Continuously Stirred Tank Reactor with energy balance and reaction A->B. 11 | % The temperature of the cooling jacket is the control. 12 | 13 | function xdot=cstr1(t,x) 14 | 15 | global u 16 | 17 | % Input (1): 18 | % Temperature of cooling jacket (K) 19 | Tc = u; 20 | 21 | % States (2): 22 | % Concentration of A in CSTR (mol/m^3) 23 | Ca = x(1,1); 24 | % Temperature in CSTR (K) 25 | T = x(2,1); 26 | 27 | % Parameters: 28 | % Volumetric Flowrate (m^3/sec) 29 | q = 100; 30 | % Volume of CSTR (m^3) 31 | V = 100; 32 | % Density of A-B Mixture (kg/m^3) 33 | rho = 1000; 34 | % Heat capacity of A-B Mixture (J/kg-K) 35 | Cp = .239; 36 | % Heat of reaction for A->B (J/mol) 37 | mdelH = 5e4; 38 | % E - Activation energy in the Arrhenius Equation (J/mol) 39 | % R - Universal Gas Constant = 8.31451 J/mol-K 40 | EoverR = 8750; 41 | % Pre-exponential factor (1/sec) 42 | k0 = 7.2e10; 43 | % U - Overall Heat Transfer Coefficient (W/m^2-K) 44 | % A - Area - this value is specific for the U calculation (m^2) 45 | UA = 5e4; 46 | % Feed Concentration (mol/m^3) 47 | Caf = 1; 48 | % Feed Temperature (K) 49 | Tf = 350; 50 | 51 | % Compute xdot: 52 | xdot(1,1) = (q/V*(Caf - Ca) - k0*exp(-EoverR/T)*Ca); 53 | xdot(2,1) = (q/V*(Tf - T) + mdelH/(rho*Cp)*k0*exp(-EoverR/T)*Ca + UA/V/rho/Cp*(Tc-T)); -------------------------------------------------------------------------------- /example_cstr_steps/cstr2.csv: -------------------------------------------------------------------------------- 1 | time,Tc 2 | 0,220 3 | 0.25,220 4 | 0.26,220 5 | 0.5,220 6 | 0.75,220 7 | 1,220 8 | 9 | -------------------------------------------------------------------------------- /example_cstr_steps/main.m: -------------------------------------------------------------------------------- 1 | % Add path to APM libraries 2 | addpath('../apm'); 3 | 4 | % Clear MATLAB 5 | clear all 6 | close all 7 | 8 | % Select server 9 | server = 'http://byu.apmonitor.com'; 10 | 11 | % Application 12 | app = 'nlc'; 13 | 14 | % Clear previous application 15 | apm(server,app,'clear all'); 16 | 17 | % load model variables and equations 18 | apm_load(server,app,'cstr.apm'); 19 | 20 | % load data 21 | csv_load(server,app,'cstr1.csv'); 22 | 23 | % Set up variable classifications for data flow 24 | 25 | % Feedforwards - measured process disturbances 26 | apm_info(server,app,'FV','Caf'); 27 | apm_info(server,app,'FV','Tf'); 28 | % Manipulated variables (for controller design) 29 | apm_info(server,app,'MV','tc'); 30 | % State variables (for display only) 31 | apm_info(server,app,'SV','Ca'); 32 | % Controlled variables (for controller design) 33 | apm_info(server,app,'CV','T'); 34 | 35 | % imode = 1, steady state mode 36 | apm_option(server,app,'nlc.imode',1); 37 | % solve here for steady state initialization 38 | apm(server,app,'solve') 39 | 40 | % imode = 4, switch to dynamic simulation 41 | apm_option(server,app,'nlc.imode',4); 42 | % nodes = 3, internal nodes in the collocation structure (2-6) 43 | apm_option(server,app,'nlc.nodes',3); 44 | % simulation step size for every 'solve' command 45 | apm_option(server,app,'nlc.ctrl_time',0.25); 46 | % coldstart application 47 | apm_option(server,app,'nlc.coldstart',1); 48 | % read csv file 49 | apm_option(server,app,'nlc.csv_read',1); 50 | 51 | % time shift 52 | apm_option(server,app,'nlc.time_shift',5); 53 | 54 | % solve problem in 5 blocks 55 | X = []; 56 | for isim = 1:5, 57 | % load a different data file on cycle two 58 | if (isim==2), 59 | apm(server,app,'clear csv'); 60 | csv_load(server,app,'cstr2.csv'); 61 | end 62 | 63 | % Run APMonitor 64 | apm(server,app,'solve') 65 | 66 | % Retrieve solution (creates solution.csv locally) 67 | solution = apm_sol(server,app); 68 | cc = cell2mat(solution(2:end,:)); 69 | if (isim==1), 70 | time = cc(:,1) + isim-1; 71 | X(:,1) = cc(:,2); 72 | X(:,2:3) = cc(:,13:14); 73 | else 74 | time = [time; cc(:,1) + isim-1]; 75 | Y = [X(:,1); cc(:,2)]; 76 | Z = [X(:,2:3); cc(:,13:14)]; 77 | X = [Y Z]; 78 | end 79 | end 80 | 81 | % simulate with ode15s (for comparison) 82 | % Verify dynamic response of CSTR model 83 | 84 | global u 85 | 86 | % Steady State Initial Conditions for the States 87 | Ca_ss = 0.989; 88 | T_ss = 296.6; 89 | y_ss = [Ca_ss;T_ss]; 90 | 91 | % Open Loop Step Change 92 | u = 220; 93 | 94 | % Final Time (sec) 95 | tf = 5; 96 | 97 | [t_ode15s,y] = ode15s('cstr1',[0.25 tf],y_ss); 98 | 99 | % Parse out the state values 100 | Ca_ode15s = y(:,1); 101 | T_ode15s = y(:,2); 102 | 103 | 104 | figure(1) 105 | plot(time,X(:,2),'b-'); 106 | hold on; 107 | plot(t_ode15s,Ca_ode15s,'k--') 108 | xlabel('Time (min)') 109 | ylabel('Concentration') 110 | legend('APM','ODE15S'); 111 | 112 | figure(2) 113 | subplot(2,1,1); 114 | plot(time,X(:,3),'b-'); 115 | hold on; 116 | plot(t_ode15s,T_ode15s,'k--'); 117 | ylabel('Temp (K)'); 118 | legend('APM','ODE15S'); 119 | 120 | subplot(2,1,2); 121 | plot(time,X(:,1),'r-'); 122 | xlabel('Time (min)'); 123 | ylabel('Temp (K)'); 124 | legend('Jacket'); -------------------------------------------------------------------------------- /example_cstr_steps/matlab_results.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/APMonitor/apm_matlab/ee47918ca71412ddf2f074b20b62eb693f1fcb6f/example_cstr_steps/matlab_results.png -------------------------------------------------------------------------------- /example_distillation/distill.apm: -------------------------------------------------------------------------------- 1 | Model 2 | Parameters 3 | ! reflux ratio 4 | rr = 3.0, >=0.0, <=100 5 | 6 | ! fraction of feed leaving from bottoms 7 | fbot = 0.5, >=0.0, <=1.0 8 | 9 | ! Feed Flowrate (mol/min) 10 | Feed = 2.0, >=0 11 | ! Mole Fraction of Feed 12 | x_Feed = 0.5, >=0, <=1 13 | ! Relative Volatility = (yA/xA)/(yB/xB) = KA/KB = alpha(A,B) 14 | alpha = 1.6, >=0 15 | ! Total Molar Holdup in the Condenser 16 | atray=0.25, >=0 17 | ! Total Molar Holdup on each Tray 18 | acond=0.5, >=0 19 | ! Total Molar Holdup in the Reboiler 20 | areb=2.0, >=0 21 | 22 | ! For trending the historical set points 23 | sp_x[1] = 0.935 24 | sp_x[32] = 0.065 25 | End Parameters 26 | 27 | Variables 28 | ! mole fraction of component A at 29 | ! (1) condenser 30 | ! (30) trays 31 | ! (1) reboiler 32 | x[1:32] 33 | End Variables 34 | 35 | Intermediates 36 | ! Assume constant molar holdups on trays / reboiler 37 | ! Assume feed is liquid at bubble point 38 | ! Distillate Flowrate (mol/min) 39 | D=(1-fbot)*Feed 40 | ! Flowrate of the Liquid in the Rectification Section (mol/min) 41 | L=rr*D 42 | ! Vapor Flowrate in the Column (mol/min) 43 | V=L+D 44 | ! Flowrate of the Liquid in the Stripping Section (mol/min) 45 | FL=Feed+L 46 | 47 | ! Vapor Mole Fractions of Component A 48 | ! From the equilibrium assumption and mole balances 49 | ! 1) alpha = (yA/xA) / (yB/xB), xA + xB = 1, yA + yB = 1 50 | ! 2) alpha = yA xB / xA yB 51 | ! 3) alpha = y(1-x) / x(1-y) (with x = xA, y = yA) 52 | ! 4) alpha (x*y-x) = x*y - y 53 | ! 5) y + alpha*x*y - x*y = x * alpha 54 | ! 6) y*(1+alpha*x-x) = x*alpha 55 | y[1:32] = x[1:32]*alpha/(1+(alpha-1)*x[1:32]) 56 | End Intermediates 57 | 58 | Equations 59 | ! condenser 60 | acond * $x[1] = V*(y[2]-x[1]) 61 | 62 | ! 15 column stages 63 | atray * $x[2:16] = L*(x[1:15]-x[2:16]) - V*(y[2:16]-y[3:17]) 64 | 65 | ! feed tray 66 | atray * $x[17] = Feed*x_Feed + L*x[16] - FL*x[17] - V*(y[17]-y[18]) 67 | 68 | ! 14 column stages 69 | atray * $x[18:31] = FL*(x[17:30]-x[18:31]) - V*(y[18:31]-y[19:32]) 70 | 71 | ! reboiler 72 | areb * $x[32] = FL*x[31] - (Feed-D)*x[32] - V*y[32] 73 | End Equations 74 | End Model 75 | 76 | File *.plt 77 | New Trend 78 | x[1] 79 | x[2] 80 | x[3] 81 | x[5] 82 | x[10] 83 | x[15] 84 | x[20] 85 | x[25] 86 | x[30] 87 | x[31] 88 | x[32] 89 | New Trend 90 | rr 91 | fbot 92 | x[1] 93 | x[32] 94 | New Trend 95 | x[1] 96 | sp_x[1] 97 | New Trend 98 | x[32] 99 | sp_x[32] 100 | End File -------------------------------------------------------------------------------- /example_distillation/distill_pid.apm: -------------------------------------------------------------------------------- 1 | Model 2 | Parameters 3 | ! pid tuning parameters for top composition control 4 | kc_1 = 1/0.069 ! ~1/Kp1 5 | taui_1 = 30 ! ~taup1 6 | taud_1 = 0 ! 0 7 | sp_x[1] = 0.935 8 | 9 | ! pid tuning parameters for bottom composition control 10 | kc_2 = 1/1.42 ! ~1/Kp2 11 | taui_2 = 60 ! ~taup2 12 | taud_2 = 0 ! 0 13 | sp_x[32] = 0.065 14 | 15 | ! Feed Flowrate (mol/min) 16 | Feed = 2.0, >=0 17 | ! Mole Fraction of Feed 18 | x_Feed = 0.5, >=0, <=1 19 | ! Relative Volatility = (yA/xA)/(yB/xB) = KA/KB = alpha(A,B) 20 | alpha = 1.6, >=0 21 | ! Total Molar Holdup in the Condenser 22 | atray=0.25, >=0 23 | ! Total Molar Holdup on each Tray 24 | acond=0.5, >=0 25 | ! Total Molar Holdup in the Reboiler 26 | areb=2.0, >=0 27 | End Parameters 28 | 29 | Variables 30 | ! reflux ratio 31 | rr = 3.0 32 | i_rr = 0 ! integrator in pid equation 33 | 34 | ! fraction of feed leaving from bottoms 35 | fbot = 0.5 36 | i_fbot = 0 ! integrator in pid equation 37 | 38 | ! mole fraction of component A at 39 | ! (1) condenser 40 | ! (30) trays 41 | ! (1) reboiler 42 | x[1:32] 43 | End Variables 44 | 45 | Intermediates 46 | ! Assume constant molar holdups on trays / reboiler 47 | ! Assume feed is liquid at bubble point 48 | ! Distillate Flowrate (mol/min) 49 | D=(1-fbot)*Feed 50 | ! Flowrate of the Liquid in the Rectification Section (mol/min) 51 | L=rr*D 52 | ! Vapor Flowrate in the Column (mol/min) 53 | V=L+D 54 | ! Flowrate of the Liquid in the Stripping Section (mol/min) 55 | FL=Feed+L 56 | 57 | ! Vapor Mole Fractions of Component A 58 | ! From the equilibrium assumption and mole balances 59 | ! 1) alpha = (yA/xA) / (yB/xB), xA + xB = 1, yA + yB = 1 60 | ! 2) alpha = yA xB / xA yB 61 | ! 3) alpha = y(1-x) / x(1-y) (with x = xA, y = yA) 62 | ! 4) alpha (x*y-x) = x*y - y 63 | ! 5) y + alpha*x*y - x*y = x * alpha 64 | ! 6) y*(1+alpha*x-x) = x*alpha 65 | y[1:32] = x[1:32]*alpha/(1+(alpha-1)*x[1:32]) 66 | End Intermediates 67 | 68 | Equations 69 | ! pid equations for rr / x[1] control 70 | rr = kc_1 * (sp_x[1]-x[1]) + (kc_1/taui_1) * i_rr - kc_1 * taud_1 * $x[1] 71 | $i_rr = (sp_x[1]-x[1]) 72 | 73 | ! pid equations for fbot / x[32] control 74 | fbot = kc_2 * (sp_x[32]-x[32]) + (kc_2/taui_2) * i_fbot - kc_2 * taud_2 * $x[32] 75 | $i_fbot = (sp_x[32]-x[32]) 76 | 77 | ! condenser 78 | acond * $x[1] = V*(y[2]-x[1]) 79 | 80 | ! 15 column stages 81 | atray * $x[2:16] = L*(x[1:15]-x[2:16]) - V*(y[2:16]-y[3:17]) 82 | 83 | ! feed tray 84 | atray * $x[17] = Feed*x_Feed + L*x[16] - FL*x[17] - V*(y[17]-y[18]) 85 | 86 | ! 14 column stages 87 | atray * $x[18:31] = FL*(x[17:30]-x[18:31]) - V*(y[18:31]-y[19:32]) 88 | 89 | ! reboiler 90 | areb * $x[32] = FL*x[31] - (Feed-D)*x[32] - V*y[32] 91 | End Equations 92 | End Model 93 | 94 | File *.plt 95 | New Trend 96 | x[1] 97 | x[2] 98 | x[3] 99 | x[5] 100 | x[10] 101 | x[15] 102 | x[20] 103 | x[25] 104 | x[30] 105 | x[31] 106 | x[32] 107 | New Trend 108 | rr 109 | fbot 110 | x[1] 111 | x[32] 112 | New Trend 113 | x[1] 114 | sp_x[1] 115 | New Trend 116 | x[32] 117 | sp_x[32] 118 | End File -------------------------------------------------------------------------------- /example_distillation/horizon_ctl.csv: -------------------------------------------------------------------------------- 1 | time 2 | 0 3 | 5 4 | 10 5 | 20 6 | 40 7 | 60 8 | -------------------------------------------------------------------------------- /example_distillation/horizon_sim.csv: -------------------------------------------------------------------------------- 1 | time 2 | 0 3 | 5 4 | 10 5 | 20 6 | 40 7 | 60 8 | -------------------------------------------------------------------------------- /example_distillation/main_nlc.m: -------------------------------------------------------------------------------- 1 | addpath('../apm'); 2 | 3 | % Clear MATLAB 4 | clear all 5 | close all 6 | 7 | % Select server 8 | server = 'http://xps.apmonitor.com' 9 | 10 | % Set application name 11 | app = int2str(int32(rand()*10000)); 12 | 13 | % Clear previous application 14 | apm(server,app,'clear all'); 15 | 16 | % Load model file 17 | disp ('Load Model') 18 | apm_load(server,app,'distill.apm'); 19 | 20 | % Load time points for future predictions 21 | disp ('Load CSV File') 22 | csv_load(server,app,'horizon_ctl.csv'); 23 | 24 | % Load replay replay data for local use 25 | csv = csv_data('replay_ctl.csv'); 26 | 27 | % APM Variable Classification 28 | % class = FV, MV, SV, CV 29 | % F or FV = Fixed value - parameter may change to a new value every cycle 30 | % M or MV = Manipulated variable - independent variable over time horizon 31 | % S or SV = State variable - model variable for viewing 32 | % C or CV = Controlled variable - model variable for control 33 | % Names of each variable type in cell arrays 34 | % Same as listed in the model.apm file 35 | FVs = {'feed','x_feed','alpha','atray','acond','areb'}; 36 | MVs = {'rr','fbot','sp_x[1]','sp_x[32]'}; 37 | SVs = {'x[2]','x[5]','x[10]','x[15]','x[20]','x[25]','x[30]','x[31]'}; 38 | CVs = {'x[1]','x[32]'}; 39 | 40 | % Get number of each variable type 41 | n_FVs = size(FVs,2); 42 | n_MVs = size(MVs,2); 43 | n_SVs = size(SVs,2); 44 | n_CVs = size(CVs,2); 45 | 46 | % Set up variable classifications for data flow 47 | % Feedforwards - measured process disturbances 48 | for i = 1:n_FVs, 49 | apm_info(server,app,'FV',FVs(:,i)); 50 | end 51 | % Manipulated variables / parameters 52 | for i = 1:n_MVs, 53 | apm_info(server,app,'MV',MVs(:,i)); 54 | end 55 | % State variables (for display only) 56 | for i = 1:n_SVs, 57 | apm_info(server,app,'SV',SVs(:,i)); 58 | end 59 | % Controlled / Measured variables 60 | for i = 1:n_CVs, 61 | apm_info(server,app,'CV',CVs(:,i)); 62 | end 63 | 64 | % Options 65 | 66 | % time units (1=sec,2=min,3=hrs,etc) 67 | apm_option(server,app,'nlc.ctrl_units',2); 68 | apm_option(server,app,'nlc.hist_units',3); 69 | 70 | % set controlled variable error model type 71 | apm_option(server,app,'nlc.cv_type',1); 72 | apm_option(server,app,'nlc.ev_type',1); 73 | 74 | % controller mode (1=simulate, 2=predict, 3=control) 75 | apm_option(server,app,'nlc.reqctrlmode',1); 76 | 77 | % read discretization from CSV file 78 | apm_option(server,app,'nlc.csv_read',1); 79 | 80 | % turn on historization to see past results 81 | apm_option(server,app,'nlc.hist_hor',200); 82 | 83 | % set web plot update frequency 84 | apm_option(server,app,'nlc.web_plot_freq',10); 85 | 86 | % Controlled variable (c) 87 | apm_option(server,app,'x[1].sphi',0.95); 88 | apm_option(server,app,'x[1].splo',0.94); 89 | apm_option(server,app,'x[1].tau',20.0); 90 | apm_option(server,app,'x[1].fstatus',0); 91 | 92 | apm_option(server,app,'x[32].sphi',0.05); 93 | apm_option(server,app,'x[32].splo',0.04); 94 | apm_option(server,app,'x[32].tau',20.0); 95 | apm_option(server,app,'x[32].fstatus',0); 96 | 97 | % Manipulated variables (u) 98 | apm_option(server,app,'rr.upper',10); 99 | apm_option(server,app,'rr.dmax',0.2); 100 | apm_option(server,app,'rr.lower',1); 101 | apm_option(server,app,'rr.fstatus',0); 102 | 103 | apm_option(server,app,'fbot.upper',1); 104 | apm_option(server,app,'fbot.dmax',0.05); 105 | apm_option(server,app,'fbot.lower',0); 106 | apm_option(server,app,'fbot.fstatus',0); 107 | 108 | % Measured Disturbances 109 | apm_option(server,app,'feed.fstatus',1); 110 | apm_option(server,app,'x_feed.fstatus',1); 111 | 112 | % imode (1=ss, 2=mpu, 3=rto, 4=sim, 5=mhe, 6=nlc) 113 | apm_option(server,app,'nlc.imode',1); 114 | apm_option(server,app,'nlc.sensitivity',1); 115 | 116 | % steady state solution 117 | apm(server,app,'solve'); 118 | 119 | % imode (1=ss, 2=mpu, 3=rto, 4=sim, 5=mhe, 6=nlc) 120 | apm_option(server,app,'nlc.imode',6) 121 | apm_option(server,app,'nlc.sensitivity',0); 122 | 123 | blank_line = sprintf('\n'); 124 | for isim = 1:size(csv,1)-1, 125 | pause(0.1) 126 | 127 | disp(blank_line) 128 | disp(['--- Cycle ' num2str(isim) ' of ' num2str(size(csv,1)-1) '---']) 129 | 130 | if (isim==2), 131 | % turn on controller 132 | apm_option(server,app,'nlc.reqctrlmode',3); 133 | % turn on overhead composition control 134 | apm_option(server,app,'rr.status',1); 135 | apm_option(server,app,'x[1].sphi',0.952); 136 | apm_option(server,app,'x[1].splo',0.952); 137 | apm_option(server,app,'x[1].status',1); 138 | apm_meas(server,app,'sp_x[1]',0.952); 139 | % turn on bottoms composition control 140 | apm_option(server,app,'fbot.status',1); 141 | apm_option(server,app,'x[32].sphi',0.019); 142 | apm_option(server,app,'x[32].splo',0.019); 143 | apm_option(server,app,'x[32].status',1); 144 | apm_meas(server,app,'sp_x[32]',0.019); 145 | end 146 | 147 | if (isim==70), 148 | % set point change 149 | apm_option(server,app,'x[1].sphi',0.9955); 150 | apm_option(server,app,'x[1].splo',0.9955); 151 | apm_option(server,app,'x[32].sphi',0.0095); 152 | apm_option(server,app,'x[32].splo',0.0095); 153 | apm_meas(server,app,'sp_x[1]',0.9955); 154 | apm_meas(server,app,'sp_x[32]',0.0095); 155 | end 156 | 157 | % FV measurements 158 | for i = 1:n_FVs, 159 | name = deblank(FVs(:,i)); 160 | value = csv_element(name,isim,csv); 161 | if (~isnan(value)), 162 | apm_meas(server,app,name,value); 163 | end 164 | end 165 | % MV measurements 166 | for i = 1:n_MVs, 167 | name = deblank(MVs(:,i)); 168 | value = csv_element(name,isim,csv); 169 | if (~isnan(value)), 170 | apm_meas(server,app,name,value); 171 | end 172 | end 173 | % CV measurements 174 | for i = 1:n_CVs, 175 | name = deblank(CVs(:,i)); 176 | value = csv_element(name,isim,csv); 177 | if (~isnan(value)), 178 | apm_meas(server,app,name,value); 179 | end 180 | end 181 | 182 | % Run NLC on APMonitor server 183 | apm(server,app,'solve'); 184 | 185 | if (isim==1), 186 | apm_web(server,app) 187 | end 188 | 189 | end 190 | -------------------------------------------------------------------------------- /example_distillation/main_pid.m: -------------------------------------------------------------------------------- 1 | addpath('../apm'); 2 | 3 | % Clear MATLAB 4 | clear all 5 | close all 6 | 7 | % Select server 8 | server = 'http://xps.apmonitor.com' 9 | 10 | % Set application name 11 | app = int2str(int32(rand()*10000)); 12 | 13 | % Clear previous application 14 | apm(server,app,'clear all'); 15 | 16 | % Load model file 17 | disp ('Load Model') 18 | apm_load(server,app,'distill_pid.apm'); 19 | 20 | % Load time points for future predictions 21 | disp ('Load CSV File') 22 | csv_load(server,app,'horizon_sim.csv'); 23 | 24 | % Load replay replay data for local use 25 | csv = csv_data('replay_ctl.csv'); 26 | 27 | % APM Variable Classification 28 | % class = FV, MV, SV, CV 29 | % F or FV = Fixed value - parameter may change to a new value every cycle 30 | % M or MV = Manipulated variable - independent variable over time horizon 31 | % S or SV = State variable - model variable for viewing 32 | % C or CV = Controlled variable - model variable for control 33 | % Names of each variable type in cell arrays 34 | % Same as listed in the model.apm file 35 | FVs = {'feed','x_feed','alpha','atray','acond','areb'}; 36 | MVs = {'sp_x[1]','sp_x[32]'}; 37 | SVs = {'rr','fbot','x[2]','x[5]','x[10]','x[15]','x[20]','x[25]','x[30]','x[31]'}; 38 | CVs = {'x[1]','x[32]'}; 39 | 40 | % Get number of each variable type 41 | n_FVs = size(FVs,2); 42 | n_MVs = size(MVs,2); 43 | n_SVs = size(SVs,2); 44 | n_CVs = size(CVs,2); 45 | 46 | % Set up variable classifications for data flow 47 | % Feedforwards - measured process disturbances 48 | for i = 1:n_FVs, 49 | apm_info(server,app,'FV',FVs(:,i)); 50 | end 51 | % Manipulated variables / parameters 52 | for i = 1:n_MVs, 53 | apm_info(server,app,'MV',MVs(:,i)); 54 | end 55 | % State variables (for display only) 56 | for i = 1:n_SVs, 57 | apm_info(server,app,'SV',SVs(:,i)); 58 | end 59 | % Controlled / Measured variables 60 | for i = 1:n_CVs, 61 | apm_info(server,app,'CV',CVs(:,i)); 62 | end 63 | 64 | % Options 65 | 66 | % time units (1=sec,2=min,3=hrs,etc) 67 | apm_option(server,app,'nlc.ctrl_units',2); 68 | apm_option(server,app,'nlc.hist_units',3); 69 | 70 | % set controlled variable error model type 71 | apm_option(server,app,'nlc.cv_type',1); 72 | apm_option(server,app,'nlc.ev_type',1); 73 | 74 | % controller mode (1=simulate, 2=predict, 3=control) 75 | apm_option(server,app,'nlc.reqctrlmode',1); 76 | 77 | % read discretization from CSV file 78 | apm_option(server,app,'nlc.csv_read',1); 79 | 80 | % turn on historization to see past results 81 | apm_option(server,app,'nlc.hist_hor',200); 82 | 83 | % set web plot update frequency 84 | apm_option(server,app,'nlc.web_plot_freq',10); 85 | 86 | % Measured Disturbances 87 | apm_option(server,app,'feed.fstatus',1); 88 | apm_option(server,app,'x_feed.fstatus',1); 89 | 90 | % imode (1=ss, 2=mpu, 3=rto, 4=sim, 5=mhe, 6=nlc) 91 | apm_option(server,app,'nlc.imode',1); 92 | apm_option(server,app,'nlc.sensitivity',1); 93 | 94 | % steady state solution 95 | apm(server,app,'solve'); 96 | 97 | % imode (1=ss, 2=mpu, 3=rto, 4=sim, 5=mhe, 6=nlc) 98 | apm_option(server,app,'nlc.imode',4) 99 | apm_option(server,app,'nlc.sensitivity',0); 100 | 101 | blank_line = sprintf('\n'); 102 | for isim = 1:size(csv,1)-1, 103 | pause(0.1) 104 | 105 | disp(blank_line) 106 | disp(['--- Cycle ' num2str(isim) ' of ' num2str(size(csv,1)-1) '---']) 107 | 108 | if (isim==2), 109 | % controller set-points 110 | apm_meas(server,app,'sp_x[1]',0.952) 111 | apm_meas(server,app,'sp_x[32]',0.019) 112 | end 113 | 114 | if (isim==70), 115 | % set point change 116 | apm_meas(server,app,'sp_x[1]',0.9955) 117 | apm_meas(server,app,'sp_x[32]',0.0095) 118 | end 119 | 120 | % FV measurements 121 | for i = 1:n_FVs, 122 | name = deblank(FVs(:,i)); 123 | value = csv_element(name,isim,csv); 124 | if (~isnan(value)), 125 | apm_meas(server,app,name,value); 126 | end 127 | end 128 | % MV measurements 129 | for i = 1:n_MVs, 130 | name = deblank(MVs(:,i)); 131 | value = csv_element(name,isim,csv); 132 | if (~isnan(value)), 133 | apm_meas(server,app,name,value); 134 | end 135 | end 136 | % CV measurements 137 | for i = 1:n_CVs, 138 | name = deblank(CVs(:,i)); 139 | value = csv_element(name,isim,csv); 140 | if (~isnan(value)), 141 | apm_meas(server,app,name,value); 142 | end 143 | end 144 | 145 | % Run NLC on APMonitor server 146 | apm(server,app,'solve'); 147 | 148 | if (isim==1), 149 | apm_web(server,app) 150 | end 151 | 152 | end 153 | -------------------------------------------------------------------------------- /example_distillation/replay_ctl.csv: -------------------------------------------------------------------------------- 1 | time,feed,x_feed 2 | 0,2,0.5 3 | 5,2,0.5 4 | 10,2,0.5 5 | 15,2,0.5 6 | 20,2,0.5 7 | 25,2.5,0.5 8 | 30,2.5,0.5 9 | 35,2.5,0.5 10 | 40,2.5,0.5 11 | 45,2.5,0.5 12 | 50,2.5,0.5 13 | 55,2.5,0.5 14 | 60,2.5,0.5 15 | 65,1.5,0.5 16 | 70,1.5,0.5 17 | 75,1.5,0.5 18 | 80,1.5,0.5 19 | 85,1.5,0.5 20 | 90,1.5,0.5 21 | 95,1.5,0.5 22 | 100,1.5,0.5 23 | 105,1.5,0.5 24 | 110,1.5,0.5 25 | 115,1.5,0.5 26 | 120,1.5,0.5 27 | 125,2,0.5 28 | 130,2,0.5 29 | 135,2,0.5 30 | 140,2,0.5 31 | 145,2,0.5 32 | 150,2,0.5 33 | 155,2,0.5 34 | 160,2,0.5 35 | 165,2,0.5 36 | 170,2,0.5 37 | 175,2,0.5 38 | 180,2,0.6 39 | 185,2,0.6 40 | 190,2,0.6 41 | 195,2,0.6 42 | 200,2,0.6 43 | 205,2,0.6 44 | 210,2,0.6 45 | 215,2,0.6 46 | 220,2,0.6 47 | 225,2,0.6 48 | 230,2,0.6 49 | 235,2,0.6 50 | 240,2,0.6 51 | 245,2,0.4 52 | 250,2,0.4 53 | 255,2,0.4 54 | 260,2,0.4 55 | 265,2,0.4 56 | 270,2,0.4 57 | 275,2,0.4 58 | 280,2,0.4 59 | 285,2,0.4 60 | 290,2,0.4 61 | 295,2,0.4 62 | 300,2,0.4 63 | 305,2,0.5 64 | 310,2,0.5 65 | 315,2,0.5 66 | 320,2,0.5 67 | 325,2,0.5 68 | 330,2,0.5 69 | 335,2,0.5 70 | 340,2,0.5 71 | 345,2,0.5 72 | 350,2,0.5 73 | 355,2,0.5 74 | 360,2,0.5 75 | 365,2,0.5 76 | 370,2,0.5 77 | 375,2,0.5 78 | 380,2,0.5 79 | 385,2,0.5 80 | 390,2,0.5 81 | 395,2,0.5 82 | 400,2,0.5 83 | 405,2,0.5 84 | 410,2,0.5 85 | 415,2,0.5 86 | 420,2,0.5 87 | 425,2,0.5 88 | 430,2,0.5 89 | 435,2,0.5 90 | 440,2,0.5 91 | 445,2,0.5 92 | 450,2,0.5 93 | 455,2,0.5 94 | 460,2,0.5 95 | 465,2,0.5 96 | 470,2,0.5 97 | 475,2,0.5 98 | 480,2,0.5 99 | 485,2,0.5 100 | 490,2,0.5 101 | 495,2,0.5 102 | 500,2,0.5 103 | -------------------------------------------------------------------------------- /example_distillation/replay_sim.csv: -------------------------------------------------------------------------------- 1 | time,rr,fbot 2 | 0,3,0.5 3 | 5,3,0.5 4 | 10,3.5,0.5 5 | 15,3.5,0.5 6 | 20,3.5,0.5 7 | 25,3.5,0.5 8 | 30,3.5,0.5 9 | 35,3.5,0.5 10 | 40,3.5,0.5 11 | 45,3.5,0.5 12 | 50,3.5,0.5 13 | 55,3.5,0.5 14 | 60,3.5,0.5 15 | 65,2.5,0.5 16 | 70,2.5,0.5 17 | 75,2.5,0.5 18 | 80,2.5,0.5 19 | 85,2.5,0.5 20 | 90,2.5,0.5 21 | 95,2.5,0.5 22 | 100,2.5,0.5 23 | 105,2.5,0.5 24 | 110,2.5,0.5 25 | 115,2.5,0.5 26 | 120,2.5,0.5 27 | 125,3,0.5 28 | 130,3,0.5 29 | 135,3,0.5 30 | 140,3,0.5 31 | 145,3,0.5 32 | 150,3,0.5 33 | 155,3,0.5 34 | 160,3,0.5 35 | 165,3,0.5 36 | 170,3,0.5 37 | 175,3,0.5 38 | 180,3,0.6 39 | 185,3,0.6 40 | 190,3,0.6 41 | 195,3,0.6 42 | 200,3,0.6 43 | 205,3,0.6 44 | 210,3,0.6 45 | 215,3,0.6 46 | 220,3,0.6 47 | 225,3,0.6 48 | 230,3,0.6 49 | 235,3,0.6 50 | 240,3,0.6 51 | 245,3,0.4 52 | 250,3,0.4 53 | 255,3,0.4 54 | 260,3,0.4 55 | 265,3,0.4 56 | 270,3,0.4 57 | 275,3,0.4 58 | 280,3,0.4 59 | 285,3,0.4 60 | 290,3,0.4 61 | 295,3,0.4 62 | 300,3,0.4 63 | 305,3,0.5 64 | 310,3,0.5 65 | 315,3,0.5 66 | 320,3,0.5 67 | 325,3,0.5 68 | 330,3,0.5 69 | 335,3,0.5 70 | 340,3,0.5 71 | 345,3,0.5 72 | 350,3,0.5 73 | 355,3,0.5 74 | 360,3,0.5 75 | 365,3,0.5 76 | 370,3,0.5 77 | 375,3,0.5 78 | 380,3,0.5 79 | 385,3,0.5 80 | 390,3,0.5 81 | 395,3,0.5 82 | 400,3,0.5 83 | 405,3,0.5 84 | 410,3,0.5 85 | 415,3,0.5 86 | 420,3,0.5 87 | 425,3,0.5 88 | 430,3,0.5 89 | 435,3,0.5 90 | 440,3,0.5 91 | 445,3,0.5 92 | 450,3,0.5 93 | 455,3,0.5 94 | 460,3,0.5 95 | 465,3,0.5 96 | 470,3,0.5 97 | 475,3,0.5 98 | 480,3,0.5 99 | 485,3,0.5 100 | 490,3,0.5 101 | 495,3,0.5 102 | 500,3,0.5 103 | -------------------------------------------------------------------------------- /example_distillation/test.m: -------------------------------------------------------------------------------- 1 | addpath('../apm'); 2 | 3 | % Clear MATLAB 4 | clear all 5 | close all 6 | 7 | % Select server 8 | server = 'http://byu.apmonitor.com' 9 | 10 | % Set application name 11 | app = int2str(int32(rand()*10000)); 12 | 13 | % Clear previous application 14 | apm(server,app,'clear all'); 15 | 16 | % Load model file 17 | disp ('Load Model') 18 | apm_load(server,app,'distill.apm'); 19 | 20 | % Load time points for future predictions 21 | disp ('Load CSV File') 22 | csv_load(server,app,'horizon_ctl.csv'); 23 | 24 | % Load replay replay data for local use 25 | csv = csv_data('replay_ctl.csv'); 26 | 27 | % APM Variable Classification 28 | % class = FV, MV, SV, CV 29 | % F or FV = Fixed value - parameter may change to a new value every cycle 30 | % M or MV = Manipulated variable - independent variable over time horizon 31 | % S or SV = State variable - model variable for viewing 32 | % C or CV = Controlled variable - model variable for control 33 | % Names of each variable type in cell arrays 34 | % Same as listed in the model.apm file 35 | FVs = {'feed','x_feed','alpha','atray','acond','areb'}; 36 | MVs = {'rr','fbot','sp_x[1]','sp_x[32]'}; 37 | SVs = {'x[2]','x[5]','x[10]','x[15]','x[20]','x[25]','x[30]','x[31]'}; 38 | CVs = {'x[1]','x[32]'}; 39 | 40 | % Get number of each variable type 41 | n_FVs = size(FVs,2); 42 | n_MVs = size(MVs,2); 43 | n_SVs = size(SVs,2); 44 | n_CVs = size(CVs,2); 45 | 46 | % Set up variable classifications for data flow 47 | % Feedforwards - measured process disturbances 48 | for i = 1:n_FVs, 49 | apm_info(server,app,'FV',FVs(:,i)); 50 | end 51 | % Manipulated variables / parameters 52 | for i = 1:n_MVs, 53 | apm_info(server,app,'MV',MVs(:,i)); 54 | end 55 | % State variables (for display only) 56 | for i = 1:n_SVs, 57 | apm_info(server,app,'SV',SVs(:,i)); 58 | end 59 | % Controlled / Measured variables 60 | for i = 1:n_CVs, 61 | apm_info(server,app,'CV',CVs(:,i)); 62 | end 63 | 64 | % Options 65 | 66 | % time units (1=sec,2=min,3=hrs,etc) 67 | apm_option(server,app,'nlc.ctrl_units',2); 68 | apm_option(server,app,'nlc.hist_units',3); 69 | 70 | % set controlled variable error model type 71 | apm_option(server,app,'nlc.cv_type',1); 72 | apm_option(server,app,'nlc.ev_type',1); 73 | 74 | % controller mode (1=simulate, 2=predict, 3=control) 75 | apm_option(server,app,'nlc.reqctrlmode',1); 76 | 77 | % read discretization from CSV file 78 | apm_option(server,app,'nlc.csv_read',1); 79 | 80 | % turn on historization to see past results 81 | apm_option(server,app,'nlc.hist_hor',200); 82 | 83 | % set web plot update frequency 84 | apm_option(server,app,'nlc.web_plot_freq',10); 85 | 86 | % Controlled variable (c) 87 | apm_option(server,app,'x[1].sphi',0.95); 88 | apm_option(server,app,'x[1].splo',0.94); 89 | apm_option(server,app,'x[1].tau',20.0); 90 | apm_option(server,app,'x[1].fstatus',0); 91 | 92 | apm_option(server,app,'x[32].sphi',0.05); 93 | apm_option(server,app,'x[32].splo',0.04); 94 | apm_option(server,app,'x[32].tau',20.0); 95 | apm_option(server,app,'x[32].fstatus',0); 96 | 97 | % Manipulated variables (u) 98 | apm_option(server,app,'rr.upper',10); 99 | apm_option(server,app,'rr.dmax',0.2); 100 | apm_option(server,app,'rr.lower',1); 101 | apm_option(server,app,'rr.fstatus',0); 102 | 103 | apm_option(server,app,'fbot.upper',1); 104 | apm_option(server,app,'fbot.dmax',0.05); 105 | apm_option(server,app,'fbot.lower',0); 106 | apm_option(server,app,'fbot.fstatus',0); 107 | 108 | % Measured Disturbances 109 | apm_option(server,app,'feed.fstatus',1); 110 | apm_option(server,app,'x_feed.fstatus',1); 111 | 112 | % imode (1=ss, 2=mpu, 3=rto, 4=sim, 5=mhe, 6=nlc) 113 | apm_option(server,app,'nlc.imode',1); 114 | apm_option(server,app,'nlc.sensitivity',1); 115 | 116 | % steady state solution 117 | apm(server,app,'solve'); 118 | 119 | % imode (1=ss, 2=mpu, 3=rto, 4=sim, 5=mhe, 6=nlc) 120 | apm_option(server,app,'nlc.imode',6) 121 | apm_option(server,app,'nlc.sensitivity',0); 122 | 123 | blank_line = sprintf('\n'); 124 | for isim = 1:10, 125 | pause(0.1) 126 | 127 | disp(blank_line) 128 | disp(['--- Cycle ' num2str(isim) ' of 10 ---']) 129 | 130 | if (isim==2), 131 | % turn on controller 132 | apm_option(server,app,'nlc.reqctrlmode',3); 133 | % turn on overhead composition control 134 | apm_option(server,app,'rr.status',1); 135 | apm_option(server,app,'x[1].sphi',0.952); 136 | apm_option(server,app,'x[1].splo',0.952); 137 | apm_option(server,app,'x[1].status',1); 138 | apm_meas(server,app,'sp_x[1]',0.952); 139 | % turn on bottoms composition control 140 | apm_option(server,app,'fbot.status',1); 141 | apm_option(server,app,'x[32].sphi',0.019); 142 | apm_option(server,app,'x[32].splo',0.019); 143 | apm_option(server,app,'x[32].status',1); 144 | apm_meas(server,app,'sp_x[32]',0.019); 145 | end 146 | 147 | if (isim==70), 148 | % set point change 149 | apm_option(server,app,'x[1].sphi',0.9955); 150 | apm_option(server,app,'x[1].splo',0.9955); 151 | apm_option(server,app,'x[32].sphi',0.0095); 152 | apm_option(server,app,'x[32].splo',0.0095); 153 | apm_meas(server,app,'sp_x[1]',0.9955); 154 | apm_meas(server,app,'sp_x[32]',0.0095); 155 | end 156 | 157 | % FV measurements 158 | for i = 1:n_FVs, 159 | name = deblank(FVs(:,i)); 160 | value = csv_element(name,isim,csv); 161 | if (~isnan(value)), 162 | apm_meas(server,app,name,value); 163 | end 164 | end 165 | % MV measurements 166 | for i = 1:n_MVs, 167 | name = deblank(MVs(:,i)); 168 | value = csv_element(name,isim,csv); 169 | if (~isnan(value)), 170 | apm_meas(server,app,name,value); 171 | end 172 | end 173 | % CV measurements 174 | for i = 1:n_CVs, 175 | name = deblank(CVs(:,i)); 176 | value = csv_element(name,isim,csv); 177 | if (~isnan(value)), 178 | apm_meas(server,app,name,value); 179 | end 180 | end 181 | 182 | % Run NLC on APMonitor server 183 | apm(server,app,'solve'); 184 | 185 | if (isim==1), 186 | apm_web(server,app) 187 | end 188 | 189 | end 190 | -------------------------------------------------------------------------------- /example_hs71/hs71.apm: -------------------------------------------------------------------------------- 1 | Model 2 | Variables 3 | x[1] = 1, >=1, <=5 4 | x[2] = 5, >=1, <=5 5 | x[3] = 5, >=1, <=5 6 | x[4] = 1, >=1, <=5 7 | End Variables 8 | 9 | Equations 10 | x[1] * x[2] * x[3] * x[4] > 25 11 | x[1]^2 + x[2]^2 + x[3]^2 + x[4]^2 = 40 12 | 13 | minimize x[1] * x[4] * (x[1]+x[2]+x[3]) + x[3] 14 | End Equations 15 | End Model 16 | -------------------------------------------------------------------------------- /example_hs71/hs71.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/APMonitor/apm_matlab/ee47918ca71412ddf2f074b20b62eb693f1fcb6f/example_hs71/hs71.gif -------------------------------------------------------------------------------- /example_hs71/main.m: -------------------------------------------------------------------------------- 1 | addpath('../apm'); 2 | 3 | % Select server 4 | server = 'http://byu.apmonitor.com'; 5 | 6 | % Application name 7 | app = 'trial'; 8 | 9 | % Clear previous application 10 | apm(server,app,'clear all'); 11 | 12 | % Load model file 13 | apm_load(server,app,'hs71.apm'); 14 | 15 | % Option to select solver (1=APOPT, 2=BPOPT, 3=IPOPT) 16 | apm_option(server,app,'nlc.solver',3); 17 | 18 | % Solve on APM server 19 | apm(server,app,'solve') 20 | 21 | % Retrieve results 22 | disp('Results'); 23 | results = apm_sol(server,app) 24 | values = cell2mat(results(2:end,:)); 25 | 26 | % Display Results in Web Viewer 27 | url = apm_web_var(server,app); 28 | 29 | -------------------------------------------------------------------------------- /example_hs71/solution_trial.csv: -------------------------------------------------------------------------------- 1 | x[1], 1.000000E+00 2 | x[2], 4.743000E+00 3 | x[3], 3.821150E+00 4 | x[4], 1.379408E+00 5 | slk_1, 6.880146E-09 6 | -------------------------------------------------------------------------------- /example_id/myTest.m: -------------------------------------------------------------------------------- 1 | clear all; close all; clc 2 | 3 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4 | % Configuration 5 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6 | obj_scale = 1; 7 | % number of terms 8 | ny = 3; % output coefficients 9 | nu = 3; % input coefficients 10 | % number of inputs 11 | ni = 2; 12 | % number of outputs 13 | no = 2; 14 | % load data and parse into columns 15 | load test_data.csv 16 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 17 | 18 | % generate state space model 19 | addpath('../apm') 20 | sysd = apm_id(test_data,ni,nu,ny); -------------------------------------------------------------------------------- /example_id/test_data.csv: -------------------------------------------------------------------------------- 1 | 0,0,0,0,0 2 | 1,0,0,0,0 3 | 2,0,0,0,0 4 | 3,0,0,0,0 5 | 4,0,1,0,0 6 | 5,0,1,0,-0.663597651 7 | 6,0,1,5.902040104,-1.180408021 8 | 7,1,1,9.481808382,-1.582900342 9 | 8,1,1,12.83345562,-2.228160502 10 | 9,1,4.398737296,14.86633243,-2.73068962 11 | 10,1,7.217007674,16.09933454,-5.377453776 12 | 11,2,2.241276559,36.90667195,-9.308953375 13 | 12,2,9.838506268,67.34091286,-9.400723688 14 | 13,2,1.801104209,56.43324848,-14.51369827 15 | 14,2,6.190528646,94.65657003,-13.16208575 16 | 15,2,9.502873039,70.40311718,-15.02226061 17 | 16,2,1.781191495,81.59921349,-18.6690302 18 | 17,2,3.340694481,107.9395786,-16.38504748 19 | 18,2,2.53273966,78.3421435,-15.64116247 20 | 19,2,6.376394269,69.59464082,-14.52566732 21 | 20,2,6.376394269,59.5204305,-16.20755899 22 | 21,2,6.376394269,76.09551672,-17.51741754 23 | 22,2,6.376394269,86.14881469,-18.53753641 24 | 23,2,6.376394269,92.24644815,-19.33200578 25 | 24,2,6.376394269,95.94484979,-19.95073915 26 | 25,2,6.376394269,98.18804377,-20.43260918 27 | -------------------------------------------------------------------------------- /example_id/test_data.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/APMonitor/apm_matlab/ee47918ca71412ddf2f074b20b62eb693f1fcb6f/example_id/test_data.xlsx -------------------------------------------------------------------------------- /example_lti/linear.apm: -------------------------------------------------------------------------------- 1 | 2 | Objects 3 | linear = axb 4 | End Objects 5 | 6 | Connections 7 | x[1:10] = linear.x[1:10] 8 | End Connections 9 | 10 | Model 11 | Variables 12 | x[1:10] = 0 13 | End Variables 14 | 15 | Equations 16 | ! add any additional equations here 17 | End Equations 18 | End Model 19 | 20 | File linear.txt 21 | sparse, Ax>b ! dense or sparse, Ax=b or Axb 22 | 10 ! m=number of rows in A and b 23 | 10 ! n=number of columns in A or variables x 24 | End File 25 | 26 | File linear.a.txt 27 | 1 1 2.000000 28 | 2 2 2.000000 29 | 3 3 2.000000 30 | 4 4 2.000000 31 | 5 5 2.000000 32 | 6 6 2.000000 33 | 7 7 2.000000 34 | 8 8 2.000000 35 | 9 9 2.000000 36 | 10 10 2.000000 37 | End File 38 | 39 | File linear.b.txt 40 | 1 0.706046 41 | 2 0.031833 42 | 3 0.276923 43 | 4 0.046171 44 | 5 0.097132 45 | 6 0.823458 46 | 7 0.694829 47 | 8 0.317099 48 | 9 0.950222 49 | 10 0.034446 50 | End File 51 | -------------------------------------------------------------------------------- /example_lti/linear_test.m: -------------------------------------------------------------------------------- 1 | clear all; close all; clc 2 | 3 | addpath('../apm') 4 | 5 | %% generate linear model (A x = b) 6 | A = eye(10)*2; 7 | b = rand(10,1); 8 | apm_linear(A,b,'=','linear'); 9 | 10 | % solve linear system of equations 11 | s = 'http://byu.apmonitor.com'; 12 | a = 'lintest'; 13 | apm(s,a,'clear all'); 14 | apm_load(s,a,'linear.apm'); 15 | output = apm(s,a,'solve'); 16 | disp(output) 17 | y = apm_sol(s,a); 18 | apm_web(s,a); 19 | 20 | 21 | 22 | %% generate linear model (A x > b) 23 | A = eye(10)*2; 24 | b = rand(10,1); 25 | apm_linear(A,b,'>','linear'); 26 | 27 | % solve linear system of equations 28 | s = 'http://byu.apmonitor.com'; 29 | a = 'lintest'; 30 | apm(s,a,'clear all'); 31 | apm_load(s,a,'linear.apm'); 32 | apm_option(s,a,'nlc.solver',3); % switch to IPOPT 33 | output = apm(s,a,'solve'); 34 | disp(output) 35 | y = apm_sol(s,a); 36 | apm_web(s,a); -------------------------------------------------------------------------------- /example_lti/lti_test.m: -------------------------------------------------------------------------------- 1 | clear all; close all; clc 2 | 3 | addpath('../apm') 4 | 5 | % generate LTI model in MATLAB 6 | s = tf('s') 7 | G = [ 1/(2*s+1) 3/(4*s+1); 0 5/(6*s+1)]; 8 | sys = ss(G) 9 | 10 | % generate LTI model in APMonitor 11 | apm_lti(G); 12 | 13 | % model is now created, need to call apm_solve to solve it -------------------------------------------------------------------------------- /example_lti/solution_lintest.csv: -------------------------------------------------------------------------------- 1 | x[1], 3.620230E-01 2 | x[2], 2.491651E-02 3 | x[3], 1.474615E-01 4 | x[4], 3.208551E-02 5 | x[5], 5.756601E-02 6 | x[6], 4.207290E-01 7 | x[7], 3.564145E-01 8 | x[8], 1.675495E-01 9 | x[9], 4.841110E-01 10 | x[10], 2.622301E-02 11 | -------------------------------------------------------------------------------- /example_lti_regression/lti_regression.m: -------------------------------------------------------------------------------- 1 | clear all; close all; clc 2 | 3 | addpath('../apm') 4 | 5 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6 | % Configuration 7 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8 | % number of terms 9 | ny = 3; % output coefficients 10 | nu = 3; % input coefficients 11 | % number of inputs 12 | ni = 2; 13 | % number of outputs 14 | no = 2; 15 | % load data and parse into columns 16 | load data_no_headers.csv 17 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 18 | 19 | % generate state space model 20 | sysd = apm_id(data_no_headers,ni,nu,ny); 21 | -------------------------------------------------------------------------------- /example_minlp/minlp.apm: -------------------------------------------------------------------------------- 1 | ! Mixed Integer Nonlinear Programming Test Problem 2 | ! min p(x,y) 3 | ! s.t. Linear Constraints 4 | ! A*x <= b 5 | ! Aeq*x = beq 6 | ! lb <= x <= ub 7 | ! Nonlinear Constraints 8 | ! f(y) <= 0 9 | ! g(y) = 0 10 | ! lower <= y <= upper 11 | 12 | Constants 13 | n = 4 14 | End Constants 15 | 16 | Variables 17 | int_x[1:n] >=0, <=1 18 | End Variables 19 | 20 | Parameters 21 | A[1] = 5 22 | A[2] = 7 23 | A[3] = 4 24 | A[4] = 3 25 | b = 14 26 | c[1] = -8 27 | c[2] = -11 28 | c[3] = -6 29 | c[4] = -4 30 | End Parameters 31 | 32 | ! More variables, but not integers 33 | Variables 34 | y[1:n] = 1, >=1, <=5 35 | End Variables 36 | 37 | Intermediates 38 | x[1:n] = int_x[1:n] 39 | p[0] = 0 40 | p[1:n] = p[0:3] + A[1:n] * x[1:n] 41 | Ax = p[n] 42 | 43 | s[0] = 0 44 | s[1:n] = s[0:n-1] + c[1:n] * x[1:n] 45 | obj = s[n] 46 | End Intermediates 47 | 48 | Equations 49 | ! Linear or Nonlinear Contraints 50 | Ax <= b 51 | x[1]*x[2] + x[3]*x[4] = 1 52 | y[1]*y[2]*y[3]*y[4] > 25 53 | y[1]^2 + y[2]^2 + y[3]^2 + y[4]^2 = 40 54 | 55 | minimize obj + y[1]*y[4]*(y[1]+y[2]+y[3]) + y[3] 56 | End Equations 57 | -------------------------------------------------------------------------------- /example_minlp/minlp.m: -------------------------------------------------------------------------------- 1 | addpath('../apm'); 2 | 3 | % Select server 4 | server = 'http://byu.apmonitor.com'; 5 | 6 | % Application name 7 | app = 'mixed_integer'; 8 | 9 | % Clear previous application 10 | apm(server,app,'clear all'); 11 | 12 | % Load model file 13 | apm_load(server,app,'minlp.apm'); 14 | 15 | % Option to select solver (1=APOPT, 2=BPOPT, 3=IPOPT) 16 | apm_option(server,app,'nlc.solver',1); 17 | 18 | % Solve on APM server 19 | apm(server,app,'solve') 20 | 21 | % Retrieve results 22 | disp('Results'); 23 | y = apm_sol(server,app); 24 | disp(y) 25 | disp(y.x) 26 | 27 | % Display Results in Web Viewer 28 | url = apm_web_var(server,app); 29 | 30 | -------------------------------------------------------------------------------- /example_nlc/data.csv: -------------------------------------------------------------------------------- 1 | time 2 | 0 3 | 1 4 | 2 5 | 3 6 | 5 7 | 10 8 | 20 9 | 30 10 | -------------------------------------------------------------------------------- /example_nlc/main.m: -------------------------------------------------------------------------------- 1 | addpath('../apm'); 2 | 3 | % Clear MATLAB 4 | clc 5 | clear all 6 | close all 7 | 8 | % assign server and application names 9 | server = 'http://byu.apmonitor.com'; 10 | app = 'nlc_matlab' 11 | 12 | % Clear previous application 13 | apm(server,app,'clear all'); 14 | 15 | % load model variables and equations 16 | apm_load(server,app,'model.apm'); 17 | 18 | % Set up variable classifications for data flow 19 | 20 | % Feedforwards - measured process disturbances 21 | apm_info(server,app,'FV','tau'); 22 | % Manipulated variables (for controller design) 23 | apm_info(server,app,'MV','u'); 24 | % State variables (for display only) 25 | apm_info(server,app,'SV','x'); 26 | % Controlled variables (for controller design) 27 | apm_info(server,app,'CV','y'); 28 | 29 | % initialize time 30 | time = 0; 31 | 32 | % ---------------------------------------------------------- 33 | % Steady state solution 34 | % ---------------------------------------------------------- 35 | % imode = 1, steady state mode 36 | apm_option(server,app,'nlc.imode',1); 37 | % turn on sensitivity analysis 38 | apm_option(server,app,'nlc.sensitivity',1); 39 | 40 | % change the value of tau & u 41 | tau = 5; 42 | u = 10; 43 | 44 | % input value of u and tau 45 | apm_meas(server,app,'u',u); 46 | apm_meas(server,app,'tau',tau); 47 | 48 | % solve here for steady state initialization 49 | apm(server,app,'solve') 50 | 51 | % retrieve results 52 | x = apm_tag(server,app,'x.MODEL'); 53 | y = apm_tag(server,app,'y.MODEL'); 54 | 55 | % store steady state solution 56 | Xs = [time tau u x y]; 57 | % ---------------------------------------------------------- 58 | 59 | 60 | 61 | % ---------------------------------------------------------- 62 | % Dynamic simulation 63 | % ---------------------------------------------------------- 64 | % imode = 4, switch to dynamic simulation 65 | apm_option(server,app,'nlc.imode',4); 66 | % internal nodes in the collocation (between 2 and 6) 67 | apm_option(server,app,'nlc.nodes',3); 68 | % turn off sensitivity analysis 69 | apm_option(server,app,'nlc.sensitivity',0); 70 | % simulation step size for every 'solve' command 71 | apm_option(server,app,'nlc.ctrl_time',1.0); 72 | apm_option(server,app,'nlc.ctrl_hor',2); 73 | apm_option(server,app,'nlc.pred_hor',2); 74 | % simulation time units (option 2 = minutes) 75 | apm_option(server,app,'nlc.ctrl_units',2); 76 | % turn on history horizon to see results from web-interface 77 | apm_option(server,app,'nlc.hist_hor',30); 78 | apm_option(server,app,'nlc.hist_units',2); 79 | % turn off measurement biasing of CV 80 | apm_option(server,app,'y.FSTATUS',0); 81 | 82 | % step the value of u 83 | u = 20; 84 | apm_meas(server,app,'u',u); 85 | 86 | % simulate with APM 87 | for i = 1:10, 88 | % increment time 89 | time = time + 1.0; 90 | 91 | % Run APMonitor 92 | apm(server,app,'solve') 93 | 94 | % Read APM output 95 | x = apm_tag(server,app,'x.MODEL'); 96 | y = apm_tag(server,app,'y.MODEL'); 97 | 98 | Xs = [Xs; time tau u x y]; 99 | end 100 | 101 | 102 | % ---------------------------------------------------------- 103 | % Steady state solution for new starting point 104 | % ---------------------------------------------------------- 105 | % imode = 1, steady state mode 106 | apm_option(server,app,'nlc.imode',1); 107 | apm(server,app,'solve') 108 | 109 | % increment time to show SS solution results 110 | time = time+1; 111 | 112 | % retrieve results 113 | x = apm_tag(server,app,'x.MODEL'); 114 | y = apm_tag(server,app,'y.MODEL'); 115 | 116 | % store steady state solution 117 | Xs = [Xs; time tau u x y]; 118 | % ---------------------------------------------------------- 119 | 120 | 121 | % ---------------------------------------------------------- 122 | % Nonlinear control with L2 Error model 123 | % ---------------------------------------------------------- 124 | % imode = 6, switch to nonlinear control mode 125 | apm_option(server,app,'nlc.imode',6); 126 | % request control mode (1=simulate, 2=predict, 3=control) 127 | apm_option(server,app,'nlc.reqctrlmode',3); 128 | % use squared error model type 129 | apm_option(server,app,'nlc.cv_type',2); 130 | % CV set-point 131 | apm_option(server,app,'y.SP',10); 132 | % set reference trajectory speed 133 | apm_option(server,app,'y.TAU',6); 134 | % turn off measurement biasing of CV 135 | apm_option(server,app,'y.FSTATUS',0); 136 | apm_option(server,app,'y.BIAS',0); 137 | % turn ON the status of the MV and CV 138 | apm_option(server,app,'u.STATUS',1); 139 | apm_option(server,app,'y.STATUS',1); 140 | % add a delta movement constraint to the MV 141 | apm_option(server,app,'u.DMAX',10); 142 | 143 | % set up time horizon 144 | apm_option(server,app,'nlc.csv_read',1); 145 | 146 | % load time horizon 147 | csv_load(server,app,'data.csv'); 148 | 149 | % nonlinear control with APM 150 | for i = 1:15, 151 | % increment time 152 | time = time + 1; 153 | 154 | % Run APMonitor 155 | apm(server,app,'solve') 156 | 157 | % Read APM output 158 | u = apm_tag(server,app,'u.NEWVAL'); 159 | x = apm_tag(server,app,'x.MODEL'); 160 | y = apm_tag(server,app,'y.MODEL'); 161 | 162 | Xs = [Xs; time tau u x y]; 163 | end 164 | 165 | % ---------------------------------------------------------- 166 | % Nonlinear control with L1 Error model 167 | % ---------------------------------------------------------- 168 | % controller coldstart (start with steady state solution) 169 | apm_option(server,app,'nlc.coldstart',1); 170 | % use L1 (abs value) error model type 171 | apm_option(server,app,'nlc.cv_type',1); 172 | % CV set-point high and low for controller dead-band 173 | apm_option(server,app,'y.SPHI',10.5); 174 | apm_option(server,app,'y.SPLO',9.5); 175 | for i = 1:15, 176 | % increment time 177 | time = time + 1; 178 | 179 | % Run APMonitor 180 | apm(server,app,'solve') 181 | 182 | % Read APM output 183 | u = apm_tag(server,app,'u.NEWVAL'); 184 | x = apm_tag(server,app,'x.MODEL'); 185 | y = apm_tag(server,app,'y.MODEL'); 186 | 187 | Xs = [Xs; time tau u x y]; 188 | end 189 | 190 | 191 | figure(1) 192 | 193 | subplot(2,1,1); 194 | % plot tau 195 | plot(Xs(:,1),Xs(:,2),'g--'); 196 | hold on; 197 | % plot u 198 | plot(Xs(:,1),Xs(:,3),'r-'); 199 | xlabel('Time (min)') 200 | ylabel('Inputs') 201 | legend('tau (FV)','u (MV)'); 202 | % get min and max values for axis adjustment 203 | x_min = 0; 204 | x_max = max(Xs(:,1)) + 1; 205 | y_min = min(min(Xs(:,2:3))) - 1; 206 | y_max = max(max(Xs(:,2:3))) + 1; 207 | axis([x_min x_max y_min y_max]); 208 | title('Nonlinear Control with APMonitor') 209 | 210 | subplot(2,1,2); 211 | % plot x 212 | plot(Xs(:,1),Xs(:,4),'k-.'); 213 | hold on; 214 | % plot y 215 | plot(Xs(:,1),Xs(:,5),'b-'); 216 | y_min = min(min(Xs(:,4:5))) - 1; 217 | y_max = max(max(Xs(:,4:5))) + 1; 218 | axis([x_min x_max y_min y_max]); 219 | xlabel('Time (min)') 220 | ylabel('Outputs') 221 | legend('x (SV)','y (CV)'); 222 | 223 | % open web viewer 224 | apm_web(server,app); 225 | -------------------------------------------------------------------------------- /example_nlc/matlab_ctrl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/APMonitor/apm_matlab/ee47918ca71412ddf2f074b20b62eb693f1fcb6f/example_nlc/matlab_ctrl.png -------------------------------------------------------------------------------- /example_nlc/model.apm: -------------------------------------------------------------------------------- 1 | Model 2 | Parameters 3 | tau = 5 4 | u = 3, >=0, < 100 5 | End Parameters 6 | 7 | Variables 8 | x 9 | y 10 | End Variables 11 | 12 | Equations 13 | tau * $x + x = u 14 | y = 2 * x 15 | End Equations 16 | End Model 17 | -------------------------------------------------------------------------------- /example_pendulum/pendulum.apm: -------------------------------------------------------------------------------- 1 | ! Pendulum - Index 3 DAE 2 | ! http://apmonitor.com/wiki/index.php/Apps/PendulumMotion 3 | Model pend 4 | Parameters 5 | m = 1 ! mass of pendulum 6 | g = 9.81 ! gravitational constant 7 | s = 1 ! length of pendulum 8 | End Parameters 9 | 10 | Variables 11 | x = 0 ! horizontal position from pivot point 12 | y = -s ! vertical position from pivot point 13 | v = 1 ! horizontal velocity 14 | w = 0 ! vertical velocity 15 | lam ! intial condition: m*(1+s*g)/2*s^2 16 | End Variables 17 | 18 | Equations 19 | x^2 + y^2 = s^2 20 | $x = v 21 | $y = w 22 | m*$v = -2*x*lam 23 | m*$w = -m*g - 2*y*lam 24 | End Equations 25 | End Model -------------------------------------------------------------------------------- /example_pendulum/pendulum.m: -------------------------------------------------------------------------------- 1 | % Add APM functions to path 2 | addpath('../apm'); 3 | 4 | % Clear MATLAB 5 | clear all 6 | close all 7 | 8 | % Select server 9 | server = 'http://xps.apmonitor.com'; 10 | 11 | % Application name 12 | app = 'pendulum'; 13 | 14 | % Clear previous application 15 | apm(server,app,'clear all'); 16 | 17 | % Load plant data data 18 | csv = csv_data('replay.csv'); 19 | 20 | % Load model file and time horizon csv info 21 | apm_load(server,app,'pendulum.apm'); 22 | 23 | % Fixed variables 24 | FVs = ['pend.g']; 25 | 26 | % Manipulated variables 27 | MVs = ['pend.m'; 28 | 'pend.s']; 29 | 30 | SVs = ['pend.lam']; 31 | 32 | CVs = ['pend.x'; 33 | 'pend.y'; 34 | 'pend.v'; 35 | 'pend.w']; 36 | 37 | % Get number of each variable type 38 | n_FVs = size(FVs,1); 39 | n_MVs = size(MVs,1); 40 | n_SVs = size(SVs,1); 41 | n_CVs = size(CVs,1); 42 | 43 | % Set up variable classifications for data flow 44 | % Feedforwards - measured process disturbances 45 | for i = 1:n_FVs, 46 | apm_info(server,app,'FV',FVs(i,:)); 47 | end 48 | % Manipulated variables / parameters 49 | for i = 1:n_MVs, 50 | apm_info(server,app,'MV',MVs(i,:)); 51 | end 52 | % State variables (for display only) 53 | for i = 1:n_SVs, 54 | apm_info(server,app,'SV',SVs(i,:)); 55 | end 56 | % Controlled / Measured variables 57 | for i = 1:n_CVs, 58 | apm_info(server,app,'CV',CVs(i,:)); 59 | end 60 | 61 | % ----------------------------------------------------------------- 62 | % simulation step size for every 'solve' command 63 | next_row_interval = 1; % the next row interval for skipping over plant data 64 | % for a more course replay 65 | collection_interval = 0.1; % time interval for each plant data row 66 | interval = next_row_interval * collection_interval; 67 | % imode = 5, MHE mode 68 | apm_option(server,app,'nlc.imode',5); 69 | % estimated variable type (1=L1 norm, 2=Squared error objective) 70 | apm_option(server,app,'nlc.ev_type',2); 71 | % csv_read = 0 (OFF) - don't read horizon info from pendulum.csv 72 | apm_option(server,app,'nlc.csv_read',0); 73 | horizon = 21; 74 | apm_option(server,app,'nlc.ctrl_hor',horizon); 75 | apm_option(server,app,'nlc.pred_hor',horizon); 76 | apm_option(server,app,'nlc.ctrl_time',interval); 77 | apm_option(server,app,'nlc.pred_time',interval); 78 | % nodes = 3, internal nodes in the collocation structure (2-6) 79 | apm_option(server,app,'nlc.nodes',3); 80 | % time units (1=sec,2=min,3=hrs,etc) 81 | apm_option(server,app,'nlc.ctrl_units',1); 82 | apm_option(server,app,'nlc.hist_units',1); 83 | % set trending horizons for web-viewer 84 | apm_option(server,app,'nlc.hist_hor',200); 85 | % calculate initial conditions - OFF 86 | apm_option(server,app,'nlc.icd_calc',0); 87 | % set horizons 88 | apm_option(server,app,'nlc.hist_hor',200); 89 | % turn sensitivity calc off 90 | apm_option(server,app,'nlc.sensitivity',0); 91 | 92 | % use measurement for x position 93 | apm_option(server,app,'pend.x.FSTATUS',1); 94 | apm_option(server,app,'pend.x.WMEAS',50); 95 | apm_option(server,app,'pend.x.WMODEL',5); 96 | 97 | % determine mass and length of pendulum 98 | apm_option(server,app,'pend.s.STATUS',1); 99 | apm_option(server,app,'pend.s.LOWER',0.1); 100 | apm_option(server,app,'pend.s.UPPER',10); 101 | apm_option(server,app,'pend.s.MV_STEP_HOR',horizon); 102 | 103 | apm_option(server,app,'pend.m.STATUS',1); 104 | apm_option(server,app,'pend.m.LOWER',0.1); 105 | apm_option(server,app,'pend.m.UPPER',20); 106 | apm_option(server,app,'pend.m.MV_STEP_HOR',horizon); 107 | 108 | % MHE with APM 109 | row = 0; 110 | time = 0; 111 | for isim = 1:100, 112 | tic 113 | 114 | % row for data access 115 | row = row + next_row_interval; 116 | 117 | % store time values 118 | Xm(isim,1) = time; 119 | 120 | % FV measurements 121 | for i = 1:n_FVs, 122 | name = strtrim(FVs(i,:)); 123 | value = csv_element(name,row,csv); 124 | if (~isnan(value)), 125 | apm_meas(server,app,name,value); 126 | % get column number 127 | col = csv_lookup(name,csv); 128 | % store measured value 129 | if(col>=1), Xm(isim,col) = value;, end; 130 | end 131 | end 132 | % MV measurements 133 | for i = 1:n_MVs, 134 | name = strtrim(MVs(i,:)); 135 | value = csv_element(name,row,csv); 136 | if (~isnan(value)), 137 | apm_meas(server,app,name,value); 138 | % get column number 139 | col = csv_lookup(name,csv); 140 | % store measured value 141 | if(col>=1), Xm(isim,col) = value;, end; 142 | end 143 | end 144 | % CV measurements 145 | for i = 1:n_CVs, 146 | name = strtrim(CVs(i,:)); 147 | value = csv_element(name,row,csv); 148 | if (~isnan(value)), 149 | apm_meas(server,app,name,value); 150 | % get column number 151 | col = csv_lookup(name,csv); 152 | % store measured value 153 | if(col>=1), Xm(isim,col) = value;, end; 154 | end 155 | end 156 | disp('Input measurements time') 157 | toc 158 | 159 | tic 160 | % Run APMonitor 161 | apm(server,app,'solve') 162 | 163 | disp('Overall solve time') 164 | toc 165 | 166 | tic 167 | % SV predictions 168 | for i = 1:n_SVs, 169 | name = strtrim(SVs(i,:)); 170 | value = apm_tag(server,app,[name '.MODEL']); 171 | Xs(isim,i) = value; 172 | end 173 | % CV predictions 174 | for i = 1:n_CVs, 175 | name = strtrim(CVs(i,:)); 176 | value = apm_tag(server,app,[name '.MODEL']); 177 | % get column number 178 | col = csv_lookup(name,csv); 179 | % store results 180 | Xc(isim,i) = value; 181 | end 182 | disp(['Store results time for cycle ' num2str(isim)]) 183 | toc 184 | 185 | % for Matlab trends 186 | time = time + interval; 187 | 188 | end 189 | 190 | 191 | 192 | plot_all; 193 | 194 | 195 | -------------------------------------------------------------------------------- /example_pendulum/plot_all.m: -------------------------------------------------------------------------------- 1 | % Plot results 2 | Xt = Xm(:,1); 3 | 4 | i_fig = 0; 5 | 6 | if (0), 7 | for i = 1:n_FVs 8 | name = strtrim(FVs(i,:)); 9 | % get column number 10 | col = csv_lookup(name,csv); 11 | if (col>=1), 12 | name = strrep(name,'_',' '); 13 | i_fig = i_fig + 1; 14 | figure(i_fig); 15 | plot(Xt,Xm(:,col)) 16 | xlabel('Time (hr)') 17 | ylabel(name) 18 | legend('Meas') 19 | title(['FV: ' name]) 20 | end 21 | end 22 | end 23 | 24 | if (1), 25 | for i = 1:n_MVs 26 | name = strtrim(MVs(i,:)); 27 | % get column number 28 | col = csv_lookup(name,csv); 29 | if (col>=1), 30 | name = strrep(name,'_',' '); 31 | i_fig = i_fig + 1; 32 | figure(i_fig); 33 | plot(Xt,Xm(:,col)) 34 | xlabel('Time (hr)') 35 | ylabel(name) 36 | legend('Meas') 37 | title(['MV: ' name]) 38 | end 39 | end 40 | end 41 | 42 | if (0), 43 | for i = 1:n_SVs 44 | name = strtrim(SVs(i,:)); 45 | name = strrep(name,'_',' '); 46 | i_fig = i_fig + 1; 47 | figure(i_fig); 48 | plot(Xt,Xs(:,i)) 49 | xlabel('Time (hr)') 50 | ylabel(name) 51 | legend('Model') 52 | title(['SV: ' name]) 53 | end 54 | end 55 | 56 | if(1), 57 | for i = 1:n_CVs 58 | name = strtrim(CVs(i,:)); 59 | % get column number 60 | col = csv_lookup(name,csv); 61 | i_fig = i_fig + 1; 62 | figure(i_fig); 63 | name = strrep(name,'_',' '); 64 | if (col>=1), 65 | plot(Xt,Xc(:,i),'b-') 66 | hold on; 67 | plot(Xt,Xm(:,col),'r.-') 68 | xlabel('Time (hr)') 69 | ylabel(name) 70 | legend('Model','Meas') 71 | title(['CV: ' name]) 72 | else 73 | plot(Xt,Xc(:,i),'b-') 74 | xlabel('Time (hr)') 75 | ylabel(name) 76 | legend('Model') 77 | title(['CV: ' name]) 78 | end 79 | end 80 | end 81 | -------------------------------------------------------------------------------- /example_pendulum/replay.csv: -------------------------------------------------------------------------------- 1 | time,pend.x 2 | 0,0 3 | 0.1,0.062413811 4 | 0.2,0.12233938 5 | 0.3,0.177387665 6 | 0.4,0.225364063 7 | 0.5,0.264355906 8 | 0.6,0.292808715 9 | 0.7,0.309588163 10 | 0.8,0.314025309 11 | 0.9,0.305943256 12 | 1,0.285664212 13 | 1.1,0.253996636 14 | 1.2,0.212203017 15 | 1.3,0.161949532 16 | 1.4,0.105239631 17 | 1.5,0.044334158 18 | 1.6,-0.018338778 19 | 1.7,-0.080280605 20 | 1.8,-0.139021897 21 | 1.9,-0.192220826 22 | 2,-0.237756516 23 | 2.1,-0.273813604 24 | 2.2,-0.298954608 25 | 2.3,-0.312177236 26 | 2.4,-0.312954342 27 | 2.5,-0.301254946 28 | 2.6,-0.277545466 29 | 2.7,-0.242771124 30 | 2.8,-0.198318263 31 | 2.9,-0.145959079 32 | 3,-0.087780968 33 | 3.1,-0.026103306 34 | 3.2,0.036615013 35 | 3.3,0.097873606 36 | 3.4,0.155230287 37 | 3.5,0.206398427 38 | 3.6,0.249338113 39 | 3.7,0.282337475 40 | 3.8,0.304080933 41 | 3.9,0.313701644 42 | 4,0.31081606 43 | 4.1,0.295539221 44 | 4.2,0.268480165 45 | 4.3,0.230717653 46 | 4.4,0.183757156 47 | 4.5,0.129470841 48 | 4.6,0.070022932 49 | 4.7,0.007783429 50 | 4.8,-0.054766374 51 | 4.9,-0.115132814 52 | 5,-0.170909273 53 | 5.1,-0.219872118 54 | 5.2,-0.260069355 55 | 5.3,-0.289898449 56 | 5.4,-0.308170205 57 | 5.5,-0.314156189 58 | 5.6,-0.307617756 59 | 5.7,-0.288815574 60 | 5.8,-0.258499227 61 | 5.9,-0.217877331 62 | 6,-0.168569354 63 | 6.1,-0.112541048 64 | 6.2,-0.052026086 65 | 6.3,0.010562992 66 | 6.4,0.072730957 67 | 6.5,0.131999368 68 | 6.6,0.18600538 69 | 6.7,0.232595946 70 | 6.8,0.269913645 71 | 6.9,0.296470738 72 | 7,0.311208479 73 | 7.1,0.31353932 74 | 7.2,0.303370338 75 | 7.3,0.281106937 76 | 7.4,0.24763669 77 | 7.5,0.20429395 78 | 7.6,0.152806655 79 | 7.7,0.09522744 80 | 7.8,0.033851808 81 | 7.9,-0.028873389 82 | 8,-0.090447494 83 | 8.1,-0.148415744 84 | 8.2,-0.200467127 85 | 8.3,-0.244526517 86 | 8.4,-0.278837407 87 | 8.5,-0.30203193 88 | 8.6,-0.313185392 89 | 8.7,-0.311853142 90 | 8.8,-0.29808829 91 | 8.9,-0.2724396 92 | 9,-0.235929602 93 | 9.1,-0.190013835 94 | 9.2,-0.136522817 95 | 9.3,-0.077589064 96 | 9.4,-0.015562081 97 | 9.5,0.047085314 98 | 9.6,0.107855566 99 | 9.7,0.164325957 100 | 9.8,0.21424519 101 | 9.9,0.255623144 102 | 10,0.286810209 103 | -------------------------------------------------------------------------------- /example_pendulum/test.m: -------------------------------------------------------------------------------- 1 | % Add APM functions to path 2 | addpath('../apm'); 3 | 4 | % Clear MATLAB 5 | clear all 6 | close all 7 | 8 | % Select server 9 | server = 'http://byu.apmonitor.com'; 10 | 11 | % Application name 12 | app = 'pendulum'; 13 | 14 | % Clear previous application 15 | apm(server,app,'clear all'); 16 | 17 | % Load plant data data 18 | csv = csv_data('replay.csv'); 19 | 20 | % Load model file and time horizon csv info 21 | apm_load(server,app,'pendulum.apm'); 22 | 23 | % Fixed variables 24 | FVs = ['pend.g']; 25 | 26 | % Manipulated variables 27 | MVs = ['pend.m'; 28 | 'pend.s']; 29 | 30 | SVs = ['pend.lam']; 31 | 32 | CVs = ['pend.x'; 33 | 'pend.y'; 34 | 'pend.v'; 35 | 'pend.w']; 36 | 37 | % Get number of each variable type 38 | n_FVs = size(FVs,1); 39 | n_MVs = size(MVs,1); 40 | n_SVs = size(SVs,1); 41 | n_CVs = size(CVs,1); 42 | 43 | % Set up variable classifications for data flow 44 | % Feedforwards - measured process disturbances 45 | for i = 1:n_FVs, 46 | apm_info(server,app,'FV',FVs(i,:)); 47 | end 48 | % Manipulated variables / parameters 49 | for i = 1:n_MVs, 50 | apm_info(server,app,'MV',MVs(i,:)); 51 | end 52 | % State variables (for display only) 53 | for i = 1:n_SVs, 54 | apm_info(server,app,'SV',SVs(i,:)); 55 | end 56 | % Controlled / Measured variables 57 | for i = 1:n_CVs, 58 | apm_info(server,app,'CV',CVs(i,:)); 59 | end 60 | 61 | % ----------------------------------------------------------------- 62 | % simulation step size for every 'solve' command 63 | next_row_interval = 1; % the next row interval for skipping over plant data 64 | % for a more course replay 65 | collection_interval = 0.1; % time interval for each plant data row 66 | interval = next_row_interval * collection_interval; 67 | % imode = 5, MHE mode 68 | apm_option(server,app,'nlc.imode',5); 69 | % estimated variable type (1=L1 norm, 2=Squared error objective) 70 | apm_option(server,app,'nlc.ev_type',2); 71 | % csv_read = 0 (OFF) - don't read horizon info from pendulum.csv 72 | apm_option(server,app,'nlc.csv_read',0); 73 | horizon = 21; 74 | apm_option(server,app,'nlc.ctrl_hor',horizon); 75 | apm_option(server,app,'nlc.pred_hor',horizon); 76 | apm_option(server,app,'nlc.ctrl_time',interval); 77 | apm_option(server,app,'nlc.pred_time',interval); 78 | % nodes = 3, internal nodes in the collocation structure (2-6) 79 | apm_option(server,app,'nlc.nodes',3); 80 | % time units (1=sec,2=min,3=hrs,etc) 81 | apm_option(server,app,'nlc.ctrl_units',1); 82 | apm_option(server,app,'nlc.hist_units',1); 83 | % set trending horizons for web-viewer 84 | apm_option(server,app,'nlc.hist_hor',200); 85 | % calculate initial conditions - OFF 86 | apm_option(server,app,'nlc.icd_calc',0); 87 | % set horizons 88 | apm_option(server,app,'nlc.hist_hor',200); 89 | % turn sensitivity calc off 90 | apm_option(server,app,'nlc.sensitivity',0); 91 | 92 | % use measurement for x position 93 | apm_option(server,app,'pend.x.FSTATUS',1); 94 | apm_option(server,app,'pend.x.WMEAS',50); 95 | apm_option(server,app,'pend.x.WMODEL',5); 96 | 97 | % determine mass and length of pendulum 98 | apm_option(server,app,'pend.s.STATUS',1); 99 | apm_option(server,app,'pend.s.LOWER',0.1); 100 | apm_option(server,app,'pend.s.UPPER',10); 101 | apm_option(server,app,'pend.s.MV_STEP_HOR',horizon); 102 | 103 | apm_option(server,app,'pend.m.STATUS',1); 104 | apm_option(server,app,'pend.m.LOWER',0.1); 105 | apm_option(server,app,'pend.m.UPPER',20); 106 | apm_option(server,app,'pend.m.MV_STEP_HOR',horizon); 107 | 108 | % MHE with APM 109 | row = 0; 110 | time = 0; 111 | for isim = 1:20, 112 | tic 113 | 114 | % row for data access 115 | row = row + next_row_interval; 116 | 117 | % store time values 118 | Xm(isim,1) = time; 119 | 120 | % FV measurements 121 | for i = 1:n_FVs, 122 | name = strtrim(FVs(i,:)); 123 | value = csv_element(name,row,csv); 124 | if (~isnan(value)), 125 | apm_meas(server,app,name,value); 126 | % get column number 127 | col = csv_lookup(name,csv); 128 | % store measured value 129 | if(col>=1), Xm(isim,col) = value;, end; 130 | end 131 | end 132 | % MV measurements 133 | for i = 1:n_MVs, 134 | name = strtrim(MVs(i,:)); 135 | value = csv_element(name,row,csv); 136 | if (~isnan(value)), 137 | apm_meas(server,app,name,value); 138 | % get column number 139 | col = csv_lookup(name,csv); 140 | % store measured value 141 | if(col>=1), Xm(isim,col) = value;, end; 142 | end 143 | end 144 | % CV measurements 145 | for i = 1:n_CVs, 146 | name = strtrim(CVs(i,:)); 147 | value = csv_element(name,row,csv); 148 | if (~isnan(value)), 149 | apm_meas(server,app,name,value); 150 | % get column number 151 | col = csv_lookup(name,csv); 152 | % store measured value 153 | if(col>=1), Xm(isim,col) = value;, end; 154 | end 155 | end 156 | disp('Input measurements time') 157 | toc 158 | 159 | tic 160 | % Run APMonitor 161 | apm(server,app,'solve') 162 | 163 | disp('Overall solve time') 164 | toc 165 | 166 | tic 167 | % SV predictions 168 | for i = 1:n_SVs, 169 | name = strtrim(SVs(i,:)); 170 | value = apm_tag(server,app,[name '.MODEL']); 171 | Xs(isim,i) = value; 172 | end 173 | % CV predictions 174 | for i = 1:n_CVs, 175 | name = strtrim(CVs(i,:)); 176 | value = apm_tag(server,app,[name '.MODEL']); 177 | % get column number 178 | col = csv_lookup(name,csv); 179 | % store results 180 | Xc(isim,i) = value; 181 | end 182 | disp(['Store results time for cycle ' num2str(isim)]) 183 | toc 184 | 185 | % for Matlab trends 186 | time = time + interval; 187 | 188 | end 189 | 190 | 191 | 192 | plot_all; 193 | 194 | 195 | -------------------------------------------------------------------------------- /example_sbml_erbb/erbb.csv: -------------------------------------------------------------------------------- 1 | time,k116,k1,kd1,k1c,kd1c,kd1d,kd6,kd122,k122,k119 2 | 0,0.015,0,0.0033,800,1,0.1,0.00E+00,1,1.00E-04,0 3 | 90,0,0,0.0033,800,1,0.1,0.00E+00,1,1.00E-04,0 4 | 180,0,0,0.0033,800,1,0.1,0.00E+00,1,1.00E-04,0 5 | 270,0,0,0.0033,800,1,0.1,0.00E+00,1,1.00E-04,0 6 | 360,0,0,0.0033,800,1,0.1,0.00E+00,1,1.00E-04,0 7 | 450,0,0,0.0033,800,1,0.1,0.00E+00,1,1.00E-04,0 8 | 540,0,0,0.0033,800,1,0.1,0.00E+00,1,1.00E-04,0 9 | 630,0,0,0.0033,800,1,0.1,0.00E+00,1,1.00E-04,0 10 | 720,0,0,0.0033,800,1,0.1,0.00E+00,1,1.00E-04,0 11 | 810,0,0,0.0033,800,1,0.1,0.00E+00,1,1.00E-04,0 12 | 900,0,0,0.0033,800,1,0.1,0.00E+00,1,1.00E-04,0 13 | 990,0,0,0.0033,800,1,0.1,0.00E+00,1,1.00E-04,0 14 | 1080,0,0,0.0033,800,1,0.1,0.00E+00,1,1.00E-04,0 15 | 1170,0,0,0.0033,800,1,0.1,0.00E+00,1,1.00E-04,0 16 | 1260,0,0,0.0033,800,1,0.1,0.00E+00,1,1.00E-04,0 17 | 1350,0,0,0.0033,800,1,0.1,0.00E+00,1,1.00E-04,0 18 | 1440,0,0,0.0033,800,1,0.1,0.00E+00,1,1.00E-04,0 19 | 1530,0,0,0.0033,800,1,0.1,0.00E+00,1,1.00E-04,0 20 | 1620,0,0,0.0033,800,1,0.1,0.00E+00,1,1.00E-04,0 21 | 1710,0,0,0.0033,800,1,0.1,0.00E+00,1,1.00E-04,0 22 | 1798,0,0,0.0033,800,1,0.1,0.00E+00,1,1.00E-04,0 23 | 1800,0,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 24 | 1890,0,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 25 | 1980,0,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 26 | 2070,0,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 27 | 2160,0,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 28 | 2250,0,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 29 | 2340,0,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 30 | 2430,0,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 31 | 2520,0,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 32 | 2600,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 33 | 2690,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 34 | 2880,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 35 | 2970,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 36 | 3060,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 37 | 3150,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 38 | 3240,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 39 | 3330,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 40 | 3420,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 41 | 3510,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 42 | 3600,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 43 | 3690,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 44 | 3780,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 45 | 3870,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 46 | 3960,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 47 | 4050,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 48 | 4140,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 49 | 4230,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 50 | 4320,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 51 | 4410,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 52 | 4500,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 53 | 4590,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 54 | 4680,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 55 | 4770,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 56 | 4860,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 57 | 4950,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 58 | 5040,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 59 | 5130,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 60 | 5220,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 61 | 5310,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 62 | 5400,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 63 | 5490,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 64 | 5580,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 65 | 5670,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 66 | 5760,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 67 | 5850,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 68 | 5940,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 69 | 6030,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 70 | 6120,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 71 | 6210,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 72 | 6300,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 73 | 6390,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 74 | 6480,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 75 | 6570,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 76 | 6660,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 77 | 6750,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 78 | 6840,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 79 | 6930,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 80 | 7020,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 81 | 7110,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 82 | 7200,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 83 | 7290,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 84 | 7380,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 85 | 7470,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 86 | 7560,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 87 | 7650,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 88 | 7740,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 89 | 7830,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 90 | 7920,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 91 | 8010,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 92 | 8100,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 93 | 8190,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 94 | 8280,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 95 | 8370,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 96 | 8460,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 97 | 8550,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 98 | 8640,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 99 | 8730,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 100 | 8820,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 101 | 8910,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 102 | 9000,0.0150356,10000000,0.0033,0,0,0,5.00E-05,1,1.87E-08,10000000 103 | -------------------------------------------------------------------------------- /example_sbml_erbb/main.m: -------------------------------------------------------------------------------- 1 | % Clear MATLAB 2 | clear all; close all; clc 3 | 4 | % Add path to APM libraries 5 | addpath('../apm') 6 | 7 | % Solve ErbB model with dynamic sequential simulation 8 | y = apm_solve('erbb',7); 9 | 10 | % extract values for trending 11 | time = y.x.time; 12 | akt_pp = y.x.relakt_pp; 13 | erk_pp = y.x.relerk_pp; 14 | erb1_p = y.x.relerb1_p; 15 | 16 | % plot results 17 | figure(1) 18 | subplot(2,1,1); 19 | plot(time,akt_pp,'b-'); 20 | hold on; 21 | plot(time,erk_pp,'r-'); 22 | legend('AKT PP','ERK PP'); 23 | ylabel('Relative Value') 24 | subplot(2,1,2); 25 | plot(time,erb1_p,'g-'); 26 | ylabel('Relative Value'); 27 | legend('ERB1 P'); 28 | xlabel('Time (sec)'); 29 | -------------------------------------------------------------------------------- /example_sbml_vaccine/main.m: -------------------------------------------------------------------------------- 1 | % Clear MATLAB 2 | clear all; close all; 3 | 4 | % Add path to APM libraries 5 | addpath('../apm'); 6 | 7 | % Select server 8 | server = 'http://byu.apmonitor.com'; 9 | 10 | % Application 11 | app = 'vaccine'; 12 | 13 | % ----------- tau = 0.7 --------------------------- 14 | % Clear previous application 15 | apm(server,app,'clear all'); 16 | 17 | % load model variables and equations 18 | apm_load(server,app,'vaccine.apm'); 19 | 20 | % load data 21 | csv_load(server,app,'vaccine_0.7.csv'); 22 | 23 | % imode = 7, switch to sequential simulation 24 | apm_option(server,app,'nlc.imode',7); 25 | 26 | % change history horizon from the default of 100 27 | apm_option(server,app,'nlc.hist_hor',200); 28 | 29 | % change time units to seconds 30 | apm_option(server,app,'nlc.ctrl_units',1); 31 | 32 | % select solver (1=APOPT, 2=BPOPT, 3=IPOPT) 33 | apm_option(server,app,'nlc.solver',1); 34 | 35 | % Run APMonitor 36 | apm(server,app,'solve') 37 | 38 | % Retrieve solution (creates solution.csv locally) 39 | y = apm_sol(server,app); 40 | 41 | % Extract names 42 | names = y.names; 43 | 44 | % Extract values 45 | cc = y.values; 46 | 47 | % Time is always the first column 48 | time = cc(:,1); 49 | 50 | % extract values for trending 51 | index = find(strcmpi('strain1_frac',names)); strain1_frac = cc(:,index); 52 | index = find(strcmpi('strain2_frac',names)); strain2_frac = cc(:,index); 53 | index = find(strcmpi('V_frac',names)); V_frac = cc(:,index); 54 | % ----------- tau = 0.7 --------------------------- 55 | 56 | 57 | % ----------- tau = 0.9 --------------------------- 58 | % Clear previous application 59 | apm(server,app,'clear all'); 60 | 61 | % load model variables and equations 62 | apm_load(server,app,'vaccine.apm'); 63 | 64 | % load data 65 | csv_load(server,app,'vaccine_0.9.csv'); 66 | 67 | % imode = 7, switch to sequential simulation 68 | apm_option(server,app,'nlc.imode',7); 69 | 70 | % change history horizon from the default of 100 71 | apm_option(server,app,'nlc.hist_hor',200); 72 | 73 | % change time units to seconds 74 | apm_option(server,app,'nlc.ctrl_units',1); 75 | 76 | % select solver (1=APOPT, 2=BPOPT, 3=IPOPT) 77 | apm_option(server,app,'nlc.solver',1); 78 | 79 | % Run APMonitor 80 | apm(server,app,'solve') 81 | 82 | % Retrieve solution (creates solution.csv locally) 83 | y = apm_sol(server,app); 84 | 85 | % Extract names 86 | names = y.names; 87 | 88 | % Extract values 89 | cc = y.values; 90 | 91 | % Time is always the first column 92 | time = cc(:,1); 93 | 94 | % extract values for trending 95 | index = find(strcmpi('strain1_frac',names)); strain1_frac2 = cc(:,index); 96 | index = find(strcmpi('strain2_frac',names)); strain2_frac2 = cc(:,index); 97 | index = find(strcmpi('V_frac',names)); V_frac2 = cc(:,index); 98 | % ----------- tau = 0.9 --------------------------- 99 | 100 | 101 | % open web-viewer 102 | apm_web(server,app); 103 | 104 | % plot results 105 | figure(1) 106 | semilogy(time,strain1_frac,'r-'); 107 | hold on; 108 | semilogy(time,strain2_frac,'g-'); 109 | semilogy(time,V_frac,'b-'); 110 | semilogy(time,strain1_frac2,'r.'); 111 | hold on; 112 | semilogy(time,strain2_frac2,'g.'); 113 | semilogy(time,V_frac2,'b.'); 114 | xlabel('Time (sec)'); 115 | legend('strain 1 (tau=0.7)','strain 2 (tau=0.7)','V (tau=0.7)','strain 1 (tau=0.9)','strain 2 (tau=0.9)','V (tau=0.9)'); 116 | ylabel('fraction in population') 117 | -------------------------------------------------------------------------------- /example_sbml_vaccine/results.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/APMonitor/apm_matlab/ee47918ca71412ddf2f074b20b62eb693f1fcb6f/example_sbml_vaccine/results.png -------------------------------------------------------------------------------- /example_sbml_vaccine/vaccine.apm: -------------------------------------------------------------------------------- 1 | ! 2 | ! This file is automatically generated with 3 | ! the System Biology Format Converter (http://sbfc.sourceforge.net/) 4 | ! from an SBML file. 5 | ! 6 | 7 | ! 8 | ! Model name = Restif2007_Vaccination_Invasion 9 | ! 10 | ! is urn:miriam:biomodels.db:BIOMD0000000294 11 | ! is urn:miriam:biomodels.db:MODEL1012210000 12 | ! isDescribedBy urn:miriam:pubmed:17210532 13 | ! 14 | 15 | Model 16 | Parameters 17 | env=1.0! Compartment: id = env, name = environment, constant 18 | l_e=50.0 ! Parameter: id = l_e, name = life expectancy, constant 19 | R0=17.0 ! Parameter: id = R0, name = R0, constant 20 | p=1.0 ! Parameter: id = p, name = p, constant 21 | tau=0.9 ! Parameter: id = tau, name = tau, constant 22 | theta=0.5 ! Parameter: id = theta, name = theta, constant 23 | nu=0.5 ! Parameter: id = nu, name = nu, constant 24 | eta=0.5 ! Parameter: id = eta, name = eta, constant 25 | tInf=21.0 ! Parameter: id = tInf, name = infectious period (d), constant 26 | tImm=20.0 ! Parameter: id = tImm, name = immune period (yr), constant 27 | tImm_V=50.0 ! Parameter: id = tImm_V, name = vaccine immune period (yr), constant 28 | N=1.0 !Is not affected by rule or reaction ! Species: id = N, name = N; Compartment:env! Warning species is not changed by either rules or reactions 29 | End Parameters 30 | 31 | Variables 32 | t=0 33 | mu=1/l_e !Variable-From Rule:assignmentRule 34 | beta=R0*(gamma+mu) !Variable-From Rule:assignmentRule 35 | gamma=365/tInf !Variable-From Rule:assignmentRule 36 | sigma=1/tImm !Variable-From Rule:assignmentRule 37 | sigmaV=1/tImm_V !Variable-From Rule:assignmentRule 38 | strain1_frac=(I1+J1)/N !Variable-From Rule:assignmentRule 39 | strain2_frac=(I2+J2+Iv2)/N !Variable-From Rule:assignmentRule 40 | S_frac=S/N !Variable-From Rule:assignmentRule 41 | V_frac=V/N !Variable-From Rule:assignmentRule 42 | R_1_frac=(R1+R)/N !Variable-From Rule:assignmentRule 43 | R_2_frac=(R2+R)/N !Variable-From Rule:assignmentRule 44 | R_frac=R/N !Variable-From Rule:assignmentRule 45 | S=0.0588235 !init ! Species: id = S, name = S; Compartment:env, affected by kineticLaw 46 | I1=0.00176967 !init ! Species: id = I1, name = I1; Compartment:env, affected by kineticLaw 47 | I2=1.0E-6 !init ! Species: id = I2, name = I2; Compartment:env, affected by kineticLaw 48 | R1=0.439407 !init ! Species: id = R1, name = R1; Compartment:env, affected by kineticLaw 49 | R2=0.0 !init ! Species: id = R2, name = R2; Compartment:env, affected by kineticLaw 50 | V=0.9 !init ! Species: id = V, name = V; Compartment:env, affected by kineticLaw 51 | Iv2=0.5 !init ! Species: id = Iv2, name = Iv2; Compartment:env, affected by kineticLaw 52 | J2=0.0 !init ! Species: id = J2, name = J2; Compartment:env, affected by kineticLaw 53 | J1=0.0 !init ! Species: id = J1, name = J1; Compartment:env, affected by kineticLaw 54 | R=0.0 !init ! Species: id = R, name = R; Compartment:env, affected by kineticLaw 55 | lgstrain1_frac=log(strain1_frac) 56 | lgstrain2_frac=log(strain2_frac) 57 | lgVfrac=log(V_frac) 58 | End Variables 59 | 60 | Intermediates 61 | 62 | r1_1=mu*(1-p)*N ! Reaction: id = r1 ! name = Birth S (unvaccinated) 63 | r2_1=mu*p*N ! Reaction: id = r2 ! name = Birth V (vaccinated) 64 | r3=mu*S ! Reaction: id = r3 ! name = Death in S 65 | r4=mu*V ! Reaction: id = r4 ! name = Death in V 66 | r5=mu*I1 ! Reaction: id = r5 ! name = Death in I1 67 | r6=mu*I2 ! Reaction: id = r6 ! name = Death in I2 68 | r7=mu*Iv2 ! Reaction: id = r7 ! name = Death in Iv2 69 | r8=mu*R1 ! Reaction: id = r8 ! name = Death in R1 70 | r9=mu*R2 ! Reaction: id = r9 ! name = Death in R2 71 | r10=mu*J1 ! Reaction: id = r10 ! name = Death in J1 72 | r11=mu*J2 ! Reaction: id = r11 ! name = Death in J2 73 | r12=mu*R ! Reaction: id = r12 ! name = Death in Rp 74 | r13=beta*S*(I1+J1)/N ! Reaction: id = r13 ! name = Primary Infection with strain 1 75 | r14=beta*S*(I2+J2+Iv2)/N ! Reaction: id = r14 ! name = Primary Infection with strain 2 76 | r15=beta*(1-tau)*V*(I2+J2+Iv2)/N ! Reaction: id = r15 ! name = Primary Infection of V with strain 2 77 | r16=gamma*I1 ! Reaction: id = r16 ! name = Recovery (I1) 78 | r17=gamma*I2 ! Reaction: id = r17 ! name = Recovery (I2) 79 | r18=beta*(1-theta)*R2*(I1+J1)/N ! Reaction: id = r18 ! name = Secondary Infection with strain 1 80 | r19=beta*(1-theta)*R1*(I2+J2+Iv2)/N ! Reaction: id = r19 ! name = Secondary Infection with strain 2 81 | r20=gamma/(1-nu)*J1 ! Reaction: id = r20 ! name = Recovery (J1) 82 | r21=gamma/(1-nu)*J2 ! Reaction: id = r21 ! name = Recovery (J2) 83 | r22=gamma/(1-eta)*Iv2 ! Reaction: id = r22 ! name = Recovery (Iv2) 84 | r23=sigma*R1 ! Reaction: id = r23 ! name = Loss of Immunity (R1) 85 | r24=sigma*R2 ! Reaction: id = r24 ! name = Loss of Immunity (R2) 86 | r25=sigma*R ! Reaction: id = r25 ! name = Loss of Immunity (Rp) 87 | r26=sigmaV*V ! Reaction: id = r26 ! name = Loss of Immunity (V) 88 | End Intermediates 89 | 90 | Equations 91 | $t=1 92 | mu=1/l_e !Equation-From Rule ! assignmentRule: variable = mu 93 | beta=R0*(gamma+mu) !Equation-From Rule ! assignmentRule: variable = beta 94 | gamma=365/tInf !Equation-From Rule ! assignmentRule: variable = gamma 95 | sigma=1/tImm !Equation-From Rule ! assignmentRule: variable = sigma 96 | sigmaV=1/tImm_V !Equation-From Rule ! assignmentRule: variable = sigmaV 97 | strain1_frac=(I1+J1)/N !Equation-From Rule ! assignmentRule: variable = strain1_frac 98 | strain2_frac=(I2+J2+Iv2)/N !Equation-From Rule ! assignmentRule: variable = strain2_frac 99 | S_frac=S/N !Equation-From Rule ! assignmentRule: variable = S_frac 100 | V_frac=V/N !Equation-From Rule ! assignmentRule: variable = V_frac 101 | R_1_frac=(R1+R)/N !Equation-From Rule ! assignmentRule: variable = R_1_frac 102 | R_2_frac=(R2+R)/N !Equation-From Rule ! assignmentRule: variable = R_2_frac 103 | R_frac=R/N !Equation-From Rule ! assignmentRule: variable = R_frac 104 | $S=( 1.0 * r1_1) + (-1.0 * r3) + (-1.0 * r13) + (-1.0 * r14) + ( 1.0 * r23) + ( 1.0 * r24) + ( 1.0 * r25) + ( 1.0 * r26) 105 | $I1=(-1.0 * r5) + ( 1.0 * r13) + (-1.0 * r16) 106 | $I2=(-1.0 * r6) + ( 1.0 * r14) + (-1.0 * r17) 107 | $R1=(-1.0 * r8) + ( 1.0 * r16) + (-1.0 * r19) + (-1.0 * r23) 108 | $R2=(-1.0 * r9) + ( 1.0 * r17) + (-1.0 * r18) + (-1.0 * r24) 109 | $V=( 1.0 * r2_1) + (-1.0 * r4) + (-1.0 * r15) + (-1.0 * r26) 110 | $Iv2=(-1.0 * r7) + ( 1.0 * r15) + (-1.0 * r22) 111 | $J2=(-1.0 * r11) + ( 1.0 * r19) + (-1.0 * r21) 112 | $J1=(-1.0 * r10) + ( 1.0 * r18) + (-1.0 * r20) 113 | $R=(-1.0 * r12) + ( 1.0 * r20) + ( 1.0 * r21) + ( 1.0 * r22) + (-1.0 * r25) 114 | lgstrain1_frac=log(strain1_frac) 115 | lgstrain2_frac=log(strain2_frac) 116 | lgVfrac=log(V_frac) 117 | End Equations 118 | 119 | 120 | End Model 121 | !Parameter Count:12 122 | !Variable Count:23 123 | !Intermediate Count:26 124 | !Equation Count:23 125 | 126 | File *.plt 127 | New Trend 128 | lgstrain1_frac 129 | lgstrain2_frac 130 | lgVfrac 131 | End File 132 | -------------------------------------------------------------------------------- /example_sbml_vaccine/vaccine_0.7.csv: -------------------------------------------------------------------------------- 1 | time,tau 2 | 0,0.7 3 | 0.06,0.7 4 | 0.12,0.7 5 | 0.18,0.7 6 | 0.24,0.7 7 | 0.3,0.7 8 | 0.36,0.7 9 | 0.42,0.7 10 | 0.48,0.7 11 | 0.54,0.7 12 | 0.6,0.7 13 | 0.66,0.7 14 | 0.72,0.7 15 | 0.78,0.7 16 | 0.84,0.7 17 | 0.9,0.7 18 | 0.96,0.7 19 | 1.02,0.7 20 | 1.08,0.7 21 | 1.14,0.7 22 | 1.2,0.7 23 | 1.26,0.7 24 | 1.32,0.7 25 | 1.38,0.7 26 | 1.44,0.7 27 | 1.5,0.7 28 | 1.56,0.7 29 | 1.62,0.7 30 | 1.68,0.7 31 | 1.74,0.7 32 | 1.8,0.7 33 | 1.86,0.7 34 | 1.92,0.7 35 | 1.98,0.7 36 | 2.04,0.7 37 | 2.1,0.7 38 | 2.16,0.7 39 | 2.22,0.7 40 | 2.28,0.7 41 | 2.34,0.7 42 | 2.4,0.7 43 | 2.46,0.7 44 | 2.52,0.7 45 | 2.58,0.7 46 | 2.64,0.7 47 | 2.7,0.7 48 | 2.76,0.7 49 | 2.82,0.7 50 | 2.88,0.7 51 | 2.94,0.7 52 | 3,0.7 53 | 3.06,0.7 54 | 3.12,0.7 55 | 3.18,0.7 56 | 3.24,0.7 57 | 3.3,0.7 58 | 3.36,0.7 59 | 3.42,0.7 60 | 3.48,0.7 61 | 3.54,0.7 62 | 3.6,0.7 63 | 3.66,0.7 64 | 3.72,0.7 65 | 3.78,0.7 66 | 3.84,0.7 67 | 3.9,0.7 68 | 3.96,0.7 69 | 4.02,0.7 70 | 4.08,0.7 71 | 4.14,0.7 72 | 4.2,0.7 73 | 4.26,0.7 74 | 4.32,0.7 75 | 4.38,0.7 76 | 4.44,0.7 77 | 4.5,0.7 78 | 4.56,0.7 79 | 4.62,0.7 80 | 4.68,0.7 81 | 4.74,0.7 82 | 4.8,0.7 83 | 4.86,0.7 84 | 4.92,0.7 85 | 4.98,0.7 86 | 5.04,0.7 87 | 5.1,0.7 88 | 5.16,0.7 89 | 5.22,0.7 90 | 5.28,0.7 91 | 5.34,0.7 92 | 5.4,0.7 93 | 5.46,0.7 94 | 5.52,0.7 95 | 5.58,0.7 96 | 5.64,0.7 97 | 5.7,0.7 98 | 5.76,0.7 99 | 5.82,0.7 100 | 5.88,0.7 101 | 5.94,0.7 102 | 6,0.7 103 | -------------------------------------------------------------------------------- /example_sbml_vaccine/vaccine_0.9.csv: -------------------------------------------------------------------------------- 1 | time,tau 2 | 0,0.9 3 | 0.06,0.9 4 | 0.12,0.9 5 | 0.18,0.9 6 | 0.24,0.9 7 | 0.3,0.9 8 | 0.36,0.9 9 | 0.42,0.9 10 | 0.48,0.9 11 | 0.54,0.9 12 | 0.6,0.9 13 | 0.66,0.9 14 | 0.72,0.9 15 | 0.78,0.9 16 | 0.84,0.9 17 | 0.9,0.9 18 | 0.96,0.9 19 | 1.02,0.9 20 | 1.08,0.9 21 | 1.14,0.9 22 | 1.2,0.9 23 | 1.26,0.9 24 | 1.32,0.9 25 | 1.38,0.9 26 | 1.44,0.9 27 | 1.5,0.9 28 | 1.56,0.9 29 | 1.62,0.9 30 | 1.68,0.9 31 | 1.74,0.9 32 | 1.8,0.9 33 | 1.86,0.9 34 | 1.92,0.9 35 | 1.98,0.9 36 | 2.04,0.9 37 | 2.1,0.9 38 | 2.16,0.9 39 | 2.22,0.9 40 | 2.28,0.9 41 | 2.34,0.9 42 | 2.4,0.9 43 | 2.46,0.9 44 | 2.52,0.9 45 | 2.58,0.9 46 | 2.64,0.9 47 | 2.7,0.9 48 | 2.76,0.9 49 | 2.82,0.9 50 | 2.88,0.9 51 | 2.94,0.9 52 | 3,0.9 53 | 3.06,0.9 54 | 3.12,0.9 55 | 3.18,0.9 56 | 3.24,0.9 57 | 3.3,0.9 58 | 3.36,0.9 59 | 3.42,0.9 60 | 3.48,0.9 61 | 3.54,0.9 62 | 3.6,0.9 63 | 3.66,0.9 64 | 3.72,0.9 65 | 3.78,0.9 66 | 3.84,0.9 67 | 3.9,0.9 68 | 3.96,0.9 69 | 4.02,0.9 70 | 4.08,0.9 71 | 4.14,0.9 72 | 4.2,0.9 73 | 4.26,0.9 74 | 4.32,0.9 75 | 4.38,0.9 76 | 4.44,0.9 77 | 4.5,0.9 78 | 4.56,0.9 79 | 4.62,0.9 80 | 4.68,0.9 81 | 4.74,0.9 82 | 4.8,0.9 83 | 4.86,0.9 84 | 4.92,0.9 85 | 4.98,0.9 86 | 5.04,0.9 87 | 5.1,0.9 88 | 5.16,0.9 89 | 5.22,0.9 90 | 5.28,0.9 91 | 5.34,0.9 92 | 5.4,0.9 93 | 5.46,0.9 94 | 5.52,0.9 95 | 5.58,0.9 96 | 5.64,0.9 97 | 5.7,0.9 98 | 5.76,0.9 99 | 5.82,0.9 100 | 5.88,0.9 101 | 5.94,0.9 102 | 6,0.9 103 | -------------------------------------------------------------------------------- /example_thermostat/heater.apm: -------------------------------------------------------------------------------- 1 | Parameters 2 | t_outside = 0 3 | int_heater = 0 , <= 1 , >= 0 4 | ua = 5 5 | 6 | Variables 7 | t_inside 8 | 9 | Equations 10 | 5 * $t_inside = -ua * (t_inside-t_outside) + (int_heater * 10 ) 11 | 12 | -------------------------------------------------------------------------------- /example_thermostat/heater.csv: -------------------------------------------------------------------------------- 1 | time,t_outside 2 | 0,0 3 | 1,1 4 | 2,2 5 | 3,3 6 | 4,4 7 | 5,4 8 | 6,4 9 | 7,4 10 | 8,4 11 | 9,4 12 | 10,4 13 | 11,3 14 | 12,3 15 | 13,3 16 | 14,3 17 | 15,3 18 | 16,2 19 | 17,2 20 | 18,2 21 | 19,1 22 | 20,1 23 | -------------------------------------------------------------------------------- /example_thermostat/main.m: -------------------------------------------------------------------------------- 1 | clear all; close all; clc 2 | addpath('../apm') 3 | 4 | s = 'http://byu.apmonitor.com'; 5 | a = 'heater'; 6 | 7 | apm(s,a,'clear all'); 8 | apm_load(s,a,'heater.apm'); 9 | csv_load(s,a,'heater.csv'); 10 | 11 | apm_option(s,a,'nlc.imode',6); 12 | apm_option(s,a,'nlc.solver',1); 13 | 14 | apm_info(s,a,'MV','int_heater'); 15 | apm_option(s,a,'int_heater.status',1); 16 | apm_option(s,a,'int_heater.dcost',0.005); 17 | 18 | apm_info(s,a,'CV','t_inside'); 19 | apm_option(s,a,'t_inside.status',1); 20 | apm_option(s,a,'t_inside.sphi',4); 21 | apm_option(s,a,'t_inside.splo',3); 22 | apm_option(s,a,'t_inside.tr_init',0); 23 | 24 | output = apm(s,a,'solve'); 25 | disp(output); 26 | 27 | apm_web(s,a); -------------------------------------------------------------------------------- /test_all.m: -------------------------------------------------------------------------------- 1 | % Run all example problems 2 | cd example_hs71; 3 | main 4 | 5 | disp('Pause for 2 sec') 6 | pause(2) 7 | cd ../example_sbml_vaccine 8 | main 9 | 10 | disp('Pause for 2 sec') 11 | pause(2) 12 | cd ../example_cstr_seq; 13 | main 14 | 15 | disp('Pause for 2 sec') 16 | pause(2) 17 | cd ../example_cstr_simul; 18 | main 19 | 20 | disp('Pause for 2 sec') 21 | pause(2) 22 | cd ../example_nlc 23 | main 24 | 25 | disp('Pause for 2 sec') 26 | pause(2) 27 | cd ../example_distillation 28 | test 29 | 30 | disp('Pause for 2 sec') 31 | pause(2) 32 | cd ../example_pendulum 33 | test 34 | 35 | disp('Pause for 2 sec') 36 | pause(2) 37 | cd ../example_4tank 38 | prbs 39 | 40 | disp('Test completed') 41 | 42 | --------------------------------------------------------------------------------