Ticket #111: conv_change

File conv_change, 4.8 kB (added by rjrw, 2 years ago)

Updated patch to deal with underflow problems on 64bit

Line 
1Index: conv_temp_eden_ioniz.cpp
2===================================================================
3--- conv_temp_eden_ioniz.cpp    (revision 3604)
4+++ conv_temp_eden_ioniz.cpp    (working copy)
5@@ -96,7 +96,6 @@
6                // here starts the standard solver for variable temperature
7                iter_track TeTrack;
8                double t1=0, error1=0, t2, error2;
9-               bool lgHighTeSearch = false;
10 
11                t2 = phycon.te;
12                error2 = CoolHeatError( t2 );
13@@ -109,38 +108,33 @@
14 
15                        TeTrack.clear();
16 
17+                       error1 = error2;
18+                       t1 = t2;
19+
20+                       // the factor 1.2 creates 20% safety margin
21+
22+                       if ( conv.dCmHdT != 0.0)
23+                               step = abs(safe_div( error1, conv.dCmHdT, 0. ));
24+                       else
25+                               step = 0.0;
26+                       
27                        // set up an initial guess for the bracket
28                        // t2 was already initialized outside the main loop, or is copied from the
29                        // previous iteration. don't record this evaluation, it may be poorly converged
30-                       for( int i=0; i < 2 && !lgAbort; ++i )
31+                       for( int i=0; error1*error2 > 0. && i < 100 && !lgAbort; ++i )
32                        {
33                                t1 = t2;
34                                error1 = error2;
35 
36-                               // the factor 1.2 creates 20% safety margin
37-                               step = safe_div( -1.2*error1, conv.dCmHdT, 0. );
38-                               step = sign( min( abs(step), factor*t1 ), step );
39-                               t2 = t1 + step;
40+                               double maxstep = factor*t1;
41+                               step = 2.0*step;
42+                               if (step == 0.0 || step > maxstep)
43+                                       step = maxstep;
44+                               t2 = t1 + sign(step,-error1 );
45                                error2 = CoolHeatError( t2 );
46                                TeTrack.add( t2, error2 );
47                        }
48 
49-                       int j = 0;
50-
51-                       // now hunt until we have bracketed the solution
52-                       while( error1*error2 > 0. && j++ < 2*DEF_ITER && !lgAbort )
53-                       {
54-                               t1 = t2;
55-                               error1 = error2;
56-                               double deriv = TeTrack.deriv(7);
57-                               // the factor 1.2 creates 20% safety margin
58-                               step = safe_div( -1.2*error1, deriv, 0. );
59-                               step = sign( min( abs(step), factor*t1 ), step );
60-                               t2 = t1 + step;
61-                               error2 = CoolHeatError( t2 );
62-                               TeTrack.add( t2, error2 );
63-                       }
64-
65                        if( trace.nTrConvg >= 2 && error1*error2 > 0. && !lgAbort )
66                        {
67                                fprintf( ioQQQ, "  ConvTempEdenIoniz: bracket1 fails t1: %e %e t2: %e %e\n",
68@@ -148,82 +142,8 @@
69                                TeTrack.print_history();
70                        }
71 
72-                       // If we reach this point without having bracketed the solution this means
73-                       // that searching using the derivate doesn't work... This typically happens
74-                       // when the heating and cooling curve no longer intersect, which implies
75-                       // that C-H vs Te now has a local maximum, but doesn't change sign any more.
76-                       // Hence we have reached a thermal front and we need to take a discontinuous
77-                       // step up or down. In the first while loop we search upwards, in the second
78-                       // downwards.
79-
80-                       int nUP = 2;
81-
82-                       if( nzone > 4 && !lgHighTeSearch && !lgAbort )
83-                       {
84-                               double x[3], y[3], a, b, siga, sigb;
85-                               for( int i=0; i < 3; ++i )
86-                               {
87-                                       x[i] = double(struc.depth[nzone-4+i]);
88-                                       y[i] = double(struc.testr[nzone-4+i]);
89-                               }
90-                               linfit( 3, x, y, a, siga, b, sigb );
91-                               // if the temperature is rising significantly in the previous zones
92-                               // we may have to take a big step upwards, so allow room for that...
93-                               if( b > sigb )
94-                               {
95-                                       lgHighTeSearch = true;
96-                                       nUP = 25;
97-                               }
98-                               if( trace.nTrConvg >= 2 )
99-                               {
100-                                       fprintf( ioQQQ, "  ConvTempEdenIoniz: temp deriv %g +/- %g\n", b, sigb );
101-                                       if( lgHighTeSearch )
102-                                               fprintf( ioQQQ, "  ConvTempEdenIoniz: doing high Te search...\n" );
103-                               }
104-                       }
105-
106-                       // hunting using the derivative failed, so first start hunting upwards
107-                       //
108-                       // guard against overrunning the maximum temperature limit of the code
109-                       // so that we are guaranteed to get a chance to hunt downwards
110-                       while( error1*error2 > 0. && j++ < (2+nUP)*DEF_ITER && !lgAbort &&
111-                              t2*(1.+factor) <= 0.99999*phycon.TEMP_LIMIT_HIGH )
112-                       {
113-                               t1 = t2;
114-                               error1 = error2;
115-                               if( lgHighTeSearch && t2 > 4000. )
116-                                       factor = 0.05;
117-                               t2 = t1*(1.+factor);
118-                               error2 = CoolHeatError( t2 );
119-                               TeTrack.add( t2, error2 );
120-                       }
121-
122-                       // hunting upwards failed, so start hunting downwards
123-                       // we may need to take a big plunge downwards, so # of iter should be big
124-                       //
125-                       // don't guard against dropping below the minimum temperature limit of the
126-                       // code so that we get an abort if the solver has completely lost the solution.
127-                       // this is a serious condition that needs to be investigated...
128-                       while( error1*error2 > 0. && j++ < (2+2*nUP+9)*DEF_ITER && !lgAbort )
129-                       {
130-                               t1 = t2;
131-                               error1 = error2;
132-                               if( lgHighTeSearch && t2 <= 4000. )
133-                                       factor = DEF_FACTOR;
134-                               t2 = t1*(1.-factor);
135-                               error2 = CoolHeatError( t2 );
136-                               TeTrack.add( t2, error2 );
137-                       }
138-
139                        factor = DEF_FACTOR;
140 
141-                       if( trace.nTrConvg >= 2 && error1*error2 > 0. && !lgAbort )
142-                       {
143-                               fprintf( ioQQQ, "  ConvTempEdenIoniz: bracket2 fails t1: %e %e t2: %e %e\n",
144-                                        t1, error1, t2, error2 );
145-                               TeTrack.print_history();
146-                       }
147-
148                        // keeping the history up until now has a bad effect on convergence
149                        // so we wipe the slate clean....
150                        TeTrack.clear();