CloudDisconnect[]

$CloudBase="https://www.wsmdev.wolfram.com/"

CloudConnect[]

Tanks with leak form

CloudDeploy[FormFunction[{"Model the change in height of water in two cylindrical tanks as water flows from one tank to another through a pipe with a leak.","pipeLen"-><|"Interpreter"->Restricted["Number",{0.01,1}],"Default"->.1,"Control"->Slider,"Label"->"Pipe length","Help"->"A longer pipe leads to a longer time for complete drainage"|>,"time"-><|"Label"->"Simulation time","Default"->80,"Hint"->"80","Help"->"It usually takes at least 80 seconds to reach steady-state","Interpreter"->Restricted["Number",{10,1000}]|>},Module[{pressureEqns,flowRate,params,massConservation,a1,a2,sol},pressureEqns={p1[t]==ρ g h1[t],p2[t]==ρ g h2[t]};flowRate=(p1[t]-p2[t])(π pipeDia^4)/(128 μ pipeLen);params={pipeLen->#pipeLen,pipeDia->0.2,ρ->0.2,μ->2 10^-3,g->9.81};
{a1,a2}={1,1};massConservation={a1 h1'[t]==-flowRate,a2 h2'[t]==flowRate-a2 h2[t]/10};sol=NDSolve[{pressureEqns,massConservation,h1[0]==1,h2[0]==0}/.params,{h1,h2,p1,p2},{t,0,#time}];
Plot[Evaluate[{h1[t],h2[t]}/.sol],{t,0,#time},PlotLabel->"Tank Simulation with time: "<>ToString[#time]<>"s and pipe length: "<>ToString[#pipeLen],PlotLegends->Placed[SwatchLegend[{"Tank1","Tank2"}],{{0.8,0.8},{0.5,.5}}],PlotRange->All,AxesLabel->{"Time [s]","Height [m]"},AxesOrigin->{0,0},ImageSize->Large,ImageMargins->10]]&,"PNG",AppearanceRules-><|"Title"->"Tank Simulation","Description"->"Simulate a tank with a leaking pipe","SubmitLabel"->"Run simulation"|>],Permissions->"Public"]

Tanks with leak Manipulate

CloudDeploy[Manipulate[pressureEqns={p1[t]== ρ g h1[t],p2[t]==ρ g h2[t]};
massConservation={a1 h1'[t]==-flowRate,a2 h2'[t]==flowRate-a2 h2[t]*leakageFactor};
flowRate=(p1[t]-p2[t])(π pipeDia^4)/(128 μ pipeLen);
params={pipeLen->plen,pipeDia->0.2,ρ->0.2,μ->2 10^-3,g->9.81};
{a1,a2}={1,1};
sol=NDSolve[{pressureEqns,massConservation,h1[0]==1,h2[0]==0}/.params,{h1,h2,p1,p2},{t,0,tend}];
Plot[Evaluate[{h1[t],h2[t]}/.sol],{t,0,tend}, PlotRange -> All,AxesLabel->{"Time [s]","Height [m]"},AxesOrigin->{0,0},ImageSize->Large],{{tend,70},10,300},{{plen,0.4},0.01,1},{{leakageFactor,0.15},0,1.5}],Permissions->"Public"]

API Function

CloudDeploy[APIFunction[{"pipeLen"->"Number"->0.1,"time"->"Number"->80},
Module[{pressureEqns,flowRate,params,massConservation,a1,a2,sol},pressureEqns={p1[t]==ρ g h1[t],p2[t]==ρ g h2[t]};flowRate=(p1[t]-p2[t])(π pipeDia^4)/(128 μ pipeLen);params={pipeLen->#pipeLen,pipeDia->0.2,ρ->0.2,μ->2 10^-3,g->9.81};
{a1,a2}={1,1};massConservation={a1 h1'[t]==-flowRate,a2 h2'[t]==flowRate-a2 h2[t]/10};sol=NDSolve[{pressureEqns,massConservation,h1[0]==1,h2[0]==0}/.params,{h1,h2,p1,p2},{t,0,#time}];
Plot[Evaluate[{h1[t],h2[t]}/.sol],{t,0,#time},PlotLabel->"Tank Simulation with time: "<>ToString[#time]<>"s and pipe length: "<>ToString[#pipeLen],PlotLegends->Placed[SwatchLegend[{"Tank1","Tank2"}],{{0.8,0.8},{0.5,.5}}],PlotRange->All,AxesLabel->{"Time [s]","Height [m]"},AxesOrigin->{0,0},ImageSize->Large,ImageMargins->10]]&,"PNG"],Permissions->"Public"]

Data upload calibration

ff=FormFunction[{"Find the conductance (W/K) of the material between the two conducting masses.",
"Documentation for the : <a href=http://reference.wolfram.com/system-modeler/libraries/Modelica/Modelica.Thermal.HeatTransfer.Components.ThermalConductor.html>Thermal Conductor</a>","data"-><|"Interpreter"->"CSV","Label"->"Measured data","Help"->"Upload data in .CSV format"|>,"Sample data can be found here: <a href=https://internal.wolfram.com/~johanr/data.csv>data.csv</a>"},Module[{criteriaFun,fittedpars,lp,sol,pl},criteriaFun[v:_?NumericQ]:=Module[{f},f=Quiet@NDSolveValue[{WSMLink`Eq`conduction▴dT[\[FormalT]]==WSMLink`Eq`conduction▴port⎵a▴T[\[FormalT]]-WSMLink`Eq`conduction▴port⎵b▴T[\[FormalT]],WSMLink`Eq`conduction▴Q⎵flow[\[FormalT]]==myconductance WSMLink`Eq`conduction▴dT[\[FormalT]],150 (WSMLink`Eq`mass1▴T)'[\[FormalT]]==WSMLink`Eq`mass1▴port▴Q⎵flow[\[FormalT]],WSMLink`Eq`mass1▴der⎵T[\[FormalT]]==(WSMLink`Eq`mass1▴T)'[\[FormalT]],WSMLink`Eq`mass1▴T[\[FormalT]]==WSMLink`Eq`mass1▴port▴T[\[FormalT]],300 (WSMLink`Eq`mass2▴T)'[\[FormalT]]==WSMLink`Eq`mass2▴port▴Q⎵flow[\[FormalT]],WSMLink`Eq`mass2▴der⎵T[\[FormalT]]==(WSMLink`Eq`mass2▴T)'[\[FormalT]],WSMLink`Eq`mass2▴T[\[FormalT]]==WSMLink`Eq`mass2▴port▴T[\[FormalT]],WSMLink`Eq`Tsensor1▴T[\[FormalT]]==WSMLink`ModelicaFunctions`Modelica▴SIunits▴Conversions▴to⎵degC[WSMLink`Eq`Tsensor1▴port▴T[\[FormalT]]],WSMLink`Eq`Tsensor2▴T[\[FormalT]]==WSMLink`ModelicaFunctions`Modelica▴SIunits▴Conversions▴to⎵degC[WSMLink`Eq`Tsensor2▴port▴T[\[FormalT]]],WSMLink`Eq`conduction▴port⎵a▴Q⎵flow[\[FormalT]]==WSMLink`Eq`conduction▴Q⎵flow[\[FormalT]],WSMLink`Eq`conduction▴port⎵b▴Q⎵flow[\[FormalT]]==-WSMLink`Eq`conduction▴Q⎵flow[\[FormalT]],WSMLink`Eq`Tsensor1▴port▴Q⎵flow[\[FormalT]]==0,WSMLink`Eq`conduction▴port⎵a▴Q⎵flow[\[FormalT]]+WSMLink`Eq`mass1▴port▴Q⎵flow[\[FormalT]]+WSMLink`Eq`Tsensor1▴port▴Q⎵flow[\[FormalT]]==0,WSMLink`Eq`Tsensor1▴port▴T[\[FormalT]]==WSMLink`Eq`conduction▴port⎵a▴T[\[FormalT]],WSMLink`Eq`Tsensor1▴port▴T[\[FormalT]]==WSMLink`Eq`mass1▴port▴T[\[FormalT]],WSMLink`Eq`Tsensor2▴port▴Q⎵flow[\[FormalT]]==0,WSMLink`Eq`conduction▴port⎵b▴Q⎵flow[\[FormalT]]+WSMLink`Eq`mass2▴port▴Q⎵flow[\[FormalT]]+WSMLink`Eq`Tsensor2▴port▴Q⎵flow[\[FormalT]]==0,WSMLink`Eq`Tsensor2▴port▴T[\[FormalT]]==WSMLink`Eq`conduction▴port⎵b▴T[\[FormalT]],WSMLink`Eq`Tsensor2▴port▴T[\[FormalT]]==WSMLink`Eq`mass2▴port▴T[\[FormalT]],WSMLink`Eq`T⎵final⎵K[0]==(1/450) (150 WSMLink`Eq`mass1▴T[0]+300 WSMLink`Eq`mass2▴T[0]),WSMLink`Eq`mass1▴der⎵T[0]==NDSolve`Guess[0],WSMLink`Eq`mass1▴T[0]==373.15`,WSMLink`Eq`mass2▴der⎵T[0]==NDSolve`Guess[0],WSMLink`Eq`mass2▴T[0]==273.15`,WSMLink`Eq`conduction▴port⎵a▴T[0]==NDSolve`Guess[288.15`],WSMLink`Eq`conduction▴port⎵b▴T[0]==NDSolve`Guess[288.15`],WSMLink`Eq`mass1▴port▴T[0]==NDSolve`Guess[288.15`],WSMLink`Eq`mass2▴port▴T[0]==NDSolve`Guess[288.15`],WSMLink`Eq`Tsensor1▴port▴T[0]==NDSolve`Guess[288.15`],WSMLink`Eq`Tsensor2▴port▴T[0]==NDSolve`Guess[288.15`],WSMLink`Eq`conduction▴G[0]==myconductance,WSMLink`Eq`mass1▴C[0]==150,WSMLink`Eq`mass2▴C[0]==300},WSMLink`Eq`Tsensor1▴T,{\[FormalT],0,40},DiscreteVariables->{WSMLink`Eq`T⎵final⎵K,WSMLink`Eq`mass1▴C,WSMLink`Eq`mass2▴C,WSMLink`Eq`conduction▴G},Method->{"EquationSimplification"->"Residual","IndexReduction"->Automatic},MaxSteps->∞]/.myconductance->v;
(Norm[Table[#data[[i,2]]-f[#data[[i,1]]],{i,Length[#data]}]])^2];
fittedpars=FindMinimum[criteriaFun[p],{p,9},StepMonitor:>PrintTemporary[p]];
lp=ListPlot[#data,PlotStyle->Red];
sol=Quiet@NDSolveValue[{WSMLink`Eq`conduction▴dT[\[FormalT]]==WSMLink`Eq`conduction▴port⎵a▴T[\[FormalT]]-WSMLink`Eq`conduction▴port⎵b▴T[\[FormalT]],WSMLink`Eq`conduction▴Q⎵flow[\[FormalT]]==myconductance WSMLink`Eq`conduction▴dT[\[FormalT]],150 (WSMLink`Eq`mass1▴T)'[\[FormalT]]==WSMLink`Eq`mass1▴port▴Q⎵flow[\[FormalT]],WSMLink`Eq`mass1▴der⎵T[\[FormalT]]==(WSMLink`Eq`mass1▴T)'[\[FormalT]],WSMLink`Eq`mass1▴T[\[FormalT]]==WSMLink`Eq`mass1▴port▴T[\[FormalT]],300 (WSMLink`Eq`mass2▴T)'[\[FormalT]]==WSMLink`Eq`mass2▴port▴Q⎵flow[\[FormalT]],WSMLink`Eq`mass2▴der⎵T[\[FormalT]]==(WSMLink`Eq`mass2▴T)'[\[FormalT]],WSMLink`Eq`mass2▴T[\[FormalT]]==WSMLink`Eq`mass2▴port▴T[\[FormalT]],WSMLink`Eq`Tsensor1▴T[\[FormalT]]==WSMLink`ModelicaFunctions`Modelica▴SIunits▴Conversions▴to⎵degC[WSMLink`Eq`Tsensor1▴port▴T[\[FormalT]]],WSMLink`Eq`Tsensor2▴T[\[FormalT]]==WSMLink`ModelicaFunctions`Modelica▴SIunits▴Conversions▴to⎵degC[WSMLink`Eq`Tsensor2▴port▴T[\[FormalT]]],WSMLink`Eq`conduction▴port⎵a▴Q⎵flow[\[FormalT]]==WSMLink`Eq`conduction▴Q⎵flow[\[FormalT]],WSMLink`Eq`conduction▴port⎵b▴Q⎵flow[\[FormalT]]==-WSMLink`Eq`conduction▴Q⎵flow[\[FormalT]],WSMLink`Eq`Tsensor1▴port▴Q⎵flow[\[FormalT]]==0,WSMLink`Eq`conduction▴port⎵a▴Q⎵flow[\[FormalT]]+WSMLink`Eq`mass1▴port▴Q⎵flow[\[FormalT]]+WSMLink`Eq`Tsensor1▴port▴Q⎵flow[\[FormalT]]==0,WSMLink`Eq`Tsensor1▴port▴T[\[FormalT]]==WSMLink`Eq`conduction▴port⎵a▴T[\[FormalT]],WSMLink`Eq`Tsensor1▴port▴T[\[FormalT]]==WSMLink`Eq`mass1▴port▴T[\[FormalT]],WSMLink`Eq`Tsensor2▴port▴Q⎵flow[\[FormalT]]==0,WSMLink`Eq`conduction▴port⎵b▴Q⎵flow[\[FormalT]]+WSMLink`Eq`mass2▴port▴Q⎵flow[\[FormalT]]+WSMLink`Eq`Tsensor2▴port▴Q⎵flow[\[FormalT]]==0,WSMLink`Eq`Tsensor2▴port▴T[\[FormalT]]==WSMLink`Eq`conduction▴port⎵b▴T[\[FormalT]],WSMLink`Eq`Tsensor2▴port▴T[\[FormalT]]==WSMLink`Eq`mass2▴port▴T[\[FormalT]],WSMLink`Eq`T⎵final⎵K[0]==(1/450) (150 WSMLink`Eq`mass1▴T[0]+300 WSMLink`Eq`mass2▴T[0]),WSMLink`Eq`mass1▴der⎵T[0]==NDSolve`Guess[0],WSMLink`Eq`mass1▴T[0]==373.15`,WSMLink`Eq`mass2▴der⎵T[0]==NDSolve`Guess[0],WSMLink`Eq`mass2▴T[0]==273.15`,WSMLink`Eq`conduction▴port⎵a▴T[0]==NDSolve`Guess[288.15`],WSMLink`Eq`conduction▴port⎵b▴T[0]==NDSolve`Guess[288.15`],WSMLink`Eq`mass1▴port▴T[0]==NDSolve`Guess[288.15`],WSMLink`Eq`mass2▴port▴T[0]==NDSolve`Guess[288.15`],WSMLink`Eq`Tsensor1▴port▴T[0]==NDSolve`Guess[288.15`],WSMLink`Eq`Tsensor2▴port▴T[0]==NDSolve`Guess[288.15`],WSMLink`Eq`conduction▴G[0]==myconductance,WSMLink`Eq`mass1▴C[0]==150,WSMLink`Eq`mass2▴C[0]==300},WSMLink`Eq`Tsensor1▴T,{\[FormalT],0,40},DiscreteVariables->{WSMLink`Eq`T⎵final⎵K,WSMLink`Eq`mass1▴C,WSMLink`Eq`mass2▴C,WSMLink`Eq`conduction▴G},Method->{"EquationSimplification"->"Residual","IndexReduction"->Automatic},MaxSteps->∞]/.myconductance->fittedpars[[2,1,2]];
pl=Plot[sol[t],{t,0,40},PlotRange->All,ImageSize->Large,AxesLabel->{"Time [s]","Temp [°C]"},AxesLabel->{"Time [s]","Temp [°C]"},PlotLabel->"The calibrated value for the parameter 'conduction.G' is: "<>ToString[fittedpars[[2,1,2]]]];
Show[pl,lp]]&,"PNG",AppearanceRules-><|"Title"->"Parameter Identification","Description"->"Use lab data to tune a model parameter.","SubmitLabel"->"Calibrate Model"|>];

CloudDeploy[ff,Permissions->"Public"]