# optimization problem with NDSolve

I want to minimize the function fcc. When fcc is calculated for a specified point the answer is correct:

In[70]:= fcc[0.5, 0.5, 0.004, 0.006, 0.0025, 0.5]
Out[70]= 2.96667*10^6


but when I want to optimize fcc with NMinimize there is a problem below:

NMinimize[{fcc[q1, q2, q3, q4, q5, q6], 0.5 <= q1 <= 1.5,
0.5 <= q2 <= 1.5, 0.003 <= q3 <= 0.01, 0.003 <= q4 <= 0.01,
0.002 <= q5 <= 0.005, 0.5 <= q6 <= 1}, {q1, q2, q3, q4, q5, q6}]


NDSolve::ndsv: Cannot find starting value for the variable ws. >>

ReplaceAll::reps: {NDSolve[{-((0.00011318 (q2+q3) (-0.0174073+ws[<<1>>]))/(q3 q4 q6))+(ws^[Prime])[x]==0,ws[q1]==0.012529},{ws},{x,0,q1}]} is neither a list of replacement rules nor a valid dispatch table, and so cannot be used for replacing. >>

ReplaceAll::reps: {NDSolve[{-((0.00011318 (q2+q3) (-0.0174073+ws[<<1>>]))/(q3 q4 q6))+(ws^[Prime])[x]==0,ws[q1]==0.012529},{ws},{x,0,q1}]} is neither a list of replacement rules nor a valid dispatch table, and so cannot be used for replacing. >>

ReplaceAll::reps: {NDSolve[{-((0.00011318 (q2+q3) (-0.0174073+ws[<<1>>]))/(q3 q4 q6))+(ws^[Prime])[x]==0,ws[q1]==0.012529},{ws},{x,0,q1}]} is neither a list of replacement rules nor a valid dispatch table, and so cannot be used for replacing. >>

General::stop: Further output of ReplaceAll::reps will be suppressed during this calculation. >>

NDSolve::ndsv: Cannot find starting value for the variable ts. >>

NMinimize::nnum: The function value 2.18625*10^6+6618.38 (-0.012529+ws[0]) is not a number at {q1,q2,q3,q4,q5,q6} = {1.4748,1.12029,0.0074076,0.00951558,0.00291973,0.810076}. >>

and this is the fcc function:

