Main Page | Namespace List | Class Hierarchy | Class List | File List | Class Members | File Members | Related Pages

distrib_1d.cpp

Go to the documentation of this file.
00001 /*
00002  * ******** fete: From ENDF To ENDL *********
00003  * 
00004  * Copyright (c) 2006, The Regents of the University of California. 
00005  * All rights reserved.
00006  * 
00007  * Produced at the Lawrence Livermore National Laboratory. 
00008  * Written by David A. Brown, Gerry Hedstrom, Tony Hill
00009  * 
00010  * This file is part of fete v1.0  (UCRL-CODE-218718)
00011  * 
00012  * Please read the COPYING file for "Our Notice and GNU General 
00013  * Public License" in the root of this software distribution.  
00014  * 
00015  * This program is free software; you can redistribute it and/or modify 
00016  * it under the terms of the GNU General Public License (as published by 
00017  * the Free Software Foundation) version 2, dated June 1991. 
00018  * 
00019  * This program is distributed in the hope that it will be useful, 
00020  * but WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF 
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms 
00022  * and conditions of the GNU General Public License for more details. 
00023  * 
00024  * You should have received a copy of the GNU General Public License along 
00025  * with this program; if not, write to the Free Software Foundation, Inc., 
00026  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
00027  * 
00028  * $Revision: 1878 $
00029  * $Date: 2006-05-23 11:11:18 -0700 (Tue, 23 May 2006) $
00030  * $Author: dbrown $
00031  * $Id: distrib_1d.cpp 1878 2006-05-23 18:11:18Z dbrown $
00032  * 
00033  * ******** fete: From ENDF To ENDL *********
00034  */
00035 
00036 // implementation of the one_d_distrib class
00037 
00038 #include <cmath>   // math library
00039 
00040 #include "distrib_1d.hpp"
00041 #include "endl_formats.hpp"
00042 #include "global_params.hpp"
00043 #include "math_util.hpp"
00044 #include "record_types.hpp"
00045 #include "endl_precision.hpp"
00046 #include "bdfls_tools.hpp"
00047 
00048 extern GlobalParameterClass Global;
00049 extern ENDLClass ENDL;
00050 extern bdflsClass bdfls;  // for the data constants
00051 
00052 // *********** one_d_table class ***********************
00053 // ---------------- one_d_table::f --------------------
00054 double one_d_table::f( double e_out )
00055 // for lin-log or log-lin interpolation between links
00056 {
00057   double ans;
00058 
00059   if( interp_ == 3 ) // log-lin
00060   {
00061     ans = y_0_ + b_*log( e_out / x_0_ );
00062   }
00063   else if( interp_ == 4 ) // lin-log
00064   {
00065     ans = y_0_ * exp( b_ * ( e_out - x_0_ ) );
00066   }
00067   else
00068   {
00069     SevereError("one_d_table::f",
00070       pastenum("attempt to interpolate with type ", interp_ ) );
00071   }
00072   return ans;
00073 }
00074 // ----------- one_d_table::expand_interp --------------------
00075 void one_d_table::expand_interp( double Max_E )
00076 // a version of expand_interp which allows lin-log and log-lin
00077 // interpolation
00078 {
00079   bool special_interp = false;
00080 
00081   // test for lin-log or log-lin interpolation
00082   for( int j = 0; j < INT.size( ); ++j)
00083   {
00084     if( ( INT[ j ] == 3 ) || ( INT[ j ] == 4 ) )
00085     {
00086       special_interp = true;
00087       break;
00088     }
00089   }
00090 
00091   if( !special_interp )
00092   {
00093     // only lin-lin, histogram, or log-log (or INT > 10)
00094     dd_list::expand_interp( Max_E );
00095   }
00096   else
00097   {
00098     if(INT[0] == -7)
00099     {
00100       SevereError("one_d_table::expand_interp","expand_interp called twice");
00101     }
00102 
00103     dd_list::iterator left_link = begin();
00104 
00105     for(int count = 1; count <= NBT.size(); ++count)
00106     {
00107       // pointer to the end of this segment
00108       dd_list::iterator last_link;
00109       if(count == NBT.size())
00110       {
00111         last_link = end();
00112         --last_link;
00113       }
00114       else
00115       {
00116         int j = NBT[count] - NBT[count-1];
00117 
00118         // get the corresponding link
00119         last_link = left_link;
00120         for(int k = 0; k < j; ++k)
00121         {
00122           ++last_link;
00123         }
00124       }
00125 
00126       // convert to lin-lin one segment at a time
00127       for( dd_list::iterator this_link = left_link;
00128            this_link != last_link; ++this_link )
00129       {
00130         x_0_ = this_link->x;
00131         y_0_ = this_link->y;
00132         dd_list::iterator next_link = this_link;
00133         ++next_link;
00134 
00135         if( INT[count-1] == 3 )
00136         {
00137           // log-lin
00138           interp_ = 3;
00139           double x_ratio = next_link->x / x_0_;
00140 
00141           // check for division by 0 and bad logarithm
00142           if( (x_ratio <= 0.0) || (x_ratio == 1.0) )
00143           {
00144             SevereError("one_d_table::expand_interp",
00145               pastenum("bad x_ratio:",x_ratio));
00146           }
00147 
00148           b_ = ( next_link->y - y_0_ ) / log( x_ratio );
00149 
00150           thicken( this_link, next_link );
00151         }
00152         else if( INT[count-1] == 4 )
00153         {
00154           // lin-log
00155           interp_ = 4;
00156           // check for proper inputs
00157           if( (y_0_ <= 0.0) || (next_link->y <= 0.0) ||
00158             (next_link->x == x_0_) )
00159           {
00160             SevereError("one_d_table::expand_interp","Bad inputs");
00161           }
00162 
00163           b_ = log( next_link->y / y_0_ ) / ( next_link->x - x_0_ );
00164 
00165           thicken( this_link, next_link );
00166         }
00167       }
00168       // save for the next set
00169       left_link = last_link;
00170     }
00171     // flag to ensure that we don't do this twice on the same data
00172     INT[0] = -7;
00173   }
00174 }
00175 // ----------- one_d_table::copy ---------------------------
00176 void one_d_table::copy( one_d_table& list_2 )
00177 // Copies a list
00178 {
00179   dd_list::copy( list_2 );
00180   weight = list_2.weight;
00181   interp_type = list_2.interp_type;
00182 }
00183 // ----------- one_d_table::line_multiple ----------
00184 double one_d_table::line_multiple( )
00185 // This routine assumes that the list consists of pairs:
00186 // (energy for a gamma line, its multiplicity).
00187 // Returns the total multiplicity of the lines.
00188 {
00189   double mult = 0;
00190 
00191   for( one_d_table::iterator link_ptr = begin( );
00192        link_ptr != end( ); ++link_ptr )
00193   {
00194     mult += link_ptr->y;
00195   }
00196   return mult;
00197 }
00198 // ----------- one_d_table::list_interp --------------------
00199 void one_d_table::list_interp(double e_in, one_d_table& left_list,
00200   one_d_table& right_list)
00201 // Interpolate this list between left_list and right_list.
00202 {
00203   dd_list temp_list;
00204 
00205   if( !empty() )
00206   {
00207     SevereError("one_d_table::list_interp",
00208         "Trying to fill a one_d_table which has already been made");
00209   }
00210 
00211   if (( right_list.interp_type == 2 )
00212     ||( right_list.interp_type == 22 )) // lin-lin
00213   {
00214     double alpha = ( e_in - left_list.E_in( ) )/
00215       ( right_list.E_in( ) - left_list.E_in( ) );
00216     if( ( alpha <= 0.0 ) || ( alpha >= 1.0 ) )
00217     {
00218       SevereError("one_d_table::list_interp","Attempt to extrapolate in lin-lin");
00219     }
00220 
00221     // What we want is (1 - alpha)*left_list + alpha*right_list
00222     if( alpha >= 0.5 )
00223     {
00224       // start with right_list and add to it
00225       //  ( (1 - alpha)/alpha )*left_list
00226       copy( right_list );
00227       temp_list.copy( left_list );
00228       temp_list *= (1 - alpha)/alpha;
00229       *this += temp_list;
00230     }
00231     else
00232     {
00233       // start with left_list and add to it
00234       //  ( alpha/(1 - alpha) )*right_list
00235       copy( left_list );
00236       temp_list.copy( right_list );
00237       temp_list *= alpha/(1 - alpha);
00238       *this += temp_list;
00239     }
00240     E_in( ) = e_in;  // reset the incident energy tag
00241     renorm( );
00242     weight = ( 1 - alpha )*left_list.weight +
00243       alpha*right_list.weight;
00244   }
00245   else if ( right_list.interp_type == 1 ) // histogram
00246   {
00247     double alpha = ( e_in - left_list.E_in( ) )/
00248       ( right_list.E_in( ) - left_list.E_in( ) );
00249     if( ( alpha <= 0.0 ) || ( alpha >= 1.0 ) )
00250     {
00251       SevereError("one_d_table::list_interp"," Attempt to extrapolate a histogram");
00252     }
00253 
00254     // just make a copy of left_list
00255     copy( left_list );
00256     E_in( ) = e_in;  // reset the incident energy tag
00257     weight = ( 1 - alpha )*left_list.weight +
00258       alpha*right_list.weight;
00259   }
00260   else if ( right_list.interp_type == 3 ) // log-lin
00261   {
00262     double left_e_in = left_list.E_in( );
00263     double right_e_in = right_list.E_in( );
00264     // start with a copy of left_list
00265     copy( left_list );
00266     E_in( ) = e_in;  // reset the incident energy tag
00267     // insert links at E_out values for right_list
00268     fill_in_lists( *this, right_list );
00269 
00270     // loop through the links
00271     for( dd_list::iterator list_ptr = begin( );
00272         list_ptr != end( ); ++list_ptr )
00273     {
00274       double e_out = list_ptr->x;
00275       list_ptr->y = Log_Lin( e_in, left_e_in, left_list.evaluate( e_out ),
00276         right_e_in, right_list.evaluate( e_out ) );
00277     }
00278     thinit( );
00279     renorm( );
00280     if(bin_interp)
00281     {
00282       // We check interpolation using equiprobabile bins,
00283       // not unit-based interpolation.
00284       get_bins( );
00285     }
00286   }
00287   else
00288   {
00289     double left_e_in = left_list.E_in( );
00290     double right_e_in = right_list.E_in( );
00291     // start with a copy of left_list
00292     copy( left_list );
00293     E_in( ) = e_in;  // reset the incident energy tag
00294     // insert links at E_out values for right_list
00295     fill_in_lists( *this, right_list );
00296 
00297     // loop through the links
00298     for( dd_list::iterator list_ptr = begin( );
00299         list_ptr != end( ); ++list_ptr )
00300     {
00301       double e_out = list_ptr->x;
00302       list_ptr->y = Lin_Log( e_in, left_e_in, left_list.evaluate( e_out ),
00303         right_e_in, right_list.evaluate( e_out ) );
00304     }
00305     thinit( );
00306     renorm( );
00307     if(bin_interp)
00308     {
00309       // We check interpolation using equiprobabile bins,
00310       // not unit-based interpolation.
00311       get_bins( );
00312     }
00313   }
00314   interp_type = right_list.interp_type;
00315 }
00316 // ---------------- one_d_table::read_data --------------------------
00317 void one_d_table::read_data( int NP, ENDF_file& inFile, double max_E )
00318 // Read in 2-column data
00319 {
00320   string linebuff;  // the input string
00321   string strbuff;   // a substring
00322   bool first_energy = true;
00323   bool done = false;
00324   double dE = ENDL_EPSILON( max_E );
00325 
00326   for( int iNP=0; iNP < NP; iNP++ ) //Loop over NP data pairs
00327   { 
00328     int iP=iNP % 3;  //There are 3 pairs per line
00329     if ( iP == 0 ) getline( inFile, linebuff); //Read in new line
00330     for( int i=0+iP*22; i<22+iP*22; i=i+22 ) //Grab the right pair
00331     { 
00332       strbuff = linebuff.substr(i,22);
00333     }
00334     double X,Y; //Real variables we will put the data pair
00335     read_dd(&strbuff, &X, &Y );
00336     if ( X==-999. || Y==-999. ) //read_PAIR sends -999. if problem
00337     {
00338       SevereError("one_d_table::read_data","read_PAIR failed!");
00339     }
00340     else 
00341     {
00342       dd_link XYdata;
00343       XYdata.E_in() = X*ENDL.eV2MeV; //convert to MeV
00344       XYdata.x_sec() = Y;
00345       if( !done )
00346       {
00347         insert(end(), XYdata);
00348         if( XYdata.E_in() > max_E - dE )
00349         {
00350           done = true;
00351         }
00352 
00353         if ( first_energy )  //Save the first energy for later use
00354         {
00355           first_energy =  false ;
00356           min_E_out = XYdata.E_in();  // for unit-base interpolation
00357           // is this a cross section table?
00358           if( ENDL.F == 3 )
00359           {
00360             ENDL.threshold = X*ENDL.eV2MeV; //convert to MeV
00361             if( ENDL.threshold > ENDL.Max_E_in )
00362             {
00363               ENDL.write_file = false;
00364               Info("one_d_table::read_data",
00365                  "Omit reaction: threshold above Max_energy");
00366             }
00367           }
00368         }
00369       }
00370     }
00371   }
00372   // There may be some double-valued cross sections so get rid of them
00373   widen_jumps();
00374 
00375   // This could be a probability table at one incident energy
00376   if( ENDL.F > 3 )
00377   {
00378     one_d_table::iterator last_link = end( );
00379     --last_link;
00380     double last_E = last_link->x;
00381     if( last_E > max_E )
00382     {
00383       chop( max_E );
00384       last_E = max_E;
00385     }
00386     max_E_out = max_E;  // for unit-base interpolation
00387   }
00388 }
00389 
00390 // *********** one_d_evap class ***********************
00391 // ----------- one_d_evap constructor -----------------
00392 // default constructor
00393 one_d_evap::one_d_evap()
00394 {
00395 }
00396 // ----------- one_d_evap::initiate --------------------
00397 void one_d_evap::initiate(double e_in, double Theta, double U)
00398 // set the parameters for the evaporation model
00399 {
00400   // to make a delta function right at threshold
00401   double EPSILON = 1.0e-10;
00402 
00403   // are we below the threshold?
00404   if( e_in < ENDL.threshold )
00405   {
00406     Info("one_d_evap::initiate",
00407       pastenum("e_in = ", e_in)+pastenum(" below threshold.  Threshold is ",ENDL.threshold));
00408   }
00409 
00410   E_in() = e_in;
00411   // for unit-base interpolation
00412   min_E_out = 0.0;
00413   max_E_out = E_in() - U;
00414   if( max_E_out > ENDL.Max_E_out )
00415   {
00416     max_E_out = ENDL.Max_E_out;
00417   }
00418 
00419   Theta_ = Theta;
00420   U_ = U;
00421 
00422   if ( max_E_out <= 0.0 )
00423   {
00424     // below model threshold OK in multiple models if weight = 0
00425     // make a dummy list
00426     dd_link link( 0.0, 0.0 );  // for creating new links
00427     insert(end(), link);
00428     link.x = EPSILON;
00429     link.y = 1.0;
00430     insert(end(), link);
00431   }
00432   else
00433   {
00434     // this is a real list
00435     extrema();  // start the list by inserting the extrema
00436     thicken();
00437   }
00438   renorm();
00439 
00440   // If we are checking interpolation using the equiprobable
00441   // bins, get the bins.
00442   if(bin_interp)
00443   {
00444     get_bins();
00445   }
00446 }
00447 // ----------- one_d_evap::extrema -----------
00448 void one_d_evap::extrema()
00449 // Start a list for an evaporation model by inserting the
00450 // maximum, minimum and inflection point
00451 {
00452   dd_link link;  // for creating new links
00453 
00454   // the maximum secondary energy
00455   double E_max = max_E_out;
00456 
00457   // exit if we are below threshold
00458   if(E_max <= 0.0)
00459   {
00460     return;
00461   }
00462 
00463   // initialize the list with 0 secondary energy
00464   link = dd_link(0.0, f(0.0));
00465   insert(end(), link);
00466 
00467   // do we include the maximum at E = Theta?
00468   double next_E = Theta_;
00469   if(E_max > next_E)
00470   {
00471     link = dd_link(next_E, f(next_E));
00472     insert(end(), link);
00473   }
00474 
00475   // do we include the inflection point at E = 2*Theta?
00476   next_E = 2*Theta_;
00477   if(E_max > next_E)
00478   {
00479     link = dd_link(next_E, f(next_E));
00480     insert(end(), link);
00481   }
00482 
00483   // end the list with E_max
00484   link = dd_link(E_max, f(E_max));
00485   insert(end(), link);
00486 }
00487 // ----------- one_d_evap::copy ---------------------------
00488 void one_d_evap::copy( one_d_evap& list_2 )
00489 // Copies a list
00490 {
00491   dd_list::copy( list_2 );
00492   weight = list_2.weight;
00493   interp_type = list_2.interp_type;
00494   U_ = list_2.U_;
00495   Theta_ = list_2.Theta_;
00496 }
00497 // -------------- one_d_evap::f -----------------
00498 double one_d_evap::f(double E_out)
00499 // f = E'*exp{-E'/Theta}, 0 <= E' <= E - U
00500 {
00501   double E_max = E_in() - U_;
00502   const double eps = 1.0e-12;
00503 
00504   if((E_out < 0.0) || (E_out > E_max*(1 + eps)))
00505   {
00506     // we are outside the range
00507     Warning("one_d_evap::f",pastenum("E_out: ",E_out)+
00508         " outside range for evaporation function");
00509     return 0.0;
00510   }
00511   else
00512   {
00513     return E_out*exp(-E_out/Theta_);
00514   }
00515 }
00516 // ----------- one_d_evap::list_interp --------------------
00517 void one_d_evap::list_interp(double e_in, one_d_evap& left_list,
00518   one_d_evap& right_list)
00519 // Interpolate this list between left_list and right_list.
00520 {
00521   if(!empty())
00522   {
00523     SevereError("one_d_evap::list_interp",
00524         "Trying to fill a one_d_evap which has already been made");
00525   }
00526   // set the parameters
00527   double Theta;
00528   double U;
00529   if ( right_list.interp_type == 2 ) // lin-lin
00530   {
00531     Theta = Lin_Lin( e_in, left_list.E_in(), left_list.Theta_,
00532       right_list.E_in(), right_list.Theta_);
00533     U = Lin_Lin( e_in, left_list.E_in(), left_list.U_,
00534       right_list.E_in(), right_list.U_);
00535   }
00536   else if ( right_list.interp_type == 3 ) // log-lin
00537   {
00538     Theta = Log_Lin( e_in, left_list.E_in(), left_list.Theta_,
00539       right_list.E_in(), right_list.Theta_);
00540     U = Log_Lin( e_in, left_list.E_in(), left_list.U_,
00541       right_list.E_in(), right_list.U_);
00542   }
00543   else if ( right_list.interp_type == 4 ) // lin-log
00544   {
00545     Theta = Lin_Log( e_in, left_list.E_in(), left_list.Theta_,
00546       right_list.E_in(), right_list.Theta_);
00547     U = Lin_Log( e_in, left_list.E_in(), left_list.U_,
00548       right_list.E_in(), right_list.U_);
00549   }
00550   else if ( right_list.interp_type == 5 ) // log-log
00551   {
00552     Theta = Log_Log( e_in, left_list.E_in(), left_list.Theta_,
00553       right_list.E_in(), right_list.Theta_);
00554     U = Log_Log( e_in, left_list.E_in(), left_list.U_,
00555       right_list.E_in(), right_list.U_);
00556   }
00557   else
00558   {
00559     SevereError("one_d_evap::list_interp", 
00560         pastenum("Implement for type: ",right_list.interp_type));
00561   }
00562   interp_type = right_list.interp_type;
00563 
00564   // fill out the list
00565   initiate(e_in, Theta, U);
00566 }
00567 // *********** one_d_Maxwell class ***********************
00568 // ----------- one_d_Maxwell constructor -----------------
00569 // default constructor
00570 one_d_Maxwell::one_d_Maxwell()
00571 {
00572 }
00573 // ----------- one_d_Maxwell::initiate --------------------
00574 void one_d_Maxwell::initiate(double e_in, double Theta, double U)
00575 // set the parameters for the Maxwell model
00576 {
00577   // to increase the incident energy right at threshold
00578   double EPSILON = Global.Value( "mf5_shift" );
00579 
00580   // are we right at the threshold?
00581   if(e_in <= ENDL.threshold)
00582   {
00583     // go a little above it to avoid getting a delta function
00584     E_in() = e_in*( 1 + EPSILON );
00585   }
00586   else
00587   {
00588     E_in() = e_in;
00589   }
00590   // for unit-base interpolation
00591   min_E_out = 0.0;
00592   max_E_out = E_in() - U;
00593   if( max_E_out > ENDL.Max_E_out )
00594   {
00595     max_E_out = ENDL.Max_E_out;
00596   }
00597 
00598   Theta_ = Theta;
00599   U_ = U;
00600 
00601   if ( max_E_out <= 0.0 )
00602   {
00603     // below model threshold OK in multiple models if weight = 0
00604     // make a dummy list
00605     dd_link link( 0.0, 0.0 );  // for creating new links
00606     insert(end(), link);
00607     link.x = EPSILON;
00608     link.y = 1.0;
00609     insert(end(), link);
00610   }
00611   else
00612   {
00613     // this is a real list
00614     extrema();  // start the list by inserting the extrema
00615     thicken();
00616   }
00617   renorm();
00618 
00619   // If we are checking interpolation using the equiprobable
00620   // bins, get the bins.
00621   if(bin_interp)
00622   {
00623     get_bins();
00624   }
00625 }
00626 // ----------- one_d_Maxwell::extrema -----------
00627 void one_d_Maxwell::extrema()
00628 // Start a list for an Maxwell model by inserting the
00629 // maximum, minimum and inflection point
00630 {
00631   dd_link link;  // for creating new links
00632 
00633   // the maximum secondary energy
00634   double E_max = max_E_out;
00635 
00636   // exit if we are below threshold
00637   if(E_max <= 0.0)
00638   {
00639     return;
00640   }
00641 
00642   // initialize the list with 0 secondary energy
00643   link = dd_link(0.0, f(0.0));
00644   insert(end(), link);
00645 
00646   // do we include the maximum at E = Theta/2?
00647   double next_E = 0.5*Theta_;
00648   if(E_max > next_E)
00649   {
00650     link = dd_link(next_E, f(next_E));
00651     insert(end(), link);
00652   }
00653 
00654   // do we include the inflection point at E = Theta*(1 + sqrt(2))/2?
00655   next_E = Theta_*(1 + sqrt(2.0))/2;
00656   if(E_max > next_E)
00657   {
00658     link = dd_link(next_E, f(next_E));
00659     insert(end(), link);
00660   }
00661 
00662   // end the list with E_max
00663   link = dd_link(E_max, f(E_max));
00664   insert(end(), link);
00665 }
00666 // ----------- one_d_Maxwell::copy ---------------------------
00667 void one_d_Maxwell::copy( one_d_Maxwell& list_2 )
00668 // Copies a list
00669 {
00670   dd_list::copy( list_2 );
00671   weight = list_2.weight;
00672   interp_type = list_2.interp_type;
00673   U_ = list_2.U_;
00674   Theta_ = list_2.Theta_;
00675 }
00676 // -------------- one_d_Maxwell::f -----------------
00677 double one_d_Maxwell::f(double E_out)
00678 // f = sqrt(E')*exp{-E'/Theta}, 0 <= E' <= E - U
00679 {
00680   double E_max = E_in() - U_;
00681   const double eps = 1.0e-12;
00682 
00683   if((E_out < 0.0) || (E_out > E_max*(1 + eps)))
00684   {
00685     // we are outside the range
00686     Warning("one_d_Maxwell::f", 
00687         pastenum("E_out: ",E_out)+" outside range for Maxwell function");
00688     return 0.0;
00689   }
00690   else
00691   {
00692     return sqrt(E_out)*exp(-E_out/Theta_);
00693   }
00694 }
00695 // ----------- one_d_Maxwell::list_interp --------------------
00696 void one_d_Maxwell::list_interp(double e_in, one_d_Maxwell& left_list,
00697   one_d_Maxwell& right_list)
00698 // Interpolate this list between left_list and right_list.
00699 {
00700   if(!empty())
00701   {
00702     SevereError("one_d_Maxwell::list_interp",
00703         "Trying to fill a one_d_Maxwell which has already been made");
00704   }
00705   // set the parameter
00706   double Theta;
00707   if ( right_list.interp_type == 2 ) // lin-lin
00708   {
00709     Theta = Lin_Lin( e_in, left_list.E_in(), left_list.Theta_,
00710       right_list.E_in(), right_list.Theta_);
00711   }
00712   else if ( right_list.interp_type == 3 ) // log-lin
00713   {
00714     Theta = Log_Lin( e_in, left_list.E_in(), left_list.Theta_,
00715       right_list.E_in(), right_list.Theta_);
00716   }
00717   else if ( right_list.interp_type == 4 ) // lin-log
00718   {
00719     Theta = Lin_Log( e_in, left_list.E_in(), left_list.Theta_,
00720       right_list.E_in(), right_list.Theta_);
00721   }
00722   else if ( right_list.interp_type == 5 ) // log-log
00723   {
00724     Theta = Log_Log( e_in, left_list.E_in(), left_list.Theta_,
00725       right_list.E_in(), right_list.Theta_);
00726   }
00727   else
00728   {
00729     Unimplemented("one_d_Maxwell::list_interp",
00730         pastenum("Implement for type: ",right_list.interp_type));
00731   }
00732   // U is independent of incident energy
00733   double U = right_list.U_;
00734   interp_type = right_list.interp_type;
00735 
00736   // fill out the list
00737   initiate(e_in, Theta, U);
00738 }
00739 // *********** one_d_Watt class ***********************
00740 // ----------- one_d_Watt constructor -----------------
00741 // default constructor
00742 one_d_Watt::one_d_Watt()
00743 {
00744 }
00745 // ------------- one_d_Watt::set_EUa ----------------------
00746 void one_d_Watt::set_EUa( double e_in, double U, double a )
00747 // set parameters E_in, U, and a
00748 {
00749   // to increase the incident energy right at threshold
00750   double EPSILON = Global.Value( "mf5_shift" );
00751 
00752   // are we right at the threshold?
00753   if( e_in <= ENDL.threshold )
00754   {
00755     // go a little above it to avoid getting a delta function
00756     E_in() = e_in*( 1 + EPSILON );
00757   }
00758   else
00759   {
00760     E_in() = e_in;
00761   }
00762   U_ = U;
00763   a_ = a;
00764 
00765   // for possible mapping to unit base
00766   max_E_out = E_in() - U;
00767   if( max_E_out > ENDL.Max_E_out )
00768   {
00769     max_E_out = ENDL.Max_E_out;
00770   }
00771   min_E_out = 0.0;
00772 }
00773 
00774 // ----------- one_d_Watt::intermediate_b --------------------
00775 void one_d_Watt::intermediate_b(double e_in, double U, double a,
00776   int a_interp, double b, int b_interp)
00777 // set up a list for b between 2 incident energies for a
00778 {
00779   // to increase the incident energy right at threshold
00780   double EPSILON = Global.Value( "mf5_shift" );
00781 
00782   // are we right at the threshold?
00783   if( e_in <= ENDL.threshold )
00784   {
00785     // go a little above it to avoid getting a delta function
00786     E_in() = e_in*( 1 + EPSILON );
00787   }
00788   else
00789   {
00790     E_in() = e_in;
00791   }
00792   U_ = U;
00793   a_ = a;
00794   b_ = b;
00795   interp_type = a_interp; // how to interpolate a
00796   interp_type_b = b_interp; // how to interpolate b
00797   // for possible mapping to unit base
00798   max_E_out = E_in() - U;
00799   if( max_E_out > ENDL.Max_E_out )
00800   {
00801     max_E_out = ENDL.Max_E_out;
00802   }
00803   min_E_out = 0.0;
00804 
00805   // expand the list
00806   initiate();
00807 }
00808 // ----------- one_d_Watt::same_b --------------------
00809 void one_d_Watt::same_b( double b, int b_interp )
00810 // set up a list for b at an incident energy for a
00811 {
00812   // to increase the incident energy right at threshold
00813   b_ = b;
00814   interp_type_b = b_interp; // how to interpolate b
00815   // expand the list
00816   initiate();
00817 }
00818 // --------------------- one_d_Watt::initiate() -------------
00819 void one_d_Watt::initiate()
00820 // fill out the list
00821 {
00822   // to increase the incident energy right at threshold
00823   double EPSILON = Global.Value( "mf5_shift" );
00824 
00825   if ( max_E_out <= 0.0 )
00826   {
00827     // below model threshold OK in multiple models if weight = 0
00828     // make a dummy list
00829     dd_link link( 0.0, 0.0 );  // for creating new links
00830     insert(end(), link);
00831     link.x = EPSILON;
00832     link.y = 1.0;
00833     insert(end(), link);
00834   }
00835   else
00836   {
00837     // this is a real list
00838     extrema();  // start the list by inserting the maximum
00839     thicken();
00840   }
00841   renorm();
00842 
00843   // If we are checking interpolation using the equiprobable
00844   // bins, get the bins.
00845   if(bin_interp)
00846   {
00847     get_bins();
00848   }
00849 }
00850 // ----------- one_d_Watt::extrema --------------------
00851 void one_d_Watt::extrema()
00852 // start the list with links a 0, the maximum probability,
00853 // and the maximum energy
00854 {
00855   dd_link link;  // for creating new links
00856   // initialize the list with 0 secondary energy
00857   link = dd_link(0.0, f(0.0));
00858   insert(end(), link);
00859 
00860   // end the list with E_max
00861   double E_max = max_E_out;
00862   link = dd_link(E_max, f(E_max));
00863   insert(end(), link);
00864 
00865   // to find the maximum
00866   double sigma = a_*b_/2;
00867   double beta = sqrt(b_*E_max);  // the largest possible beta
00868   // The zeroin function requires 2 dd_links on input
00869   dd_link B(0.0, 0.0);  // a link to the left of the maximum
00870   dd_link C(beta, Watt_max(beta, 0.0));  // a link to the right of the maximum
00871   if( C.y > sigma )
00872   {
00873     // There is an interior maximum
00874     beta = dd_list::zeroin(&Watt_max, sigma, B, C, 0.0, 1.0E-5);
00875     E_max = beta*beta/b_;
00876     if( E_max < max_E_out )
00877     {
00878       link = dd_link(E_max, f(E_max));
00879       dd_list::iterator list_ptr = end();
00880       --list_ptr;
00881       insert(list_ptr, link);
00882     }
00883   }
00884 }
00885 // ----------- one_d_Watt::copy ---------------------------
00886 void one_d_Watt::copy( one_d_Watt& list_2 )
00887 // Copies a list
00888 {
00889   dd_list::copy( list_2 );
00890   weight = list_2.weight;
00891   interp_type = list_2.interp_type;
00892   U_ = list_2.U_;
00893   a_ = list_2.a_;
00894   b_ = list_2.b_;
00895 }
00896 // -------------- one_d_Watt::f -----------------
00897 double one_d_Watt::f(double E_out)
00898 // f = sinh{sqrt(b*E')}*exp{-E'/a}, 0 <= E' <= E - U
00899 {
00900   double E_max = max_E_out;
00901   const double eps = 1.0e-12;
00902 
00903   if((E_out < 0.0) || (E_out > E_max*(1 + eps)))
00904   {
00905     // we are outside the range
00906     Warning("one_d_Watt::f",pastenum(" E_out: ",E_out)+
00907          " outside range for Watt function");
00908     return 0.0;
00909   }
00910   else
00911   {
00912     return sinh(sqrt(b_*E_out))*exp(-E_out/a_);
00913   }
00914 }
00915 // ----------- one_d_Watt::list_interp --------------------
00916 void one_d_Watt::list_interp(double e_in, one_d_Watt& left_list,
00917   one_d_Watt& right_list)
00918 // Interpolate this list between left_list and right_list.
00919 {
00920   if( !empty() )
00921   {
00922     SevereError("one_d_Watt::list_interp",
00923         "Trying to fill a one_d_Watt which has already been made");
00924   }
00925   // set the parameters
00926   double a;
00927   double b;
00928   double U;
00929   if ( right_list.interp_type == 2 ) // lin-lin for a and U
00930   {
00931     a = Lin_Lin( e_in, left_list.E_in(), left_list.a_,
00932       right_list.E_in(), right_list.a_);
00933     U = Lin_Lin( e_in, left_list.E_in(), left_list.U_,
00934       right_list.E_in(), right_list.U_);
00935   }
00936   else if ( right_list.interp_type == 3 ) // log-lin
00937   {
00938     a = Log_Lin( e_in, left_list.E_in(), left_list.a_,
00939       right_list.E_in(), right_list.a_);
00940     U = Log_Lin( e_in, left_list.E_in(), left_list.U_,
00941       right_list.E_in(), right_list.U_);
00942   }
00943   else if ( right_list.interp_type == 4 ) // lin-log
00944   {
00945     a = Lin_Log( e_in, left_list.E_in(), left_list.a_,
00946       right_list.E_in(), right_list.a_);
00947     U = Lin_Log( e_in, left_list.E_in(), left_list.U_,
00948       right_list.E_in(), right_list.U_);
00949   }
00950   else if ( right_list.interp_type == 5 ) // log-log
00951   {
00952     a = Log_Log( e_in, left_list.E_in(), left_list.a_,
00953       right_list.E_in(), right_list.a_);
00954     U = Log_Log( e_in, left_list.E_in(), left_list.U_,
00955       right_list.E_in(), right_list.U_);
00956   }
00957   else
00958   {
00959     SevereError("one_d_Watt::list_interp",
00960         pastenum("Implement for type: ",right_list.interp_type));
00961   }
00962 
00963   if ( right_list.interp_type_b == 2 ) // lin-lin for b
00964   {
00965     b = Lin_Lin( e_in, left_list.E_in(), left_list.b_,
00966       right_list.E_in(), right_list.b_);
00967   }
00968   else if ( right_list.interp_type_b == 3 ) // log-lin
00969   {
00970     b = Log_Lin( e_in, left_list.E_in(), left_list.b_,
00971       right_list.E_in(), right_list.b_);
00972   }
00973   else if ( right_list.interp_type_b == 4 ) // lin-log
00974   {
00975     b = Lin_Log( e_in, left_list.E_in(), left_list.b_,
00976       right_list.E_in(), right_list.b_);
00977   }
00978   else if ( right_list.interp_type_b == 5 ) // log-log
00979   {
00980     b = Log_Log( e_in, left_list.E_in(), left_list.b_,
00981       right_list.E_in(), right_list.b_);
00982   }
00983   else
00984   {
00985     Unimplemented("one_d_Watt::list_interp b",
00986         pastenum("Implement for type: ",right_list.interp_type_b));
00987   }
00988   interp_type = right_list.interp_type;
00989   interp_type_b = right_list.interp_type_b;
00990 
00991   // set parameters
00992   set_EUa( e_in, U, a );
00993 
00994   // set b and fill out the list
00995   same_b( b, right_list.interp_type_b );
00996 }
00997 // --------------------- Watt_max --------------------
00998 double Watt_max(double beta, double dummy)
00999 // used to locate the maximum of the Watt function
01000 {
01001   return beta*tanh(beta);
01002 }
01003 
01004 // *********** one_d_Madland class ***********************
01005 // ----------- one_d_Madland constructor -----------------
01006 // default constructor
01007 one_d_Madland::one_d_Madland()
01008 {
01009   E_max = ENDL.Max_E_in;
01010   Gamma_a = c_dgamma( 1.5 );
01011 }
01012 // ----------- one_d_Madland::initiate --------------------
01013 void one_d_Madland::initiate(double e_in, double EFL, double EFH,
01014   double TM )
01015 // set the parameters for the Madland model
01016 {
01017   E_in() = e_in;
01018   EFL_ = EFL;
01019   EFH_ = EFH;
01020   TM_ = TM;
01021 
01022   // start with some number of links
01023   const int num_links = 20;
01024   double dE = E_max/num_links;
01025   for( int count = 0; count <= num_links; ++count)
01026   {
01027     double E_out = count * dE;
01028     dd_link new_link( E_out, f(E_out) );  // for creating new links
01029     insert(end(), new_link);
01030   }
01031 
01032   thicken();
01033   thinit();
01034   renorm();
01035 
01036   // If we are checking interpolation using the equiprobable
01037   // bins, get the bins.
01038   if(bin_interp)
01039   {
01040     get_bins();
01041   }
01042 }
01043 // -------------- one_d_Madland::g -----------------
01044 double one_d_Madland::g( double E_out, double E_frag )
01045 // function used by f
01046 {
01047   double sqrt_E_out = sqrt( E_out );
01048   double sqrt_E_frag = sqrt ( E_frag );
01049   double u_1 = ( sqrt_E_out - sqrt_E_frag ) *
01050     ( sqrt_E_out - sqrt_E_frag ) / TM_;
01051   double u_2 = ( sqrt_E_out + sqrt_E_frag ) *
01052     ( sqrt_E_out + sqrt_E_frag ) / TM_;
01053 
01054   double gamma_1 = c_dgamit( 1.5, u_1 );
01055   gamma_1*= Gamma_a * u_1*sqrt(u_1);  // scale by Gamma(a) * x^a
01056 
01057   double gamma_2 = c_dgamit( 1.5, u_2 );
01058   gamma_2*= Gamma_a * u_2*sqrt(u_2);  // scale by Gamma(a) * x^a
01059 
01060   double ans = ( u_2 * sqrt( u_2 ) * expint( 1, u_2 ) -
01061                  u_1 * sqrt( u_1 ) * expint( 1, u_1 ) +
01062                  gamma_2 - gamma_1 ) / (3 * sqrt( E_frag * TM_ ));
01063   return ans;
01064 }
01065 // ----------- one_d_Madland::copy ---------------------------
01066 void one_d_Madland::copy( one_d_Madland& list_2 )
01067 // Copies a list
01068 {
01069   dd_list::copy( list_2 );
01070   weight = list_2.weight;
01071   interp_type = list_2.interp_type;
01072   EFL_ = list_2.EFL_;
01073   EFH_ = list_2.EFH_;
01074   TM_ = list_2.TM_;
01075   E_max = list_2.E_max;
01076   Gamma_a = list_2.Gamma_a;
01077 }
01078 // ----------- one_d_Madland::list_interp --------------------
01079 void one_d_Madland::list_interp(double e_in, one_d_Madland& left_list,
01080   one_d_Madland& right_list)
01081 // Interpolate this list between left_list and right_list.
01082 {
01083   if(!empty())
01084   {
01085     SevereError("one_d_Madland::list_interp",
01086         "Trying to fill a one_d_Madland which has already been made");
01087   }
01088   // set the parameters
01089   double TM;
01090   if ( right_list.interp_type == 2 ) // lin-lin
01091   {
01092     TM = Lin_Lin( e_in, left_list.E_in(), left_list.TM_,
01093       right_list.E_in(), right_list.TM_);
01094   }
01095   else if ( right_list.interp_type == 3 ) // log-lin
01096   {
01097     TM = Log_Lin( e_in, left_list.E_in(), left_list.TM_,
01098       right_list.E_in(), right_list.TM_);
01099   }
01100   else if ( right_list.interp_type == 4 ) // lin-log
01101   {
01102     TM = Lin_Log( e_in, left_list.E_in(), left_list.TM_,
01103       right_list.E_in(), right_list.TM_);
01104   }
01105   else if ( right_list.interp_type == 5 ) // log-log
01106   {
01107     TM = Log_Log( e_in, left_list.E_in(), left_list.TM_,
01108       right_list.E_in(), right_list.TM_);
01109   }
01110   else
01111   {
01112     Unimplemented("one_d_Madland::list_interp",
01113         pastenum("Implement for type: ",right_list.interp_type));
01114   }
01115   double EFL = right_list.EFL_;
01116   double EFH = right_list.EFH_;
01117   interp_type = right_list.interp_type;
01118 
01119   // fill out the list
01120   initiate(e_in, EFL, EFH, TM);
01121 }
01122 // ******************* class one_d_Legendre ******************
01123 double one_d_Legendre::f(double mu)
01124 {
01125   const double eps = 1.0e-12;  // a tolerance for the range
01126 
01127   if((mu < -1.0 - eps) || (mu > 1.0 + eps))
01128   {
01129     // we are outside the range
01130     Warning("one_d_Legendre::f",pastenum("cosine ",mu)+" outside its range");
01131 
01132     return 0.0;
01133   }
01134   else if(coef.size() < 1)
01135   {
01136     // failure
01137     SevereError("one_d_Legendre::f","Legendre_func called with no coefficients");
01138   }
01139 
01140   // First, handle the trivial cases
01141   double sum = 0.5*coef.at(0);
01142   if(coef.size() == 1)
01143   {
01144     return sum;
01145   }
01146 
01147   sum += 1.5*mu*coef.at(1);
01148   if(coef.size() == 2)
01149   {
01150     if(sum < 0.0)
01151     {
01152       Warning("one_d_Legendre::f",
01153         pastenum("Legendre sum < 0 for mu = ",mu));
01154     }
01155     return sum;
01156   }
01157 
01158   // Now use the iteration formula to compute the Legendre functions
01159   //   (n+1) P_{n+1}(mu) - (2n+1) mu P_n(mu) + n P_{n-1}(mu) = 0
01160   // See Courant and Hilbert, Methods of Mathematical Physics,
01161   // vol. 1, p. 86.
01162   double P_prev = 1.0;  // P_0(mu)
01163   double P_this = mu;   // P_1(mu)
01164   double P_next;
01165   for(int count = 1; count < coef.size() - 1; ++count)
01166   {
01167     // Note: the notation here is bad---P[count + 1] is the coefficient
01168     // multiplying the Legendre polynomial P_{count + 1}(mu).
01169     P_next = ((2*count + 1)*mu*P_this - count*P_prev)/(count + 1.0);
01170     sum += (count + 1.5)*P_next*coef.at(count + 1);
01171 
01172     // shift the values
01173     P_prev = P_this;
01174     P_this = P_next;
01175   }
01176 
01177   if(sum < 0.0) sum = 0.0;
01178 
01179   return sum;
01180 }
01181 // ----------- one_d_Legendre::expand -----------
01182 void one_d_Legendre::expand()
01183 // Expand a Legendre model into a linked list.
01184 {
01185   dd_link link;  // for creating new links
01186 
01187   // initialize the list with mu = -1
01188   link = dd_link(-1.0, f(-1.0));
01189   insert(end(), link);
01190 
01191   // add a link with mu = 1
01192   link = dd_link(1.0, f(1.0));
01193   insert(end(), link);
01194 
01195   thicken();
01196   renorm();
01197 }
01198 // ----------- one_d_Legendre::copy ---------------------------
01199 void one_d_Legendre::copy( one_d_Legendre& list_2 )
01200 // Copies a list
01201 {
01202   dd_list::copy( list_2 );
01203   weight = list_2.weight;
01204   interp_type = list_2.interp_type;
01205 }
01206 // ----------- one_d_Legendre::list_interp --------------------
01207 void one_d_Legendre::list_interp(double e_in, one_d_Legendre& left_list,
01208   one_d_Legendre& right_list )
01209 // interpolate this list between left_list and right_list.
01210 {
01211   if(!empty())
01212   {
01213     SevereError("one_d_Legendre::list_interp",
01214         "Trying to fill a one_d_Legendre which has already been made");
01215   }
01216   // how many coefficients
01217   int num_coef = ( left_list.coef.size() > right_list.coef.size() ) ?
01218     left_list.coef.size() : right_list.coef.size();
01219 
01220   coef.get_space( num_coef );
01221 
01222   // interpolate to get the coefficients
01223   for ( int count = 0; count < num_coef; ++count )
01224   {
01225     double left_coef = ( count < left_list.coef.size() ) ?
01226       left_list.coef[ count ] : 0.0;
01227     double right_coef = ( count < right_list.coef.size() ) ?
01228       right_list.coef[ count ] : 0.0;
01229     double this_coef;
01230 
01231     if ( right_list.interp_type == 1 ) // histogram
01232     {
01233       coef[ count ] = left_coef;
01234     }
01235     else if ( right_list.interp_type == 2 ) // lin-lin
01236     {
01237       this_coef = Lin_Lin( e_in, left_list.E_in(), left_coef,
01238         right_list.E_in(), right_coef );
01239       coef[ count ] = this_coef;
01240     }
01241     else if ( right_list.interp_type == 3 ) // log-lin
01242     {
01243       this_coef = Log_Lin( e_in, left_list.E_in(), left_coef,
01244         right_list.E_in(), right_coef );
01245       coef[ count ] = this_coef;
01246     }
01247     else if ( right_list.interp_type == 4 ) // lin-log
01248     {
01249       this_coef = Lin_Log( e_in, left_list.E_in(), left_coef,
01250         right_list.E_in(), right_coef );
01251       coef[ count ] = this_coef;
01252     }
01253     else if ( right_list.interp_type == 5 ) // log-log
01254     {
01255       this_coef = Log_Log( e_in, left_list.E_in(), left_coef,
01256         right_list.E_in(), right_coef );
01257       coef[ count ] = this_coef;
01258     }
01259     else
01260     {
01261       Unimplemented("one_d_Legendre::list_interp",
01262         pastenum("Implement for type: ",right_list.interp_type));
01263     }
01264   }
01265   interp_type = right_list.interp_type;
01266 
01267   // expand the 1-d model
01268   E_in() = e_in;
01269   expand();
01270 
01271   // set up the equiprobable bins
01272   get_bins();
01273 }
01274 // ****************** class one_d_isotropic *****************
01275 void one_d_isotropic::initiate(double e_in)
01276 // Make a list for this incident energy
01277 {
01278   E_in() = e_in;
01279 
01280   // put in the isotropic 1-d links
01281   dd_link link(-1.0, 0.5);
01282   insert(end(), link);
01283   link.mu() = 1.0;
01284   insert(end(), link);
01285 }
01286 // ----------- one_d_isotropic::copy ---------------------------
01287 void one_d_isotropic::copy( one_d_isotropic& list_2 )
01288 // Copies a list
01289 {
01290   dd_list::copy( list_2 );
01291   weight = list_2.weight;
01292   interp_type = list_2.interp_type;
01293 }
01294 // ****************** class one_d_hat *****************
01295 double one_d_hat::f(double E_out)
01296 {
01297   if((E_out < left_scale) || (E_out > right_scale))
01298   {
01299     // we are outside the range
01300     return 0.0;
01301   }
01302   else if(E_out <= top_scale)
01303   {
01304     return (E_out - left_scale)/(top_scale - left_scale);
01305   }
01306   else
01307   {
01308     return (right_scale - E_out)/(right_scale - top_scale);
01309   }
01310 }
01311 // ------------ one_d_hat::initiate -----------------------
01312 void one_d_hat::initiate(double left_end, double top,
01313   double right_end)
01314 // set up a hat-shaped energy distribution
01315 {
01316     // a1 = left end, a2 = top, and a3 = right end
01317   min_E_out = left_end;
01318   max_E_out = right_end;
01319 
01320   if(max_E_out <= min_E_out)
01321   {
01322     SevereError("one_d_hat::initiate","energies out of order");
01323   }
01324 
01325   left_scale = 0.0;
01326   top_scale = (top - right_end)/(left_end - right_end);
01327   left_scale = 1.0;
01328 
01329   // Expand a hat model into a linked list.
01330   dd_link link;  // for creating new links
01331 
01332   // the first link
01333   link = dd_link(0.0, 0.0);
01334   insert(end(), link);
01335 
01336   // a check
01337   if((top_scale <= 0) || (top_scale >= 1.0))
01338   {
01339     SevereError("one_d_hat::initiate","top of hat out of range");
01340   }
01341 
01342   link = dd_link(top_scale, 1.0);
01343   insert(end(), link);
01344 
01345   link = dd_link(1.0, 0.0);
01346   insert(end(), link);
01347 
01348   renorm();
01349 }
01350 

Generated on Thu Sep 7 10:30:03 2006 for fete -- From ENDFB6 To ENDL by doxygen 1.3.4