00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "list_1d.hpp"
00039 #include "math_util.hpp"
00040 #include "global_params.hpp"
00041 #include "record_types.hpp"
00042 #include "messaging.hpp"
00043 #include "endl_precision.hpp"
00044 #include "endl_formats.hpp"
00045
00046 extern GlobalParameterClass Global;
00047 extern ENDLClass ENDL;
00048
00049 #define IS_ODD(n) ((n) & 1)
00050 #define IS_EVEN(n) (!(IS_ODD(n)))
00051 #define ENDL_FIELD_WIDTH ENDL_DATA_PRECISION+7
00052
00053 using namespace std;
00054
00055
00056
00057 double dd_list::interp(double E, dd_link& left_link,
00058 dd_link& right_link, int Interp_Type)
00059 {
00060
00061 if( Interp_Type == 1 )
00062 {
00063 return hist_interp( E, left_link, right_link );
00064 }
00065 else if( ( Interp_Type == 2 ) ||
00066 ( Interp_Type == -7 ) )
00067 {
00068 return linlin_interp( E, left_link, right_link );
00069 }
00070 else if( Interp_Type == 3 )
00071 {
00072 return loglin_interp( E, left_link, right_link );
00073 }
00074 else if( Interp_Type == 4 )
00075 {
00076 return linlog_interp( E, left_link, right_link );
00077 }
00078 else if( Interp_Type == 5 )
00079 {
00080 return loglog_interp( E, left_link, right_link );
00081 }
00082 else
00083 {
00084 Unimplemented("dd_list::interp",
00085 pastenum("Implement dd_list::interp 1 for Interp_Type: ",Interp_Type));
00086 }
00087 return -1;
00088 }
00089
00090 double dd_list::hist_interp( double E, dd_link& left_link,
00091 dd_link& right_link )
00092
00093 {
00094
00095 if( (E < left_link.x) || (E > right_link.x) ||
00096 (right_link.x < left_link.x) )
00097 {
00098 SevereError("dd_list::hist_interp","improper input in hist_interp 1");
00099 }
00100
00101 return left_link.y;
00102 }
00103
00104 double dd_list::linlin_interp( double E, dd_link& left_link,
00105 dd_link& right_link )
00106 {
00107 double E_diff = right_link.E_out() - left_link.E_out();
00108
00109
00110 if(E_diff == 0.0)
00111 {
00112 Warning("dd_list::linlin_interp","attempted division by 0 in linlin_interp 1");
00113 return (left_link.y+right_link.y)/2.0;
00114 }
00115
00116 double alpha = (E - left_link.E_out())/E_diff;
00117
00118
00119 if((alpha < 0.0) || (alpha > 1.0))
00120 {
00121 Warning("dd_list::linlin_interp",
00122 pastenum("extrapolation in linlin_interp: alpha=",alpha)
00123 +pastenum(" at E=",E));
00124 }
00125
00126 return (alpha*right_link.y +
00127 (1.0 - alpha)*left_link.y);
00128 }
00129
00130 double dd_list::loglin_interp( double E, dd_link& left_link,
00131 dd_link& right_link )
00132
00133 {
00134 double x_ratio = right_link.x / left_link.x;
00135
00136
00137 if( (x_ratio <= 0.0) || (x_ratio == 1.0) )
00138 {
00139 SevereError("dd_list::loglin_interp",
00140 pastenum("bad x_ratio in loglin_interp 1: ",x_ratio));
00141 }
00142
00143 double b = ( right_link.y - left_link.y ) / log( x_ratio );
00144
00145
00146 if( ( (E > left_link.x) && (E > right_link.x) ) ||
00147 ( (E < left_link.x) && (E < right_link.x) ) )
00148 {
00149 SevereError("dd_list::loglin_interp",
00150 "extrapolation in loglin_interp 1");
00151 }
00152
00153 return ( left_link.y + b*log( E / left_link.x ) );
00154 }
00155
00156 double dd_list::linlog_interp( double E, dd_link& left_link,
00157 dd_link& right_link )
00158
00159 {
00160
00161 if( (left_link.y <= 0.0) || (right_link.y <= 0.0) ||
00162 (left_link.x == right_link.x) )
00163 {
00164 SevereError("dd_list::linlog_interp",
00165 "Bad inputs to linlog_interp 1 ");
00166 }
00167
00168 double b = log( right_link.y / left_link.y ) /
00169 ( right_link.x - left_link.x );
00170
00171
00172 if( ( (E > left_link.x) && (E > right_link.x) ) ||
00173 ( (E < left_link.x) && (E < right_link.x) ) )
00174 {
00175 SevereError("dd_list::linlog_interp",
00176 "extrapolation in linlog_interp 1");
00177 }
00178
00179 return ( left_link.y * exp( b * ( E - right_link.x ) ) );
00180 }
00181
00182 double dd_list::loglog_interp( double E, dd_link& left_link,
00183 dd_link& right_link )
00184
00185 {
00186 if( (right_link.y <= 0.0) || (left_link.y <= 0.0) ||
00187 (right_link.x <= 0.0) || (left_link.x <= 0.0) ||
00188 (right_link.x == left_link.x) )
00189 {
00190 SevereError("dd_list::loglog_interp",
00191 "Bad inputs to loglog_interp 1 ");
00192 }
00193
00194 double b = log( right_link.y / left_link.y ) /
00195 log( right_link.x / left_link.x );
00196
00197
00198 if( ( (E > left_link.x) && (E > right_link.x) ) ||
00199 ( (E < left_link.x) && (E < right_link.x) ) )
00200 {
00201 SevereError("dd_list::loglog_interp",
00202 "extrapolation in loglog_interp 1");
00203 }
00204
00205 return ( left_link.y * exp( b*log( E / left_link.x ) ) );
00206 }
00207
00208
00209
00210
00211 double dd_list::zeroin(double (*func)(double, double),
00212 double target,
00213 dd_link& BB,
00214 dd_link& CC,
00215 double alpha,
00216 double tol)
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226 {
00227
00228 dd_link B = BB;
00229 dd_link C = CC;
00230
00231 const int MAX_ITER = 100;
00232
00233 double rel_tol;
00234 double diff_cb;
00235 double new_width;
00236
00237 double num;
00238 double denom;
00239
00240 int num_poor = 0;
00241
00242
00243 double use_tol = (tol < EPS) ? EPS : tol;
00244
00245
00246 double old_width = abs(C.x - B.x);
00247
00248
00249 B.y -= target;
00250 C.y -= target;
00251
00252
00253 double worse = (abs(B.y) < abs(C.y)) ? abs(C.y) : abs(B.y);
00254
00255
00256 dd_link A = C;
00257
00258 for(int count = 0; count < MAX_ITER; ++count)
00259 {
00260
00261 if(abs(C.y) < abs(B.y))
00262 {
00263 A = B;
00264 B = C;
00265 C = A;
00266 }
00267
00268
00269 diff_cb = 0.5*(C.x - B.x);
00270 new_width = abs(diff_cb);
00271 rel_tol = use_tol*abs(B.x) + EPS;
00272 if(new_width <= rel_tol)
00273 {
00274 if(B.y*C.y > 0.0)
00275 {
00276 SevereError("dd_list::zeroin","No root found" );
00277 }
00278 else if(abs(B.y) > worse)
00279 {
00280 SevereError("dd_list::zeroin","This looks like a pole.");
00281 }
00282 else
00283 {
00284 return B.x;
00285 }
00286 }
00287
00288
00289 num = (B.x - A.x)*B.y;
00290 denom = A.y - B.y;
00291
00292
00293 if(num < 0.0)
00294 {
00295 num *= -1;
00296 denom *= -1;
00297 }
00298
00299
00300 A = B;
00301
00302
00303 ++num_poor;
00304 if((num_poor >= 4) && (8.0*new_width < old_width))
00305 {
00306 num_poor = 0;
00307 old_width = new_width;
00308 }
00309
00310
00311 if(num_poor >= 4)
00312 {
00313 B.x = 0.5*(C.x + B.x);
00314 }
00315 else if(num < abs(denom)*rel_tol)
00316 {
00317
00318 B.x += (diff_cb > 0.0) ? rel_tol : -rel_tol;
00319 }
00320 else if(num < denom*diff_cb)
00321 {
00322
00323 B.x += num/denom;
00324 }
00325 else
00326 {
00327
00328 B.x = 0.5*(C.x + B.x);
00329 }
00330
00331
00332 B.y = func(B.x, alpha) - target;
00333
00334
00335 if(B.y == 0.0)
00336 {
00337 return B.x;
00338 }
00339
00340
00341 if(B.y*C.y > 0.0)
00342 {
00343 C = A;
00344 }
00345
00346 }
00347
00348
00349 Warning("dd_list::zeroin","Too many iterations in zeroin");
00350 return B.x;
00351 }
00352
00353
00354
00355 void dd_list::unit_base( )
00356
00357 {
00358 dd_list::iterator link = begin( );
00359 dd_list::iterator last_link = end( );
00360 --last_link;
00361
00362
00363 min_E_out = link->E_out( );
00364 max_E_out = last_link->E_out( );
00365
00366 double scale = max_E_out - min_E_out;
00367
00368
00369 for( ; link != end( ); ++link )
00370 {
00371
00372 link->E_out( ) = ( link->E_out( ) - min_E_out )/scale;
00373 }
00374 }
00375
00376 void dd_list::rescale( )
00377
00378 {
00379 double scale = max_E_out - min_E_out;
00380
00381
00382 for(dd_list::iterator link = begin( ); link != end( ); ++link)
00383 {
00384
00385 link->E_out( ) = min_E_out + scale*link->E_out( );
00386 }
00387 }
00388
00389 void dd_list::read_data( ifstream& inFile, int NP, double x_factor,
00390 double y_factor )
00391
00392 {
00393 string linebuff;
00394 string strbuff;
00395 dd_link XYdata;
00396
00397 for( int iNP=0; iNP < NP; iNP++ )
00398 {
00399 int iP=iNP % 3;
00400 if ( iP == 0 )
00401 {
00402 getline( inFile, linebuff);
00403 }
00404 strbuff = linebuff.substr(iP*22, 22);
00405 read_dd(&strbuff, &XYdata.x, &XYdata.y );
00406
00407 XYdata.x *= x_factor;
00408 XYdata.y *= y_factor;
00409 insert(end(), XYdata);
00410 }
00411 }
00412
00413 void dd_list::print()
00414
00415 {
00416 cout.setf(ios::scientific,ios::floatfield);
00417
00418
00419 for(dd_list::iterator link = begin(); link != end();
00420 ++link)
00421 {
00422 cout << ENDL.data( link->x, link->y ) << endl;
00423 }
00424 cout << endl;
00425 }
00426
00427
00428
00429 bool dd_list::needs_widening( )
00430 {
00431 dd_list::iterator itr = begin();
00432 double last_x=itr->x;
00433 ++itr;
00434 for(; itr!=end(); ++itr)
00435 {
00436 if (itr->x >= last_x+ENDL_EPSILON(last_x)) return true;
00437 }
00438 return false;
00439 }
00440
00441
00442
00443 void dd_list::widen_jumps( double cluster_min )
00444 {
00445
00446 double local_eps, jump_width;
00447
00448
00449 dd_list::iterator cluster_start = begin();
00450 dd_list::iterator cluster_end = begin();
00451 dd_list::iterator this_link = begin();
00452 int cluster_size=1;
00453
00454 for( ++this_link; this_link != end( ); ++this_link )
00455 {
00456
00457 local_eps = ENDL_EPSILON( cluster_start->x );
00458 jump_width = ENDL_JUMP_WIDTH( cluster_start->x );
00459
00460
00461 if( abs( this_link->x - cluster_end->x ) <= local_eps )
00462 {
00463 cluster_end = this_link;
00464 ++cluster_size;
00465 }
00466
00467 else
00468 {
00469 if ( cluster_size > 1 )
00470 widen_cluster( cluster_start, cluster_end, cluster_size, jump_width, cluster_min );
00471
00472 cluster_start = ++cluster_end;
00473 cluster_size = 1;
00474 }
00475 }
00476
00477 if ( cluster_size > 1 )
00478 widen_cluster( cluster_start, cluster_end, cluster_size, jump_width, cluster_min );
00479 }
00480
00481
00482
00483 void dd_list::widen_cluster( dd_list::iterator cluster_start,
00484 dd_list::iterator cluster_end, int cluster_size, double jump_width, double cluster_min )
00485 {
00486
00487 if( ( cluster_size == 1 ) || ( cluster_start==cluster_end ) ) return;
00488 if ( cluster_size>4 )
00489 {
00490 Warning("dd_list::widen_cluster",pastenum("Found ",cluster_size)+
00491 pastenum(" links in a cluster, check ENDL_EPSILON and ENDL_JUMP_WIDTH values or the data is broken at x=",
00492 cluster_start->x));
00493 return;
00494 }
00495
00496 if ( cluster_start->x <= cluster_min+jump_width )
00497 {
00498 dd_list::iterator cluster_middle = cluster_start;
00499 for (int ijump = 1; ijump<=cluster_size; ++ijump)
00500 {
00501 ++cluster_middle;
00502 cluster_middle->x += static_cast<double>(ijump)*jump_width;
00503 }
00504 }
00505 else
00506 {
00507 switch (cluster_size)
00508 {
00509 case 2:
00510 cluster_start->x -= 0.5*jump_width;
00511 cluster_end->x += 0.5*jump_width;
00512 break;
00513 case 3:
00514 cluster_start->x -= jump_width;
00515 cluster_end->x += jump_width;
00516 break;
00517 case 4:
00518 {
00519 dd_list::iterator cluster_left = cluster_start;
00520 dd_list::iterator cluster_right = cluster_end;
00521 ++cluster_left;--cluster_right;
00522 cluster_start->x -= 1.5*jump_width;
00523 cluster_left->x -= 0.5*jump_width;
00524 cluster_right->x += 0.5*jump_width;
00525 cluster_end->x += 1.5*jump_width;
00526 }
00527 break;
00528 default:
00529 Warning("dd_list::widen_cluster",pastenum("Found ",cluster_size)+
00530 pastenum(" links in a cluster, check ENDL_EPSILON and ENDL_JUMP_WIDTH values or the data is broken at x=",
00531 cluster_start->x));
00532 return;
00533 }
00534 }
00535 }
00536
00537
00538 void dd_list::thinit()
00539
00540 {
00541
00542 dd_list::iterator left_link;
00543 dd_list::iterator mid_link;
00544 dd_list::iterator right_link;
00545 dd_list::iterator all_done;
00546 bool thin_ok;
00547 bool do_thin;
00548 bool prev_thin;
00549 const double cut_off = Global.Value("cut_off_1d");
00550 const double tol_1d = Global.Value("tol_1d");
00551
00552
00553 all_done = end();
00554 --all_done;
00555
00556
00557 double noise = 0.0;
00558
00559 if( ( ENDL.F != 12 ) || ( ENDL.F != 13 ) )
00560 {
00561 for(left_link = begin(); left_link != all_done; ++left_link)
00562 {
00563 if(abs(left_link->y) > noise)
00564 {
00565 noise = abs(left_link->y);
00566 }
00567 }
00568 noise *= cut_off;
00569 }
00570
00571
00572 for(left_link = begin(); left_link != all_done; ++left_link)
00573 {
00574
00575 mid_link = left_link;
00576 ++mid_link;
00577 right_link = mid_link;
00578 ++right_link;
00579 if((mid_link == end()) || (right_link == end()))
00580 {
00581 return;
00582 }
00583
00584
00585 prev_thin = false;
00586
00587
00588 for( ; right_link != end(); ++right_link)
00589 {
00590
00591 do_thin = false;
00592
00593
00594 mid_link = left_link;
00595 for(++mid_link; mid_link != right_link; ++mid_link)
00596 {
00597 thin_ok = check_interp(left_link, mid_link, right_link,
00598 tol_1d, noise);
00599 if(thin_ok)
00600 {
00601
00602 do_thin = true;
00603 }
00604 else
00605 {
00606
00607 do_thin = false;
00608 break;
00609 }
00610 }
00611
00612
00613 if(do_thin)
00614 {
00615 prev_thin = true;
00616 }
00617 else
00618 {
00619 break;
00620 }
00621 }
00622
00623 dd_list::iterator left_next = left_link;
00624 ++left_next;
00625 dd_list::iterator right_prev = right_link;
00626 --right_prev;
00627
00628 if((prev_thin) && (!do_thin))
00629 {
00630
00631 erase(left_next, right_prev);
00632 }
00633 else if((do_thin) && (right_link == end()) &&
00634 (mid_link == all_done))
00635 {
00636
00637 erase(left_next, mid_link);
00638 }
00639 }
00640 }
00641
00642 void dd_list::copy( dd_list& list_2 )
00643
00644 {
00645
00646 for( dd_list::iterator link_ptr = list_2.begin();
00647 link_ptr != list_2.end(); ++link_ptr )
00648 {
00649 dd_link new_link = dd_link( link_ptr->x, link_ptr->y );
00650 insert( end(), new_link );
00651 }
00652 tag = list_2.tag;
00653 }
00654
00655 void dd_list::chop( double max_E )
00656
00657 {
00658 dd_list::iterator list_ptr = begin( );
00659 double dE = ENDL_EPSILON( max_E );
00660
00661
00662 if( begin( )->x > max_E )
00663 {
00664 SevereError( "dd_list::chop", "all energies too big" );
00665 }
00666
00667
00668 for( ; list_ptr != end( ); ++list_ptr )
00669 {
00670 if( list_ptr->x >= max_E + dE )
00671 {
00672 break;
00673 }
00674 }
00675
00676
00677 if( list_ptr != end( ) )
00678 {
00679 list_ptr->y = evaluate(max_E);
00680 list_ptr->x = max_E;
00681 ++list_ptr;
00682 if( list_ptr != end( ) ) erase( list_ptr, end( ) );
00683 }
00684
00685 }
00686
00687
00688 void dd_list::write_endl( int I )
00689 {
00690 if( !ENDL.write_file ) return;
00691
00692
00693
00694 chop( ENDL.Max_E_in );
00695
00696 ENDL.set_I_number(I);
00697
00698 fstream endl_file;
00699 string file_name = ENDL.file_name;
00700
00701 if(empty())
00702 {
00703 Warning("dd_list::write_endl","The file "+file_name+" is empty.");
00704 return;
00705 }
00706
00707 if ( ENDL.new_file() )
00708 {
00709 endl_file.open(file_name.c_str(),ios::out);
00710 Info("dd_list::write_endl","Opening ENDL file "+file_name);
00711 }
00712 else
00713 {
00714 endl_file.open(file_name.c_str(),ios::out|ios::app);
00715 Info("dd_list::write_endl","Appending ENDL file "+file_name);
00716 }
00717
00718
00719 endl_file<<ENDL.header_line_1<<"\n";
00720 endl_file<<ENDL.header_line_2<<"\n";
00721 endl_file.setf(ios::scientific,ios::floatfield);
00722
00723
00724
00725 double old_x = -2.0;
00726 bool list_needs_widening=false;
00727 for(dd_list::iterator link = begin(); link != end(); ++link)
00728 {
00729 if( (link->x == old_x) && (ENDL.F != 3) )
00730 {
00731 Warning("dd_list::write_endl",
00732 pastenum("Widening the jump in dd_list at: ",old_x)+
00733 pastenum(" x: " ,old_x));
00734 list_needs_widening=true;
00735 }
00736 old_x = link->x;
00737 }
00738 if (list_needs_widening) widen_jumps();
00739
00740
00741 for(dd_list::iterator link = begin(); link != end(); ++link)
00742 {
00743 endl_file<<ENDL.data( link->x, link->y )<<endl;
00744 }
00745
00746
00747 endl_file<<ENDL.eof_line<<endl;
00748
00749
00750 Info("dd_list::write_endl","Closing ENDL file "+file_name);
00751 endl_file.close();
00752 }
00753
00754
00755 dd_list& dd_list::operator+=(dd_list& list_2)
00756 {
00757
00758 fill_in_lists( *this, list_2 );
00759
00760
00761 dd_list::iterator L1 = begin();
00762 dd_list::iterator L2 = list_2.begin();
00763 for( ; L1 != end(); ++L1, ++L2 )
00764 {
00765 L1->y += L2->y;
00766 }
00767
00768 return *this;
00769 }
00770
00771
00772 dd_list& dd_list::line_sum( dd_list& list_2, double tol )
00773 {
00774 dd_link new_link;
00775 dd_list::iterator L1 = begin();
00776 dd_list::iterator L2 = list_2.begin();
00777 double E1 = L1->x;
00778 double E2 = L2->x;
00779 bool L1_done = empty( );
00780
00781
00782 for( ; L2 != list_2.end( ); )
00783 {
00784 if( L1_done || ( E2 < ( 1.0 - tol )*E1 ) )
00785 {
00786 new_link.x = E2;
00787 new_link.y = L2->y;
00788 insert( L1, new_link);
00789 ++L2;
00790 E2 = L2->x;
00791 }
00792 else if( !L1_done )
00793 {
00794 if( E1 < ( 1.0 - tol )*E2 )
00795 {
00796 ++L1;
00797 E1 = L1->x;
00798 }
00799 else
00800 {
00801 L1->y += L2->y;
00802 ++L1;
00803 ++L2;
00804 E1 = L1->x;
00805 E2 = L2->x;
00806 }
00807 if( L1 == end( ) )
00808 {
00809 L1_done = true;
00810 }
00811 }
00812 }
00813
00814 return *this;
00815 }
00816
00817
00818
00819
00820 void dd_list::join_lines( )
00821 {
00822 if( size( ) < 2 ){
00823 return;
00824 }
00825 dd_list::iterator this_ptr = begin();
00826 dd_list::iterator next_ptr = this_ptr;
00827 ++next_ptr;
00828 for( ; this_ptr != end( ); this_ptr = next_ptr, ++next_ptr )
00829 {
00830 if( this_ptr->x == next_ptr->x )
00831 {
00832 next_ptr->y += this_ptr->y;
00833 erase( this_ptr );
00834 }
00835 }
00836 }
00837
00838
00839 dd_list& dd_list::operator*=(double X)
00840 {
00841 for(dd_list::iterator L1 = begin(); L1 != end(); ++L1 )
00842 {
00843 L1->y *= X;
00844 }
00845 return *this;
00846 }
00847
00848
00849 dd_list& dd_list::operator*=(dd_list& list_2)
00850 {
00851 for( dd_list::iterator itr = begin() ; itr != end(); ++itr )
00852 {
00853 itr->y *= list_2.evaluate( itr->x );
00854 }
00855
00856 return *this;
00857 }
00858
00859
00860 dd_list& dd_list::operator/=(dd_list& list_2)
00861 {
00862 double y;
00863 for( dd_list::iterator itr = begin() ; itr != end(); ++itr )
00864 {
00865 y = list_2.evaluate( itr->x );
00866 if ( y == 0.0 )
00867 {
00868 if ( itr->y != 0.0 )
00869 Warning("dd_list::operator/=","division by 0 in operator /=");
00870 itr->y = 0;
00871 }
00872 else
00873 {
00874 itr->y /= y;
00875 }
00876 }
00877
00878 return *this;
00879 }
00880
00881
00882
00883 dd_list::iterator dd_list::find_next( double X )
00884 {
00885 if( empty( ) )
00886 {
00887 return end( );
00888 }
00889
00890 dd_list::iterator next_link;
00891 for( next_link = begin( ); next_link != end( ); ++next_link )
00892 {
00893 if( next_link->x >= X )
00894 {
00895 return next_link;
00896 }
00897 }
00898
00899
00900 return end( );
00901 }
00902
00903
00904
00905 double dd_list::evaluate( double X )
00906 {
00907 if( empty( ) )
00908 {
00909 SevereError("dd_list::evaluate",
00910 "Attempt to use evaluate on an empty list");
00911 }
00912
00913
00914 dd_list::iterator next_link = find_next( X );
00915
00916 if( ( next_link == begin( ) ) && ( next_link->x != X ) )
00917 {
00918 Warning("dd_list::evaluate",
00919 pastenum("Attempt to evaluate below the first link, x=",X));
00920 return next_link->y;
00921 }
00922 else if( next_link == end( ) )
00923 {
00924 Warning("dd_list::evaluate",
00925 pastenum("Attempt to evaluate past the last link, x=",X));
00926 return (--next_link)->y;
00927 }
00928
00929 if (next_link->x == X)
00930 {
00931 return next_link->y;
00932 }
00933 else
00934 {
00935 dd_list::iterator prev_link = next_link;
00936 --prev_link;
00937 return linlin_interp( X, *prev_link, *next_link );
00938 }
00939 }
00940
00941
00942
00943
00944 bool dd_list::check_interp(dd_list::iterator left_link,
00945 dd_list::iterator mid_link,
00946 dd_list::iterator right_link, double tol, double noise)
00947 {
00948
00949 double P_interp = linlin_interp( mid_link->E_out(), *left_link,
00950 *right_link );
00951
00952 return ( ( abs(P_interp - mid_link->y) < tol*mid_link->y ) ||
00953 ( ( abs(left_link->y) <= noise ) &&
00954 ( abs(mid_link->y) <= noise ) &&
00955 ( abs(right_link->y) <= noise ) ) );
00956 }
00957
00958
00959
00960 void dd_list::expand_interp( double Max_E )
00961 {
00962 if(INT[0] == -7)
00963 {
00964
00965 return;
00966 }
00967
00968 dd_list::iterator left_link = begin();
00969
00970 for(int count = 1; count <= NBT.size(); ++count)
00971 {
00972
00973 dd_list::iterator right_link;
00974 if(count == NBT.size())
00975 {
00976 right_link = end();
00977 --right_link;
00978 }
00979 else
00980 {
00981 int j = NBT[count] - NBT[count-1];
00982
00983
00984 right_link = left_link;
00985 for(int k = 0; k < j; ++k)
00986 {
00987 ++right_link;
00988 }
00989 }
00990
00991 switch(INT[count-1])
00992 {
00993 case 1:
00994 Hist_2_LinLin(left_link, right_link, Max_E);
00995 break;
00996 case 2:
00997 break;
00998 case 5:
00999 LogLog_2_LinLin(left_link, right_link);
01000 break;
01001 default:
01002 Unimplemented("dd_list::expand_interp",
01003 pastenum("Implement interpolation model ",INT[count-1]));
01004 }
01005
01006 left_link = right_link;
01007 }
01008
01009 INT[0] = -7;
01010 }
01011
01012
01013
01014
01015 void dd_list::expand_interp( int LEP, double Max_E )
01016 {
01017 if ( LEP == 2 )
01018 {
01019 }
01020 else if ( LEP == 1 )
01021 {
01022 dd_list::iterator data_ptr = begin( );
01023
01024
01025 if( data_ptr == end( ) )
01026 {
01027 return;
01028 }
01029
01030
01031 dd_list::iterator prev_ptr = data_ptr;
01032 ++data_ptr;
01033 dd_list::iterator next_ptr = data_ptr;
01034 ++next_ptr;
01035 for( ; data_ptr != end( );
01036 prev_ptr = data_ptr, data_ptr = next_ptr, ++next_ptr )
01037 {
01038 if( prev_ptr->y != data_ptr->y )
01039 {
01040
01041 double dE_L = data_ptr->x - prev_ptr->x;
01042 double dE_R = ( next_ptr == end( ) ) ? data_ptr->x :
01043 next_ptr->x - data_ptr->x;
01044 double dE = ( dE_L < dE_R ) ? dE_L : dE_R;
01045
01046 if(dE <= 0.0)
01047 {
01048 SevereError("dd_list::expand_interp","bad histogram data");
01049 }
01050
01051
01052 dE = ENDL_EPSILON( data_ptr->x );
01053
01054 if( data_ptr->x < Max_E - dE )
01055 {
01056 dd_link new_link;
01057 insert( data_ptr, new_link );
01058 dd_list::iterator new_ptr = data_ptr;
01059 --new_ptr;
01060
01061 new_ptr->x = data_ptr->x - dE;
01062 data_ptr->x += dE;
01063 new_ptr->y = prev_ptr->y;
01064 }
01065 else
01066 {
01067 data_ptr->x = Max_E;
01068 data_ptr->y = prev_ptr->y;
01069 erase( next_ptr, end( ) );
01070 break;
01071 }
01072 }
01073 }
01074 }
01075 else
01076 {
01077 Unimplemented("dd_list::expand_interp( int LEP, double Max_E )",
01078 pastenum("Implement interpolation type: ",LEP));
01079 }
01080 }
01081
01082
01083
01084
01085 void dd_list::Hist_2_LinLin( dd_list::iterator left_link, double Max_E )
01086 {
01087 if ( left_link == end() ) SevereError( "dd_list::Hist_2_LinLin",
01088 "Trying to expand links, but starting link == end()!");
01089
01090 dd_link new_link;
01091
01092 dd_list::iterator jump_link = left_link;
01093 ++jump_link;
01094
01095
01096 if( jump_link == end( ) )
01097 {
01098 if(left_link->x < Max_E)
01099 {
01100
01101 new_link.x = Max_E;
01102 new_link.y = left_link->y;
01103 insert( jump_link, new_link );
01104 }
01105 }
01106 else
01107 {
01108
01109 if( jump_link->y != left_link->y )
01110 {
01111
01112 dd_list::iterator right_link;
01113 right_link = jump_link;
01114 ++right_link;
01115 double dE_L = jump_link->x - left_link->x;
01116 double dE_R = ( right_link == end( ) ) ? jump_link->x :
01117 right_link->x - jump_link->x;
01118 double dE = ( dE_L < dE_R ) ? dE_L : dE_R;
01119
01120
01121 double dEmin = ENDL_EPSILON( jump_link->x );
01122
01123 if( dE < 0.0 )
01124 {
01125 SevereError("dd_list::Hist_2_LinLin","energies out of order");
01126 }
01127
01128
01129 if( dE_R <= dEmin )
01130 {
01131 jump_link->x = right_link->x - dEmin;
01132 jump_link->y = left_link->y;
01133 }
01134 else if( dE > dEmin )
01135 {
01136
01137 new_link.x = jump_link->x - dEmin;
01138 new_link.y = left_link->y;
01139 insert( jump_link, new_link );
01140 jump_link->x += dEmin;
01141 }
01142 }
01143 }
01144 }
01145
01146
01147
01148
01149 void dd_list::Hist_2_LinLin( dd_list::iterator first_link,
01150 dd_list::iterator last_link, double Max_E )
01151 {
01152 dd_list::iterator next_link = first_link;
01153 ++next_link;
01154 for ( dd_list::iterator this_link = first_link; this_link != last_link;
01155 this_link = next_link, ++next_link )
01156 {
01157 if( this_link == end( ) )
01158 {
01159 SevereError("dd_list::Hist_2_LinLin","bad link");
01160 }
01161 Hist_2_LinLin( this_link, Max_E );
01162 }
01163 }
01164
01165
01166
01167
01168 void dd_list::LogLog_2_LinLin(dd_list::iterator left_link)
01169 {
01170 double tol = Global.Value("log_log_tol");
01171
01172 dd_list::iterator right_link = left_link;
01173 ++right_link;
01174 int num_add;
01175
01176
01177 if ( left_link->x <= 0.0 || right_link->x <= 0.0 )
01178 {
01179 SevereError("dd_list::LogLog_2_LinLin","x must be larger than zero!");
01180 }
01181
01182 if ( left_link->y <= 0.0 || right_link->y <= 0.0 )
01183 {
01184 SevereError("dd_list::LogLog_2_LinLin","y must be larger than zero!");
01185 }
01186
01187 if ( left_link->x > right_link->x )
01188 {
01189 SevereError("dd_list::LogLog_2_LinLin","x values not ascending!");
01190 }
01191
01192
01193 double alpha = log(right_link->y/left_link->y)/
01194 log(right_link->x/left_link->x);
01195
01196
01197 double xi = right_link->x/left_link->x;
01198 double maxE = maxE_loglog( xi, alpha );
01199 if(maxE <= tol)
01200 {
01201 num_add = 0;
01202 }
01203 else
01204 {
01205
01206 dd_link low_link = dd_link(1.0, 0.0);
01207 dd_link high_link = dd_link(xi, maxE);
01208
01209
01210 double delta = sqrt(8.0*tol/abs(alpha*(alpha - 1.0)));
01211 if(1.0 + delta < xi)
01212 {
01213 maxE = maxE_loglog( 1.0 + delta, alpha );
01214 if(maxE < tol)
01215 {
01216
01217 low_link.x = 1.0 + delta;
01218 low_link.y = maxE;
01219 }
01220 else
01221 {
01222
01223 high_link.x = 1.0 + delta;
01224 high_link.y = maxE;
01225 }
01226 }
01227
01228 xi = zeroin(&maxE_loglog, tol, low_link, high_link, alpha, 0.00001);
01229
01230 num_add = static_cast<int>
01231 (floor(log(right_link->x/left_link->x)/log(xi)));
01232
01233
01234 double eta = pow(right_link->x/left_link->x, 1.0/(num_add + 1.0));
01235 double eta_alpha = pow(eta, alpha);
01236 double x = left_link->x;
01237 double y = left_link->y;
01238 for(int count = 0; count < num_add; ++count)
01239 {
01240 x *= eta;
01241 y *= eta_alpha;
01242 dd_link link;
01243 link.x = x;
01244 link.y = y;
01245 insert(right_link, link);
01246 }
01247 }
01248 }
01249
01250
01251
01252
01253 void dd_list::LogLog_2_LinLin(dd_list::iterator first_link,
01254 dd_list::iterator last_link)
01255 {
01256 dd_list::iterator next_link = first_link;
01257 ++next_link;
01258 for (dd_list::iterator this_link = first_link; this_link != last_link;
01259 this_link = next_link, ++next_link)
01260 {
01261 if((this_link == 0) || (this_link == end()))
01262 {
01263 SevereError("dd_list::LogLog_2_LinLin"," bad link");
01264 }
01265 LogLog_2_LinLin(this_link);
01266 }
01267 }
01268
01269
01270
01271
01272 void fill_in_lists( dd_list& list_1, dd_list& list_2 )
01273 {
01274 if( list_1.empty( ) || list_2.empty( ) )
01275 {
01276 cout << "list_1\n";
01277 list_1.print( );
01278 cout << "list_2\n";
01279 list_2.print( );
01280 SevereError("fill_in_lists","attempt to fill in an empty 1d list");
01281 }
01282
01283
01284 list_1.widen_jumps( );
01285 list_2.widen_jumps( );
01286
01287
01288 dd_list::iterator L1 = list_1.begin( );
01289 dd_list::iterator L2 = list_2.begin( );
01290
01291 double E1 = L1->x;
01292 double E2 = L2->x;
01293
01294 if( E1 < E2 )
01295 {
01296 list_2.pad_head( E1 );
01297 }
01298 else if( E2 < E1 )
01299 {
01300 list_1.pad_head( E2 );
01301 }
01302
01303
01304 L1 = list_1.end( );
01305 L2 = list_2.end( );
01306 --L1;
01307 --L2;
01308
01309 E1 = L1->x;
01310 E2 = L2->x;
01311
01312 if( E1 > E2 )
01313 {
01314 list_2.pad_tail( E1 );
01315 }
01316 else if( E2 > E1 )
01317 {
01318 list_1.pad_tail( E2 );
01319 }
01320
01321
01322 list< double > E_in_list;
01323 list_1.collect_E_in( E_in_list );
01324 list_2.collect_E_in( E_in_list );
01325
01326
01327 E_in_list.sort( );
01328
01329
01330 E_in_list.unique( );
01331 list_1.unique( );
01332 list_2.unique( );
01333
01334
01335 list_1.fill_with( E_in_list );
01336 list_2.fill_with( E_in_list );
01337 }
01338
01339
01340
01341 void dd_list::collect_E_in( list< double >& E_in_list )
01342 {
01343 for( dd_list::iterator this_E = begin( ); this_E != end( );
01344 ++this_E )
01345 {
01346 double E_in = this_E->E_in( );
01347 E_in_list.push_back( E_in );
01348 }
01349 }
01350
01351
01352
01353 void dd_list::pad_head( double E0 )
01354 {
01355 dd_link new_link;
01356
01357 double first_E = begin( )->x;
01358
01359 double dE = ENDL_EPSILON( first_E );
01360
01361
01362 new_link.y = 0.0;
01363 if( ( begin( )->y != 0.0 ) && ( first_E - E0 > dE ) )
01364 {
01365 new_link.x = first_E - dE;
01366 push_front( new_link );
01367 }
01368
01369
01370 new_link.x = E0;
01371 push_front( new_link );
01372 }
01373
01374
01375
01376 void dd_list::pad_tail( double E0 )
01377 {
01378 dd_link new_link;
01379 dd_list::iterator L = end( );
01380 --L;
01381 double last_E = L->x;
01382
01383 double dE = ENDL_EPSILON( last_E );
01384
01385
01386 new_link.y = 0.0;
01387 if( ( L->y != 0.0 ) && ( E0 - last_E > dE ) )
01388 {
01389 new_link.x = last_E + dE;
01390 push_back( new_link );
01391 }
01392
01393
01394 new_link.x = E0;
01395 push_back( new_link );
01396 }
01397
01398
01399
01400 void dd_list::unique( )
01401 {
01402 dd_list::iterator this_link = begin( );
01403 dd_list::iterator prev_link = this_link;
01404 double local_epsilon;
01405
01406 for( ++this_link; this_link != end( );
01407 prev_link = this_link, ++this_link )
01408 {
01409 if( abs(this_link->x - prev_link->x) == local_epsilon )
01410 {
01411 this_link->y = (this_link->y + prev_link->y)/2.0;
01412 erase( prev_link );
01413 }
01414 }
01415 }
01416
01417
01418
01419 void dd_list::fill_with( list< double >& E_in_list )
01420 {
01421 dd_list::iterator this_link = begin( );
01422 dd_list::iterator prev_link = this_link;
01423
01424
01425 for( list< double >::iterator E_in_ptr = E_in_list.begin( );
01426 E_in_ptr != E_in_list.end( ); ++E_in_ptr )
01427 {
01428 double E_in = *E_in_ptr;
01429
01430
01431 if( this_link->x == E_in )
01432 {
01433 prev_link = this_link;
01434 ++this_link;
01435 }
01436 else
01437 {
01438
01439 dd_link new_link;
01440 new_link.x = E_in;
01441 new_link.y = linlin_interp( E_in, *prev_link, *this_link );
01442 insert( this_link, new_link );
01443 }
01444 }
01445 }