ta = 30; rha = 0.4; altitude = 1361; p =
101325*(1 - altitude*2.25577*10^-5)^5.2559; tka =
273.15 + ta; c1 = -5.8002206*10^3; c2 = 1.3914993; c3 = \
-4.8640239*10^-2; c4 =
4.1764768*10^-5; c5 = -1.4452093*10^-8; c6 = 6.5459673; psata =
Exp[c1/tka + c2 + c3*tka + c4*tka^2 + c5*tka^3 + c6*Log[tka]]; pva =
rha*psata; wa =
0.621945*pva/(p -
pva); tr = 26; rsh = 1500; nu = 7.54; lef = 0.894; tsin = ta; \
tpin = ta; twin = 20; wsin = wa; wpin = wa; tkw =
273.17 + twin; psatw =
Exp[c1/tkw + c2 + c3*tkw + c4*tkw^2 + c5*tkw^3 +
c6*Log[tkw]]; pvw = psatw; wsat =
0.621945*pvw/(p -
pvw); cps = 1006; cpp = 1006; cpv = 1873; cpw = 4183; ks = \
0.027; kp = 0.027; kwater = 0.6; kwall = 237; hfg = 2501000; lwall = \
0.0005; lwater = 0.001;
fcc[lx_, ly_, lp_, mp_, mw_, ratio_] := Module[{},
ms = ratio*mp;
ls = lp;
dhs = 2*ly*ls/(ly + ls);
dhp = 2*ly*lp/(ly + lp);
hs = nu*ks/dhs;
hp = nu*kp/dhp;
hm = hs/(lef*cps);
u = 1/(1/hp + lwall/kwall + lwater/kwater);
dels = -1; delp = -1;
wss = NDSolve[{(dels hm ly (ws[x] - wsat))/ms +
Derivative[1][ws][x] == 0, ws[lx] == wsin}, {ws}, {x, 0, lx}];
tstptw =
NDSolve[{(dels ly (ts[x] - tw[x]) (hs +
cpv hm (-Evaluate[{ws[x]} /. wss] + wsat)))/(ms (cps +
cpv Evaluate[{ws[x]} /. wss])) + Derivative[1][ts][x] ==
0, (delp ly (tp[x] - tw[x]) u)/(mp (cpp + cpv wpin)) +
Derivative[1][tp][x] == 0,
1/(cpw mw)
ly (delp (-tp[x] + tw[x]) u +
dels (hs (-ts[x] + tw[x]) -
hm (hfg + cpv tw[x] -
cpw tw[x]) (Evaluate[{ws[x]} /. wss] - wsat))) +
Derivative[1][tw][x] == 0, ts[lx] == tsin, tp[lx] == tpin,
tw[0] == twin}, {ts, tp, tw}, {x, 0, lx}];
(*Plot[Evaluate[{{ts[x],tp[x],tw[x]}/.tstptw}],{x,0,lx}]*)
tpout = Evaluate[tp[0] /. tstptw]; tpout = tpout[[1]];
tsout = Evaluate[ts[0] /. tstptw]; tsout = tsout[[1]];
wsout = Evaluate[ws[0] /. wss]; wsout = wsout[[1]];
cp = 1006;
If[(tr - tpout) < 0.5, mt = 20, mt = rsh/(cp*(tr - tpout))];
np = Round[mt/mp];
ca = 100;
at = lx*((np + 1)*(ly + 4*lp) + ly);
n = 0.6;
cinv = ca*at^n;
kel = 120;
kw = 1.5;
\[Tau] = 3000;
\[Eta] = 0.5;
ro1 = 1.17;
v1 = ms/(ro1*ls*ly);
miu1 = 10^-5;
re1 = ro1*v1*dhs/miu1;
\[Alpha]1 = ls/ly;
f1 = 24*(1 - 1.355*\[Alpha]1 + 1.9467*\[Alpha]1^2 -
1.7012*\[Alpha]1^3 + 0.9564*\[Alpha]1^4 - 0.2537*\[Alpha]1^5)/
re1;
dps = 2*f1*ro1*(v1^2)*lx/dhs;
smd = 1.17;
mst = ms*np/smd;
cos = kel*\[Tau]*((dps*mst)/(\[Eta]*10^6));
ro2 = 1.17;
v2 = ms/(ro2*lp*ly);
miu2 = 10^-5;
re2 = ro2*v2*dhp/miu2;
\[Alpha]2 = lp/ly;
f2 = 24*(1 - 1.355*\[Alpha]2 + 1.9467*\[Alpha]2^2 -
1.7012*\[Alpha]2^3 + 0.9564*\[Alpha]2^4 - 0.2537*\[Alpha]2^5)/
re2;
dpp = 2*f2*ro2*(v2^2)*lx/dhp;
pmd = 1.17;
mpt = mp*np/pmd;
cop = kel*\[Tau]*((dpp*mpt)/(\[Eta]*10^6));
h = 2;
g = 9.81;
copump = kel*\[Tau]*h*g*mw*np/\[Eta];
ew = ms*np*(wsout - wsin);
cow = kw*\[Tau]*3.6*ew;
r = 0.1;
y = 10;
a = r/(1 - (1 + r)^(-y));
a*cinv + cos + cop + copump + cow];


As the previous answer shows while dealing with this type of problem in Mathematica one must use _?NumericQ in the function definition. Once you define the function as Mr.Wizard♦ has instructed, it is pretty straightforward to call NMinimize or FindMinimum. I would also like to scale your function fcc by $10^6$. However FindMinimum is better suited for this type of multivariate optimization problem where the algorithm can't take advantage of the symbolic processing because the function definition is very numerical in nature.

• FindMinimum

This is the call to FindMinimum with Sow and Reap to show the convergence for the optimization parameters. I don't have much time so we use MaxIterations to be just $40$ but it still took some $106$ sec.

resFindMinimum =
Reap[FindMinimum[{fcc[q1, q2, q3, q4, q5, q6]/10^6,
0.5 <= q1 <= 1.5 && 0.5 <= q2 <= 1.5 && 0.003 <= q3 <= 0.01 &&
0.003 <= q4 <= 0.01 && 0.002 <= q5 <= 0.005 &&
0.5 <= q6 <= 1}, {q1, q2, q3, q4, q5, q6},
StepMonitor :> Sow[{q1, q2, q3, q4, q5, q6}],
MaxIterations -> 40]]; // AbsoluteTiming


{106.8161095, Null}

To create the convergence plot to show how the optimization parameters $\{p_1,...,p_6\}$ changes during the optimization function call we use the following

