cloudy  trunk
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
heat_save.cpp
Go to the documentation of this file.
1 /* This file is part of Cloudy and is copyright (C)1978-2017 by Gary J. Ferland and
2  * others. For conditions of distribution and use see copyright notice in license.txt */
3 /*SaveHeat save contributors to local heating, with save heat command, called by punch_do */
4 #include "cddefines.h"
5 #include "thermal.h"
6 #include "radius.h"
7 #include "conv.h"
8 #include "dense.h"
9 #include "taulines.h"
10 #include "phycon.h"
11 #include "elementnames.h"
12 #include "dynamics.h"
13 #include "save.h"
14 #include "lines_service.h"
15 
16 /* limit for number of heat agents that are saved */
17 /* limit to number to print */
18 static const int IPRINT= 9;
19 
20 /*SaveHeat save contributors to local heating, with save heat command,
21  * called by punch_do */
22 void SaveHeat(FILE* io)
23 {
24  DEBUG_ENTRY( "SaveHeat()" );
25 
26  vector<realnum>SaveVal(LIMELM*LIMELM, -FLT_MAX);
27  vector<long>ipsave(LIMELM*LIMELM, INT_MIN);
28  vector<long>jpsave(LIMELM*LIMELM, INT_MIN);
29  vector<long>ipOrdered(LIMELM*LIMELM);
30  vector<string> chLabel(LIMELM*LIMELM);
31 
32  double cool_total = thermal.ctot;
33  double heat_total = thermal.htot;
34 
35  /* >>chng 06 mar 17, comment out following block and replace with this
36  * removing dynamics heating & cooling and report only physical
37  * heating and cooling
38  * NB the heating and cooling as punched no longer need be
39  * equal for a converged model */
40  cool_total -= dynamics.Cool();
41  heat_total -= dynamics.Heat();
42  if( false )
43  {
44  if(dynamics.Cool() > dynamics.Heat())
45  {
46  cool_total -= dynamics.Heat();
47  heat_total -= dynamics.Heat();
48  }
49  else
50  {
51  cool_total -= dynamics.Cool();
52  heat_total -= dynamics.Cool();
53  }
54  }
55 
56  long ipnt = 0;
57 
58  /* heat sources are saved in a 2d square array */
59  /* WeakHeatCool set with 'set weakheatcool' command
60  * default is 0.05 */
61  for( long i=0; i < LIMELM; i++ )
62  {
63  for( long j=0; j < LIMELM; j++ )
64  {
65  if( safe_div( thermal.heating(i,j), heat_total, 0. ) > SMALLFLOAT )
66  {
67  ipsave[ipnt] = i;
68  jpsave[ipnt] = j;
69  SaveVal[ipnt] = (realnum)( safe_div( thermal.heating(i,j), heat_total, 0. ) );
70  ipnt++;
71  }
72  }
73  }
74 
75  /* now check for possible line heating not counted in 1,23
76  * there should not be any significant heating source here
77  * since they would not be counted in derivative correctly */
78  for( long i=0; i < thermal.ncltot; i++ )
79  {
80  if( safe_div( thermal.heatnt[i], heat_total, 0. ) > save.WeakHeatCool )
81  {
82  realnum awl;
83  awl = thermal.collam[i];
84  /* force to save wavelength convention as printout */
85  if( awl > 100000 )
86  awl /= 10000;
87  fprintf( io, " Negative coolant was %s %.2f %.2e\n",
88  thermal.chClntLab[i], awl, safe_div( thermal.heatnt[i], heat_total, 0. ) );
89  }
90  }
91 
92  if( !conv.lgConvTemp )
93  {
94  fprintf( io, "#>>>> Temperature not converged.\n" );
95  }
96  else if( !conv.lgConvEden )
97  {
98  fprintf( io, "#>>>> Electron density not converged.\n" );
99  }
100  else if( !conv.lgConvIoniz() )
101  {
102  fprintf( io, "#>>>> Ionization not converged.\n" );
103  }
104  else if( !conv.lgConvPres )
105  {
106  fprintf( io, "#>>>> Pressure not converged.\n" );
107  }
108 
109  /* this is mainly to keep the compiler from flagging possible paths
110  * with j not being set */
111  long i = INT_MIN;
112  long j = INT_MIN;
113  /* following loop tries to identify strongest agents and turn to labels */
114  for( long k=0; k < ipnt; k++ )
115  {
116  /* generate labels that make sense in printout
117  * if not identified with a specific agent, will print indices as [i][j],
118  * heating is thermal.heating(i,j) */
119  i = ipsave[k];
120  j = jpsave[k];
121  /* i >= j indicates agent is one of the first LIMELM elements */
122  if( i >= j )
123  {
124  if( dense.xIonDense[i][j] == 0. && thermal.heating(i,j)>SMALLFLOAT )
125  fprintf(ioQQQ,"DISASTER assert about to be thrown - search for hit it\n");
126  /*fprintf(ioQQQ,"DEBUG %li %li %.2e %.2e\n", i , j ,
127  dense.xIonDense[i][j],
128  thermal.heating(i,j));*/
129  ASSERT( dense.xIonDense[i][j] > 0. || thermal.heating(i,j)<SMALLFLOAT );
130  /* this is case of photoionization of atom or ion */
131  chLabel[k] = elementnames.chElementSym[i];
132  chLabel[k] += elementnames.chIonStage[j];
133  }
134  /* notice that in test i and j are swapped from order in heating array */
135  else if( i == 0 && j == 1 )
136  {
137  /* photoionization from all excited states of Hydrogenic species,
138  * heating(0,1) */
139  chLabel[k] = "Hn=2";
140  }
141  else if( i == 0 && j == 3 )
142  {
143  /* collisional ionization of all iso-seq from all levels,
144  * heating(0,3) */
145  chLabel[k] = "Hion";
146  }
147  else if( i == 0 && j == 7 )
148  {
149  /* UTA ionization heating(0,7) */
150  chLabel[k] = " UTA";
151  }
152  else if( i == 0 && j == 8 )
153  {
154  /* thermal.heating(0,8) is heating due to collisions within
155  * X of H2, code var hmi.HeatH2Dexc_used */
156  chLabel[k] = "H2vH";
157  }
158  else if( i == 0 && j == 17 )
159  {
160  /* thermal.heating(0,17) is heating due to photodissociation
161  * heating of X within H2,
162  * code var hmi.HeatH2Dish_used */
163  chLabel[k] = "H2dH";
164  }
165  else if( i == 0 && j == 9 )
166  {
167  /* CO dissociation, co.CODissHeat, heating(0,9) */
168  chLabel[k] = "COds";
169  }
170  else if( i == 0 && j == 20 )
171  {
172  /* extra heat thermal.heating(0,20)*/
173  chLabel[k] = "extH";
174  }
175  else if( i == 0 && j == 21 )
176  {
177  /* pair heating thermal.heating(0,21)*/
178  chLabel[k] = "pair";
179  }
180  else if( i == 0 && j == 11 )
181  {
182  /* free free heating, heating(0,11) */
183  chLabel[k] = "H FF";
184  }
185  else if( i == 0 && j == 12 )
186  {
187  /* heating coolant (not line), physical cooling process, often a bug, heating(0,12) */
188  chLabel[k] = "Hcol";
189  }
190  else if( i == 0 && j == 13 )
191  {
192  /* grain photoelectric effect, heating(0,13) */
193  chLabel[k] = "GrnP";
194  }
195  else if( i == 0 && j == 14 )
196  {
197  /* grain collisions, heating(0,14) */
198  chLabel[k] = "GrnC";
199  }
200  else if( i == 0 && j == 15 )
201  {
202  /* H- heating, heating(0,15) */
203  chLabel[k] = "H- ";
204  }
205  else if( i == 0 && j == 16 )
206  {
207  /* H2+ heating, heating(0,16) */
208  chLabel[k] = "H2+ ";
209  }
210  else if( i == 0 && j == 18 )
211  {
212  /* H2 photoionization heating, heating(0,18) */
213  chLabel[k] = "H2ph";
214  }
215  else if( i == 0 && j == 19 )
216  {
217  /* Compton heating, heating(0,19) */
218  chLabel[k] = "Comp";
219  }
220  else if( i == 0 && j == 22 )
221  {
222  /* line heating, heating(0,22) */
223  chLabel[k] = "line";
224  }
225  else if( i == 0 && j == 23 )
226  {
227  /* iso-sequence line heating - all elements together,
228  * heating(0,23) */
229  chLabel[k] = "Hlin";
230  }
231  else if( i == 0 && j == 24 )
232  {
233  /* charge transfer heating, heating(0,24) */
234  chLabel[k] = "ChaT";
235  }
236  else if( i == 1 && j == 3 )
237  {
238  /* helium triplet line heating, heating(1,3) */
239  chLabel[k] = "He3l";
240  }
241  else if( i == 1 && j == 5 )
242  {
243  /* advective heating, heating(1,5) */
244  chLabel[k] = "adve";
245  }
246  else if( i == 1 && j == 6 )
247  {
248  /* cosmic ray heating thermal.heating(1,6)*/
249  chLabel[k] = "CR H";
250  }
251  else if( i == 25 && j == 27 )
252  {
253  /* Fe 2 line heating, heating(25,27) */
254  chLabel[k] = "Fe 2";
255  }
256  else
257  {
258  ostringstream oss;
259  oss << "[" << i << "][" << j << "]";
260  chLabel[k] = oss.str();
261  }
262  }
263 
264  /* now sort by decreasing importance */
265  /*spsort netlib routine to sort array returning sorted indices */
266  UNUSED int nFail;
267  spsort(/* input array to be sorted */
268  &SaveVal[0],
269  /* number of values in x */
270  ipnt,
271  /* permutation output array */
272  &ipOrdered[0],
273  /* flag saying what to do - 1 sorts into increasing order, not changing
274  * the original routine */
275  -1,
276  /* error condition, should be 0 */
277  &nFail);
278 
279  /*>>chng 06 jun 06, change start of save to give same info as cooling
280  * as per comment by Yumihiko Tsuzuki */
281  /* begin the print out with zone number, total heating and cooling */
282  fprintf( io, "%.5e\t%.4e\t%.4e\t%.4e",
284  phycon.te,
285  heat_total,
286  cool_total );
287 
288  /* we only want to print the IPRINT strongest of the group */
289  ipnt = MIN2( ipnt , IPRINT );
290 
291  for( long k=0; k < ipnt; k++ )
292  {
293  int ip = ipOrdered[k];
294  i = ipsave[ip];
295  j = jpsave[ip];
296  ASSERT( i<LIMELM && j<LIMELM );
297  if(k > 4 && safe_div( thermal.heating(i,j), heat_total, 0. ) < save.WeakHeatCool )
298  break;
299  fprintf( io, "\t%s\t%.7f ",
300  chLabel[ip].c_str(), SaveVal[ip] );
301  }
302  fprintf( io, " \n" );
303 
304  /* a negative pointer in the heating array is probably a problem,
305  * indicating that some line has become a heat source */
306  bool lgHeatLine = false;
307 
308  /* check if any lines were major heat sources */
309  for( i=0; i < ipnt; i++ )
310  {
311  /* heating(22,0) is line heating - identify line if important */
312  if( ipsave[ipOrdered[i]] == 0 && jpsave[ipOrdered[i]] == 22 )
313  lgHeatLine = true;
314  }
315 
316  if( lgHeatLine )
317  {
318  long level = -1;
319  /* a line was a major heat source - identify it */
320  TransitionProxy t = FndLineHt(&level);
321  if( safe_div( t.Coll().heat(), heat_total, 0. ) > 0.005 )
322  {
323  ASSERT( t.associated() );
324  double TauIn = t.Emis().TauIn();
325  double Pump = t.Emis().pump();
326  double EscP = t.Emis().Pesc();
327  double CS = t.Coll().col_str();
328  /* ratio of line to total heating */
329  double ColHeat = safe_div( t.Coll().heat(), heat_total, 0. );
330 
331  fprintf( io, " LHeat lv%2ld %s TIn%10.2e Pmp%9.1e EscP%9.1e CS%9.1e Hlin/tot%10.2e\n",
332  level, chLineLbl(t).c_str(), TauIn, Pump, EscP, CS, ColHeat );
333  }
334  }
335  return;
336 }
bool lgConvEden
Definition: conv.h:197
double htot
Definition: thermal.h:169
t_thermal thermal
Definition: thermal.cpp:6
void SaveHeat(FILE *io)
Definition: heat_save.cpp:22
double Cool()
Definition: dynamics.cpp:2205
string chLineLbl(const TransitionProxy &t)
Definition: transition.h:599
char chIonStage[LIMELM+1][CHARS_ION_STAGE]
Definition: elementnames.h:29
const realnum SMALLFLOAT
Definition: cpu.h:246
static const int IPRINT
Definition: heat_save.cpp:18
bool lgConvPres
Definition: conv.h:194
t_conv conv
Definition: conv.cpp:5
t_phycon phycon
Definition: phycon.cpp:6
FILE * ioQQQ
Definition: cddefines.cpp:7
bool lgConvIoniz() const
Definition: conv.h:108
t_dynamics dynamics
Definition: dynamics.cpp:42
#define MIN2(a, b)
Definition: cddefines.h:807
t_dense dense
Definition: global.cpp:15
bool associated() const
Definition: transition.h:54
t_elementnames elementnames
Definition: elementnames.cpp:5
double Heat()
Definition: dynamics.cpp:2191
double xIonDense[LIMELM][LIMELM+1]
Definition: dense.h:135
realnum WeakHeatCool
Definition: save.h:470
double & heat() const
Definition: collision.h:224
char chClntLab[NCOLNT][NCOLNT_LAB_LEN+1]
Definition: thermal.h:108
EmissionList::reference Emis() const
Definition: transition.h:447
const TransitionProxy FndLineHt(long int *level)
float realnum
Definition: cddefines.h:124
realnum & Pesc() const
Definition: emission.h:568
sys_float safe_div(sys_float x, sys_float y, sys_float res_0by0)
Definition: cddefines.h:1015
double depth_mid_zone
Definition: radius.h:31
t_radius radius
Definition: radius.cpp:5
double heating(long nelem, long ion)
Definition: thermal.h:186
char chElementSym[LIMELM][CHARS_ELEMENT_SYM]
Definition: elementnames.h:25
#define ASSERT(exp)
Definition: cddefines.h:617
long int ncltot
Definition: thermal.h:106
realnum collam[NCOLNT]
Definition: thermal.h:103
bool lgConvTemp
Definition: conv.h:191
const int LIMELM
Definition: cddefines.h:307
realnum & col_str() const
Definition: collision.h:191
CollisionProxy Coll() const
Definition: transition.h:463
#define DEBUG_ENTRY(funcname)
Definition: cddefines.h:729
int fprintf(const Output &stream, const char *format,...)
Definition: service.cpp:1217
t_save save
Definition: save.cpp:5
double te
Definition: phycon.h:21
double heatnt[NCOLNT]
Definition: thermal.h:104
realnum & TauIn() const
Definition: emission.h:458
void spsort(realnum x[], long int n, long int iperm[], int kflag, int *ier)
Definition: service.cpp:1318
double ctot
Definition: thermal.h:130
#define UNUSED
Definition: cpu.h:14
double & pump() const
Definition: emission.h:518