col = RandomChoice[ColorData[3, "ColorList"], 6];
GraphicsGrid[
Partition[
MapThread[ListLinePlot[#1, Frame -> True, Mesh -> 10, MeshStyle -> Black,
PlotStyle -> #2] &,{(resFindMinimum[[2, 1]] // Transpose),col}
], 3],
ImageSize -> 700]


and finally the result is

{10^6 resFindMinimum[[1, 1]], resFindMinimum[[1, 2]]}


{960785., {q1 -> 1.17089, q2 -> 1.17235, q3 -> 0.00969339, q4 -> 0.0096893, q5 -> 0.002, q6 -> 0.748547}}

• NMinimize

Similar thing is done by NMinimize but this takes more time than it takes in general for FindMinimum. However in this case the objective function was further minimized using this algorithm costing $217$ sec of my CPU. I limited the MaxIterations to force the algorithm to stop.

resNMinimize =
Reap[NMinimize[{fcc[q1, q2, q3, q4, q5, q6]/10^6,
0.5 <= q1 <= 1.5 && 0.5 <= q2 <= 1.5 && 0.003 <= q3 <= 0.01 &&
0.003 <= q4 <= 0.01 && 0.002 <= q5 <= 0.005 &&
0.5 <= q6 <= 1}, {q1, q2, q3, q4, q5, q6},
StepMonitor :> Sow[{q1, q2, q3, q4, q5, q6}],
MaxIterations -> 40]]; // AbsoluteTiming


{217.2744274, Null}

The result is better

{734721., {q1 -> 0.82917, q2 -> 1.21265, q3 -> 0.00332494,q4 -> 0.00986184, q5 -> 0.002, q6 -> 0.999981}}

• Can we make FindMinimum better?

One often needs to give a better initial guess to FindMinimum to resolve a optimization problem that has stalled at some local minimum. We can use the NMinimize result to provide FindMinimum a better starting point. The new guesses are

{{q1, q2, q3, q4, q5, q6},{q1, q2, q3, q4, q5, q6}/.resNMinimize[[1, 2]]}//Transpose


{{q1, 0.82917}, {q2, 1.21265}, {q3, 0.00332494}, {q4,0.00986184}, {q5, 0.002}, {q6, 0.999981}}

Again I run FindMinimum just for $40$ iterations.

NresFindMinimum =
Reap[FindMinimum[{fcc[q1, q2, q3, q4, q5, q6]/10^6,
0.5 <= q1 <= 1.5 && 0.5 <= q2 <= 1.5 && 0.003 <= q3 <= 0.01 &&
0.003 <= q4 <= 0.01 && 0.002 <= q5 <= 0.005 &&
0.5 <= q6 <= 1}, {{q1, 0.829170177410782}, {q2,
1.212649238425597}, {q3, 0.003324936752031159}, {q4,
0.00986184329841919}, {q5, 0.0020000030660318143}, {q6,
0.9999807985249598}},
StepMonitor :> Sow[{q1, q2, q3, q4, q5, q6}],
MaxIterations -> 40]]; // AbsoluteTiming


{159.2921110, Null}

However we don't get any better result though it took $159$ sec.

{10^6 NresFindMinimum[[1, 1]], NresFindMinimum[[1, 2]]}

{819476., {q1 -> 0.796225, q2 -> 1.14357, q3 -> 0.00400138,q4 -> 0.00916374, q5 -> 0.002, q6 -> 0.998775}}

The convergence graph seems to tell my current lack of time is a problem for FindMinimum!!! Please check the Mathematica constraint optimization documentation.

• @dear PlatoManiac lots of thanks for your attention and answer Commented Jun 13, 2012 at 15:55

For a start you need _?NumericQ (search the site for NumericQ for many other examples) and you need to localize your variable in Module. fcc should be defined:

fcc[
lx_?NumericQ,
ly_?NumericQ,
lp_?NumericQ,
mp_?NumericQ,
mw_?NumericQ,
ratio_?NumericQ
] :=
Module[{ms, ls, dhs, dhp, hs, hp, hm, u, dels, delp, wss, ws, tstptw,
ts, tw, tp, tpout, tsout, wsout, cp, mt, np, ca, at, n, cinv, kel,
kw, \[Tau], \[Eta], ro1, v1, miu1, re1, \[Alpha]1, f1, dps, smd,
mst, cos, ro2, v2, miu2, re2, \[Alpha]2, f2, dpp, pmd, mpt, cop, h,
g, copump, ew, cow, r, y, a},

(* the rest of your code *)

]


With this I still get errors:

NDSolve::berr: There are significant errors {-4.09654*10^-7,-1.40957*10^-7,0.} in the boundary value residuals. Returning the best solution found. >>

NDSolve::bvluc: The equations derived from the boundary conditions are numerically ill-conditioned. The boundary conditions may not be sufficient to uniquely define a solution. The computed solution may match the boundary conditions poorly. >>

NDSolve::berr: There are significant errors {1.01351,0.148459,0.} in the boundary value residuals. Returning the best solution found. >>

however I don't feel like working these out for you.

• Anyway, thanks for your answer Commented Jun 13, 2012 at 10:39
• @xazar You're welcome. Sorry I don't have a complete answer without errors for you, but that's a lot of math to work through! Commented Jun 13, 2012 at 11:12
• @Mr.Wizard, Thanks for the reopen. Ah, well yes, the question could be shorter, but at least it had all information/code to run the problem. I deleted my comments.
– user21
Commented Jun 13, 2012 at 23:41
• @ruebenko I reopened this question at your request; I'm curious, are you intending to post an answer? Commented Jun 14, 2012 at 13:53