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

mf6classes.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: 1855 $
00029  * $Date: 2006-04-21 16:12:38 -0700 (Fri, 21 Apr 2006) $
00030  * $Author: hedstrom $
00031  * $Id: mf6classes.cpp 1855 2006-04-21 23:12:38Z hedstrom $
00032  * 
00033  * ******** fete: From ENDF To ENDL *********
00034  */
00035 
00036 // implementation of the class mf6_class
00037 
00038 #include <vector>
00039 using namespace std;
00040 #include "mf6classes.hpp"
00041 #include "record_types.hpp"
00042 #include "global_params.hpp"
00043 #include "endl_precision.hpp"
00044 
00045 extern ENDLClass ENDL;
00046 extern GlobalParameterClass Global;
00047 
00048 // ********* for class mf6_one_d *************
00049 // ----------- mf6_one_d::mf6_one_d -----------------
00050 // constructor
00051 mf6_one_d::mf6_one_d( )
00052 {
00053 }
00054 
00055 // ----------- mf6_one_d::one_E_row -----------------
00056 void mf6_one_d::one_E_row( double min_E, double max_E )
00057 // for a given mu make new links for secondary energies
00058 // min_E <= E <= max_E
00059 {
00060   double E_out;
00061   double Prob;
00062   dd_link e_out_link;
00063   const int Num = 2;  // to ensure that we start with one internal links
00064 
00065   // fudge the limits to ensure that we stay inside the range
00066   double first_E = min_E*1.00001;
00067   double dE = (max_E*0.99999 - first_E)/Num;
00068 
00069   for(int count = 0; count <= Num; ++count)
00070   {
00071     E_out = first_E + count*dE;
00072     Prob = f( E_out );
00073     e_out_link = dd_link( E_out, Prob );
00074     insert( end( ), e_out_link );
00075   }
00076 
00077   // fill in intermediate links
00078   thicken();
00079 
00080   // If we are checking interpolation using the equiprobable
00081   // bins, get the bins.
00082   if(bin_interp)
00083   {
00084     get_bins();
00085   }
00086 }
00087 
00088 // ********* for class one_d_phase *************
00089 // ----------- one_d_phase::f -------------------
00090 double one_d_phase::f( double E )
00091 // the phase-space distribution function
00092 {
00093   Pair lab_Emu; // (energy, cosine) in lab coordinates
00094   Pair cm_Emu;  // (energy, cosine) in center-of-mass coordinates
00095   double Prob;  // return value
00096 
00097   lab_Emu.mu = mu( );
00098   lab_Emu.E = E;
00099 
00100   // in center-of-mass coordinates
00101   cm_Emu = map_->lab_to_cm( lab_Emu );
00102 
00103   double E_diff = Ei_max - cm_Emu.E;
00104 
00105   if ( E_diff <= 0.0 )
00106   {
00107     Warning("one_d_phase::f",
00108         pastenum("attempt to take logarithm of ",E_diff));
00109     return 0.0;
00110   }
00111 
00112   // this probability includes the Jacobian: sqrt(lab_Emu.E/cm_Emu.E)
00113   Prob = sqrt( lab_Emu.E )*exp( exponent * log( E_diff ) );
00114 
00115   return Prob;
00116 }
00117 
00118 // ********* for class two_d_phase *************
00119 // ----------- two_d_phase::new_one_d( ) ---------
00120 two_d_phase::iterator two_d_phase::new_one_d( two_d_phase::iterator where )
00121 {
00122   one_d_phase new_link;
00123   insert( where, new_link );
00124 
00125   // point to the new link
00126   two_d_phase::iterator link_ptr = where;
00127   --link_ptr;
00128 
00129   // set up the parameters
00130   link_ptr->Ei_max = Ei_max_;
00131   link_ptr->exponent = exponent_;
00132   link_ptr->copy_map( &map );
00133 
00134   return link_ptr;
00135 }
00136 
00137 // ********* for class phase_space *************
00138 // ----------- phase_space::phase_space ------
00139 phase_space::phase_space( int projectile, int target, int ZAP )
00140 {
00141   a.set( projectile );
00142   A.set( target );
00143   b.set( ZAP );
00144   C.set( projectile + target );
00145   Q = ENDL.QI;
00146 }
00147 
00148 // ----------- phase_space::expand_data ------
00149 void phase_space::expand_data( mf6_file& inFile, multiplicity& multiple)
00150 {
00151   double dE;
00152   double e_in;
00153   int count;
00154 
00155   // the multiplicity ought to be constant
00156   if( ( multiple.INT.size() > 1 ) || ( multiple.INT[0] > 2 ) )
00157   {
00158     SevereError("phase_space::expand_data","Strange multiplicity for phase_space class");
00159   }
00160 
00161   // read the data line
00162   double APSX;  // the total mass involved
00163   int NPSX;      // for the exponent
00164   inFile.phase_space( &APSX, &NPSX );
00165   mass_ratio = ( APSX - b.AWR ) / APSX;
00166   exponent__ = 1.5 * NPSX - 4;
00167 
00168   // our maximum incident energy
00169   double Max_energy = ENDL.Max_E_in;
00170   if( ENDL.threshold >= Max_energy )
00171   {
00172     ENDL.write_file = false;
00173     return;
00174   }
00175 
00176   // find the transition from forward to omnidirectional emission
00177   double E_transition = find_E_trans( );
00178   // make lists for various incident energies
00179   int Num_E_in = static_cast<int>( Global.Value( "num_E_in_3d" ) );
00180   if( ( E_transition <= 0.0 ) || ( E_transition >= Max_energy ) )
00181   {
00182     dE = ( Max_energy - ENDL.threshold ) / Num_E_in;
00183     for ( count = 0; count <= Num_E_in; ++ count )
00184     {
00185       e_in = ENDL.threshold + count * dE;
00186       one_E_in( e_in );
00187     }
00188   }
00189   else
00190   {
00191     double local_eps = ENDL_EPSILON( E_transition );
00192     dE = ( E_transition - local_eps - ENDL.threshold ) / Num_E_in;
00193     for ( count = 0; count <= Num_E_in; ++ count )
00194     {
00195       e_in = ENDL.threshold + count * dE;
00196       one_E_in( e_in );
00197     }
00198     dE = ( Max_energy - E_transition - local_eps ) / Num_E_in;
00199     for ( count = 0; count <= Num_E_in; ++ count )
00200     {
00201       e_in = E_transition + local_eps + count * dE;
00202       one_E_in( e_in );
00203     }
00204   }
00205 }
00206 
00207 // ----------- phase_space::one_E_in ------
00208 void phase_space::one_E_in( double e_in )
00209 {
00210   two_d_phase e_in_link;
00211 
00212   e_in_link.E_in() = e_in;
00213   insert( end(), e_in_link );
00214 
00215   // make a pointer to the new 3-d link
00216   phase_space::iterator this_link = end();
00217   --this_link;
00218 
00219   // Expand this data into a 3-d link
00220   expand_E_in( this_link );
00221 
00222   // add a link to the cosine list
00223   one_d_table new_cos;
00224   cosines.insert( cosines.end(), new_cos );
00225 
00226   // expand this cosine link
00227   two_d_list<one_d_table>::iterator cos_ptr = cosines.end();
00228   --cos_ptr;
00229   this_link->make_cos_link( this_link->E_in(), cos_ptr );
00230 }
00231 
00232 // ----------- phase_space::expand_E_in -----------------
00233 void phase_space::expand_E_in( phase_space::iterator e_in_link )
00234 {
00235   // maximum center-of-mass energy for the emitted particle
00236   e_in_link->Ei_max_ = mass_ratio *
00237     ( Q + e_in_link->E_in()*( A.AWR/(A.AWR + a.AWR) ) );
00238   if( e_in_link->Ei_max_ <= 0.0 )
00239   {
00240     Warning("phase_space::expand_E_in",
00241          pastenum(" negative Ei_max_: ",e_in_link->Ei_max_)+
00242          pastenum(" for E_in: ", e_in_link->E_in()));
00243     // to increase the incident energy at or below threshold
00244     double EPSILON = Global.Value( "mf5_shift" );
00245     e_in_link->E_in() = -Q * ( 1 + EPSILON ) * (A.AWR + a.AWR) / A.AWR;
00246     e_in_link->Ei_max_ = mass_ratio *
00247       ( Q + e_in_link->E_in()*( A.AWR/(A.AWR + a.AWR) ) );
00248   }
00249 
00250   // to map between lab and center-of-mass coordinates
00251   e_in_link->map.set_map( &A, &a, &b, e_in_link->E_in() );
00252   e_in_link->exponent_ = exponent__;
00253 
00254   // Identify the geometry of the (E', mu) region in lab coordinates.
00255   // Note that the zero minimal energy makes 
00256   //   e_in_link->geom_.slowest == Forward.
00257   e_in_link->get_geom( 0.0, e_in_link->Ei_max_ );
00258   if( e_in_link->geom_.fastest == Both_ways )
00259   {
00260     e_in_link->full_range( e_in_link->Ei_max_ );
00261   }
00262   else if( e_in_link->geom_.fastest == Transition )
00263   {
00264     e_in_link->full_trans( e_in_link->Ei_max_ );
00265   }
00266   else if( e_in_link->geom_.fastest == Forward )
00267   {
00268     e_in_link->full_forward( 0.0, e_in_link->Ei_max_ );
00269   }
00270   else
00271   {
00272     SevereError("phase_space::expand_E_in","Strange geometry");
00273   }
00274 }
00275 // ----------- phase_space::find_E_trans -----------------
00276 double phase_space::find_E_trans( )
00277 {
00278   // calculate the incident energy at which we first have zero
00279   // outgoing energy in the lab frame
00280   double numerator = mass_ratio*Q;
00281   double denominator =
00282     ( (a.AWR*b.AWR) / (A.AWR + a.AWR) - mass_ratio*A.AWR ) /
00283     (A.AWR + a.AWR);
00284 
00285   double E_transition = numerator / denominator;
00286   return E_transition;
00287 }
00288 
00289 // ********* for class two_d_ENDL_table *************
00290 // ----------- two_d_ENDL_table::new_one_d( ) ---------
00291 two_d_ENDL_table::iterator 
00292   two_d_ENDL_table::new_one_d( two_d_ENDL_table::iterator where )
00293 {
00294   one_d_table new_link;
00295   insert( where, new_link );
00296 
00297   // point to the new link
00298   two_d_ENDL_table::iterator link_ptr = where;
00299   --link_ptr;
00300 
00301   return link_ptr;
00302 }
00303 
00304 // ********* for class ENDL_table *************
00305 // ----------- ENDL_table::ENDL_table ------
00306 ENDL_table::ENDL_table( )
00307 // constructor
00308 {
00309 }
00310 
00311 // ----------- ENDL_table::read_data ---------
00312 void ENDL_table::read_data( mf6_file& inFile, int ZAP,
00313   multiplicity& multiple )
00314 // Reads in all the data
00315 {
00316   // the multiplicity ought to be constant
00317   if( ( multiple.INT.size() > 1 ) || ( multiple.INT[0] > 2 ) )
00318   {
00319     SevereError("ENDL_table::read_data","Strange multiplicity for ENDL_table class");
00320   }
00321 
00322   // read the number of incident energies
00323   int NR; // number of interpolation regions
00324   int NE; // number of incident energies
00325   inFile.ENDL( &NR, &NE );
00326   inFile.get_regions( NR, NBT, INT );
00327   // loop over the incident energies
00328   for ( int count = 0; count < NE; ++count)
00329   {
00330     one_E_in( inFile );
00331   }
00332 }
00333 
00334 // ----------- ENDL_table::one_E_in ---------
00335 void ENDL_table::one_E_in( mf6_file& inFile )
00336 // Reads the data for one incident energy
00337 {
00338   string linebuff;
00339   string strbuff;
00340 
00341   // read the incident energy and the number of cosines
00342   double e_in;
00343   int NR; // number of interpolation regions
00344   int NMU; // number of cosines
00345   inFile.ENDL_head( &e_in, &NR, &NMU );
00346   two_d_ENDL_table new_e_in_link;
00347   insert( end(), new_e_in_link );
00348   // make a pointer to the new 3-d link
00349   ENDL_table::iterator e_in_link = end();
00350   --e_in_link;
00351   e_in_link->E_in() = e_in*ENDL.eV2MeV; // convert to MeV
00352 
00353   inFile.get_regions( NR, e_in_link->NBT, e_in_link->INT );
00354   // loop over the cosines
00355   for ( int count = 0; count < NMU; ++count )
00356   {
00357     // mu corresponds to a new 2d link in the list for this E_in
00358     double this_mu;
00359     int NEP; // number of (E', probability) pairs
00360     inFile.ENDL_head( &this_mu, &NR, &NEP );
00361     two_d_ENDL_table::iterator mu_ptr =
00362       e_in_link->new_one_d( e_in_link->end( ) );
00363     mu_ptr->mu( ) = this_mu;
00364     inFile.get_regions( NR, mu_ptr->NBT, mu_ptr->INT );
00365 
00366     // make a 1-d list of (E', probability) values
00367     for( int iNP=0; iNP < NEP; ++iNP ) //Loop over NEP data pairs
00368     { 
00369       int iP=iNP % 3;  //There are 3 pairs per line
00370       if ( iP == 0 )
00371       {
00372         getline( inFile, linebuff); //Read in new line
00373       }
00374       strbuff = linebuff.substr( iP*22, 22 );  // grab the right pair
00375       double X, Y; //Real variables we will put the data pair
00376       read_dd(&strbuff, &X, &Y );
00377       if ( X==-999. || Y==-999. ) //read_PAIR sends -999. if problem
00378       {
00379         SevereError("ENDL_table::one_E_in","read_PAIR fucked up!");
00380       }
00381       else
00382       {
00383         dd_link XYdata( X*ENDL.eV2MeV, Y );
00384         mu_ptr->insert( mu_ptr->end(), XYdata );
00385       }
00386     }
00387   }
00388   // add a link to the cosine list
00389   one_d_table new_cos;
00390   cosines.insert( cosines.end(), new_cos );
00391 
00392   // expand this cosine link
00393   two_d_list<one_d_table>::iterator cos_ptr = cosines.end();
00394   --cos_ptr;
00395   e_in_link->make_cos_link( e_in_link->E_in(), cos_ptr );
00396 }
00397 
00398 // *********** class Legendre_item ***********
00399 // ----------- Legendre_item::Legendre_item ---------
00400 Legendre_item::Legendre_item( )
00401 {
00402   // default constructor
00403 }
00404 // ----------- Legendre_item::read_coefs ---------
00405 void Legendre_item::read_coefs( int i_start, string& linebuff, int order,
00406   mf6_file& inFile, bool *E_out_done )
00407 // Reads the Legendre coefficients for one outgoing energy.
00408 // There are 6 entries per line, but the reading may start at any entry.
00409 // *E_out_done = true if E_out > ENDL.max_E_out
00410 {
00411   if( !(*E_out_done) )
00412   {
00413     // Allocate space for the coefficients
00414     coefs.get_space( order + 1 );
00415   }
00416 
00417   string strbuff;
00418 
00419   // read the outgoing energy
00420   if( i_start == 0 )
00421   {
00422     getline( inFile, linebuff );
00423   }
00424   strbuff = linebuff.substr( 11*i_start, 11 );  // grab the first entry
00425   read_d( &strbuff, &E_out );
00426   E_out *= ENDL.eV2MeV; // convert to MeV
00427 
00428   // get the coefficients
00429   int count = 0;
00430   for(  ; count <= order; ++count )
00431   {
00432     // There are 6 entries per line, and we already read E_out.
00433     int iP = ( i_start + count + 1 ) % 6;
00434     if ( iP == 0 )
00435     {
00436       getline( inFile, linebuff); //Read in new line
00437     }
00438     if( !(*E_out_done) )
00439     {
00440       // grab the proper entry
00441       strbuff = linebuff.substr( 11*iP, 11 );
00442       read_d( &strbuff, &coefs[ count ] );
00443     }
00444   }
00445   double dE = ENDL_EPSILON( ENDL.Max_E_out );
00446   if( E_out > ENDL.Max_E_out - dE )
00447   {
00448     *E_out_done = true;
00449   }
00450 }
00451 // ----------- Legendre_item::copy_coef ---------
00452 void Legendre_item::copy_coef( Legendre_item& copy_from )
00453 // Copy the Legendre coefficients
00454 {
00455   // Allocate space for the coefficients
00456   int num_coef = copy_from.coefs.size( );
00457   coefs.get_space( num_coef );
00458 
00459   for( int count = 0; count < num_coef; ++count )
00460   {
00461     coefs[ count ] = copy_from.coefs[ count ];
00462   }
00463 }
00464 // ----------- Legendre_item::interpolate ---------
00465 void Legendre_item::interpolate( Legendre_item& prev_link,
00466   Legendre_item& next_link )
00467 // interpolate the coefficients between next_link and the previous one
00468 {
00469   double E_diff = next_link.E_out - prev_link.E_out;
00470 
00471   // check for division by 0
00472   if(E_diff == 0.0)
00473   {
00474     SevereError("Legendre_item::interpolate","division by 0");
00475   }
00476 
00477   double alpha = (E_out - prev_link.E_out)/E_diff;
00478 
00479   // check for extrapolation
00480   if((alpha < 0.0) || (alpha > 1.0))
00481   {
00482     SevereError("Legendre_item::interpolate", "attempt to extrapolate");
00483   }
00484 
00485   for( int j = 0; j < coefs.size( ); ++j )
00486   {
00487     coefs[ j ] += alpha*next_link.coefs[ j ] +
00488       (1.0 - alpha)*prev_link.coefs[ j ];
00489   }
00490 }
00491 
00492 // *********** class Legendre_list ***********
00493 // ----------- Legendre_list::read_data ---------
00494 void Legendre_list::read_data( int LEP, mf6_file& inFile, bool *done )
00495 // Reads the Legendre data for one incident energy
00496 // *done = true if E_in > ENDL.Max_E_in
00497 {
00498   // we may need a list of gamma lines
00499   one_d_table gamma_lines;
00500 
00501   int num_E_out;
00502   int ND;  // number of discrete lines
00503   // How much data?
00504   inFile.Legendre_E_in( &E_in, &ND, &order, &num_E_out );
00505 
00506   E_in *= ENDL.eV2MeV; // convert to MeV
00507 
00508   // read the data
00509   string linebuff;
00510   string strbuff;
00511 
00512   // start with the lines
00513   for( int count = 0; count < ND; ++count )
00514   {
00515     int iP = count % 3;  //There are 3 pairs per line
00516     if ( iP == 0 )
00517     {
00518       getline( inFile, linebuff ); //Read in new line
00519     }
00520     strbuff = linebuff.substr( iP*22, 22 );  // grab the right pair
00521     double X, Y; //Real variables we will put the data pair
00522     read_dd(&strbuff, &X, &Y );
00523     // to MeV
00524     X *= ENDL.eV2MeV;
00525     dd_link XYdata( X, Y );
00526 
00527     // insert the line if it is within our range
00528     double dE = ENDL_EPSILON( ENDL.Max_E_out );
00529     if( ( Y > 0.0 ) && ( X <= ENDL.Max_E_out + dE ) )
00530     {
00531       // find where to insert the line
00532       one_d_table::iterator next_line = gamma_lines.find_next( X );
00533       gamma_lines.insert( next_line, XYdata );
00534     }
00535   }
00536 
00537   // now read the Legendre coefficients for the continuum
00538   int i_start = 2*ND % 6;
00539   bool E_out_done = false;
00540   for( int count = 0; count < num_E_out - ND; ++count )
00541   {
00542     Legendre_item new_E_out;
00543     if( !(*done) )
00544     {
00545       insert( end( ), new_E_out );
00546       Legendre_list::iterator E_out_data = end( );
00547       --E_out_data;  // now points to the new list
00548       E_out_data->read_coefs( i_start, linebuff, order, inFile,
00549         &E_out_done );
00550     }
00551     else
00552     {
00553       new_E_out.read_coefs( i_start, linebuff, order, inFile,
00554         &E_out_done );
00555     }
00556     i_start += order + 2;
00557     i_start = i_start % 6;
00558   }
00559 
00560   // expand the interpolation
00561   expand_interp( LEP );
00562 
00563   // are there lines?
00564   if( gamma_lines.size( ) > 0 )
00565   {
00566     gamma_lines.widen_delta( );
00567 
00568     // are there Legendre coefficients for the continuum?
00569     if( empty( ) )
00570     {
00571       // copy the lines
00572       only_lines( gamma_lines );
00573     }
00574     else
00575     {
00576       // add the lines
00577       add_lines( gamma_lines );
00578     }
00579   }
00580   // is this incident energy too big?
00581   double dE = ENDL_EPSILON( ENDL.Max_E_in );
00582   if( E_in > ENDL.Max_E_in - dE )
00583   {
00584     *done = true;
00585   }
00586 }
00587 // ----------- Legendre_list::only_lines ---------
00588 void Legendre_list::only_lines( one_d_table& gamma_lines )
00589 // we have only gamma lines---no continuum
00590 {
00591   for( one_d_table::iterator line_ptr = gamma_lines.begin( );
00592        line_ptr != gamma_lines.end( ); ++line_ptr )
00593   {
00594     Legendre_item new_E_out;
00595     insert( end( ), new_E_out );
00596     Legendre_list::iterator E_out_data = end( );
00597     --E_out_data;  // now points to the new list
00598     E_out_data->E_out = line_ptr->x;
00599     E_out_data->coefs.get_space( 1 );
00600     E_out_data->coefs[ 0 ] = line_ptr->y;
00601   }
00602 }
00603 // ----------- Legendre_list::add_lines ---------
00604 void Legendre_list::add_lines( one_d_table& gamma_lines )
00605 // we have gamma lines and continuum
00606 {
00607   // pad the start with zeros if necessary
00608   one_d_table::iterator line_ptr = gamma_lines.begin( );
00609   Legendre_list::iterator continuum = begin( );
00610 
00611   double Eout_line = line_ptr->x;
00612   double Eout_continuum = continuum->E_out;
00613 
00614   if( Eout_line < Eout_continuum )
00615   {
00616     pad_head( Eout_line );
00617   }
00618   else if( Eout_continuum < Eout_line )
00619   {
00620     gamma_lines.pad_head( Eout_continuum );
00621   }
00622 
00623   // pad the tail with zeros if necessary
00624   line_ptr = gamma_lines.end( );
00625   continuum = end( );
00626   --line_ptr;
00627   --continuum;
00628 
00629   Eout_line = line_ptr->x;
00630   Eout_continuum = continuum->E_out;
00631 
00632   if( Eout_line > Eout_continuum )
00633   {
00634     pad_tail( Eout_line );
00635   }
00636   else if( Eout_continuum > Eout_line )
00637   {
00638     gamma_lines.pad_tail( Eout_continuum );
00639   }
00640 
00641   // in order to add them, first make a list of the common E_out values
00642   list< double > E_out_list;
00643   gamma_lines.collect_E_in( E_out_list );
00644 
00645   for( Legendre_list::iterator continuum = begin( );
00646        continuum != end( ); ++continuum )
00647   {
00648     double E_cont = continuum->E_out;
00649     E_out_list.push_back( E_cont );
00650   }
00651 
00652   E_out_list.sort( );
00653   E_out_list.unique( );
00654   // fill the line list with values from E_out_list
00655   gamma_lines.fill_with( E_out_list );
00656 
00657   // fill the continuum list with values from E_out_list
00658   fill_with( E_out_list );
00659 
00660   // add the gamma data
00661   for( line_ptr = gamma_lines.begin( ), continuum = begin( );
00662        (  line_ptr != gamma_lines.end( ) ) && ( continuum != end( ) );
00663        ++line_ptr, ++continuum )
00664   {
00665     double E_gamma = line_ptr->x;
00666     double E_cont = continuum->E_out;
00667 
00668     if( E_gamma != E_cont )
00669     {
00670       SevereError( "Legendre_list::add_lines",
00671            "energies don't match" );
00672     }
00673     // add the line data
00674     continuum->coefs[ 0 ] += line_ptr->y;
00675   }
00676 }
00677 // ----------- Legendre_list::pad_head ---------
00678 void Legendre_list::pad_head( double E0 )
00679 // insert zero links from E0 to the head
00680 {
00681   Legendre_item new_link;  // for creating new links
00682   Legendre_list::iterator E_out_data;
00683 
00684   double first_E = begin( )->E_out;
00685   // smallest dE can see in output file
00686   double dE = ENDL_EPSILON( first_E );
00687 
00688   // insert a jump if needed
00689   if( first_E - E0 > dE )
00690   {
00691     bool non_zero = false;
00692     for( int j = 0; j <= order; ++j )
00693     {
00694       if( begin( )->coefs[ j ] != 0.0 )
00695       {
00696         non_zero = true;
00697     break;
00698       }
00699     }
00700     if( non_zero )
00701     {
00702       new_link.E_out = first_E - dE;
00703       push_front( new_link );
00704       E_out_data = begin( );
00705       E_out_data->coefs.get_space( order + 1 );
00706       E_out_data->coefs.set_zero( );
00707     }
00708   }
00709 
00710   // insert a new head
00711   new_link.E_out = E0;
00712   push_front( new_link );
00713   E_out_data = begin( );
00714   E_out_data->coefs.get_space( order + 1 );
00715   E_out_data->coefs.set_zero( );
00716 }
00717 // ----------- Legendre_list::pad_tail ---------
00718 void Legendre_list::pad_tail( double E0 )
00719 // insert zero links from E0 to the tail
00720 {
00721   Legendre_item new_link;  // for creating new links
00722 
00723   Legendre_list::iterator E_out_data = end( );
00724   --E_out_data;
00725   double last_E = E_out_data->E_out;
00726   // smallest dE can see in output file
00727   double dE = ENDL_EPSILON( last_E );
00728 
00729   // insert a jump if needed
00730   if( E0 - last_E > dE )
00731   {
00732     bool non_zero = false;
00733     for( int j = 0; j <= order; ++j )
00734     {
00735       if( E_out_data->coefs[ j ] != 0.0 )
00736       {
00737         non_zero = true;
00738     break;
00739       }
00740     }
00741     if( non_zero )
00742     {
00743       new_link.E_out = last_E + dE;
00744       push_back( new_link );
00745       E_out_data = end( );
00746       --E_out_data;
00747       E_out_data->coefs.get_space( order + 1 );
00748       E_out_data->coefs.set_zero( );
00749     }
00750   }
00751 
00752   // insert a new tail
00753   new_link.E_out = E0;
00754   push_back( new_link );
00755   E_out_data = end( );
00756   --E_out_data;
00757   E_out_data->coefs.get_space( order + 1 );
00758   E_out_data->coefs.set_zero( );
00759 }
00760 // ----------- Legendre_list::fill_with ------------
00761 void Legendre_list::fill_with( list< double >& E_out_list )
00762 // make sure that there are links for each energy in E_out_list
00763 {
00764   Legendre_list::iterator this_link = begin( );
00765 
00766   // go through the E_out_list
00767   for( list< double >::iterator E_out_ptr = E_out_list.begin( ); 
00768        E_out_ptr != E_out_list.end( ); ++E_out_ptr )
00769   {
00770     double E_out = *E_out_ptr;
00771 
00772     // if there is a node here, just go on to the next
00773     if( this_link->E_out == E_out )
00774     {
00775       ++this_link;
00776     }
00777     else
00778     {
00779       // interpolate and make a new link
00780       Legendre_item new_link;  // for creating new links
00781       new_link.E_out = E_out;
00782       Legendre_list::iterator prev_link = this_link;
00783       --prev_link;
00784       insert( this_link, new_link );
00785       Legendre_list::iterator new_ptr = this_link;
00786       --new_ptr;
00787       new_ptr->coefs.get_space( order + 1 );
00788       new_ptr->interpolate( *prev_link, *this_link );
00789     }
00790   }
00791 }
00792 
00793 // ----------- Legendre_list::get_norm ---------
00794 double Legendre_list::get_norm( )
00795 // Get the norm with respect to E_out
00796 {
00797   // point to the zeroth Legendre_item
00798   Legendre_list::iterator data_ptr = begin( );
00799 
00800   if (size()==0) SevereError("Legendre_list::get_norm","Empty list!");
00801 
00802   double prev_E_out = data_ptr->E_out;
00803   double prev_P = data_ptr->coefs.at( 0 );
00804   ++data_ptr;
00805   double sum = 0.0;
00806 
00807   // loop through the other Legendre_items
00808   for(  ; data_ptr != end( ); ++data_ptr )
00809   {
00810     double next_E_out = data_ptr->E_out;
00811     double next_P = data_ptr->coefs.at( 0 );
00812 
00813     // accumulate the probability
00814     sum += 0.5*( next_P + prev_P )*( next_E_out - prev_E_out );
00815     // save the values for the next interval
00816     prev_E_out = next_E_out;
00817     prev_P = next_P;
00818   }
00819   return sum;
00820 }
00821 // ----------- Legendre_list::renorm ---------
00822 void Legendre_list::renorm( )
00823 // Set the norm with respect to E_out to 1.
00824 {
00825   double norm = get_norm( );
00826   // point to the first Legendre_item
00827   Legendre_list::iterator data_ptr = begin( );
00828 
00829   // error check
00830   if( norm == 0.0 )
00831   {
00832     if (size()==0) SevereError("Legendre_list::renorm","Empty list!");
00833     Warning("Legendre_list::renorm",
00834          pastenum("zero norm in Legendre_list::renorm routine for E_in: ",E_in));
00835     // fudge something
00836     data_ptr->coefs[ 0 ] = 1.0;
00837   }
00838   else
00839   {
00840     // scale the data
00841     for(  ;  data_ptr != end( ); ++data_ptr )
00842     {
00843       for( int i_coef = 0; i_coef < data_ptr->coefs.size( );
00844           ++i_coef )
00845       {
00846         data_ptr->coefs[ i_coef ] /= norm;
00847       }
00848     }
00849   }
00850 }
00851 
00852 // ----------- Legendre_list::widen_jumps ---------
00853 //! shift (near) duplicate x-values in the list
00854 void Legendre_list::widen_jumps( )
00855 {
00856 
00857   // scale dE by the smoother used for histograms
00858   double local_eps, jump_width;
00859 
00860   typedef Legendre_list::iterator list_iterator;
00861 
00862   // container to hold links to elements we need to widen
00863   list_iterator cluster_start = begin();
00864   list_iterator cluster_end = begin();
00865   int cluster_size=1;
00866 
00867   for( list_iterator this_link = begin(); this_link != end( ); ++this_link )
00868   {
00869     // get the local energy epsilon (smallest dE can see in output file)
00870     local_eps = ENDL_EPSILON( this_link->E_out );
00871     jump_width = ENDL_JUMP_WIDTH( this_link->E_out );
00872 
00873     // this_link is too close to the cluster_end, so add it to the cluster
00874     if( abs( this_link->E_out - cluster_end->E_out ) <= local_eps )
00875     {
00876       cluster_end = this_link;
00877       ++cluster_size;
00878     }
00879     // this_link is far from the cluster_end, so let's process the cluster
00880     else 
00881     {
00882       if ( cluster_size > 1 ) 
00883         widen_cluster( cluster_start, cluster_end, cluster_size, jump_width );
00884       // clear the clusters
00885       cluster_start = ++cluster_end;
00886       cluster_size  = 1;
00887     }
00888   }
00889   // check the last cluster since doesn't get processed otherwise
00890   if ( cluster_size > 1 ) 
00891     widen_cluster( cluster_start, cluster_end, cluster_size, jump_width );
00892 }
00893 
00894 // -------------- Legendre_list::widen_clusters ------------------
00895 //! used by widen_jumps to do the actual widening between the cluster_start and cluster_end iterator
00896 void Legendre_list::widen_cluster( Legendre_list::iterator cluster_start, 
00897   Legendre_list::iterator cluster_end, int cluster_size, double jump_width )
00898 {
00899   if( ( cluster_size == 1 ) || ( cluster_start==cluster_end ) ) return;
00900   if ( cluster_size>4 ) 
00901   {
00902     Warning("Legendre_list::widen_cluster",pastenum("Found ",cluster_size)+
00903       pastenum(" links in a cluster, check ENDL_EPSILON and ENDL_JUMP_WIDTH values or the data is broken at E_out=",
00904       cluster_start->E_out)); 
00905   }
00906 
00907   if ( cluster_start->E_out <= jump_width )
00908   {
00909     Legendre_list::iterator cluster_middle = cluster_start; 
00910     for (int ijump = 1; ijump<=cluster_size; ++ijump)
00911     {
00912       ++cluster_middle; 
00913       cluster_middle->E_out += static_cast<double>(ijump)*jump_width;
00914     }
00915   }
00916   else
00917   {
00918     switch (cluster_size)
00919     {
00920       case 2:
00921         cluster_start->E_out -= 0.5*jump_width;
00922         cluster_end->E_out   += 0.5*jump_width;
00923         break;
00924       case 3:
00925         cluster_start->E_out -= jump_width;
00926         cluster_end->E_out   += jump_width;
00927         break;
00928       case 4:
00929         {
00930         Legendre_list::iterator cluster_left = cluster_start;
00931         Legendre_list::iterator cluster_right = cluster_end;
00932         ++cluster_left;--cluster_right;
00933         cluster_start->E_out -= 1.5*jump_width;
00934         cluster_left->E_out  -= 0.5*jump_width;
00935         cluster_right->E_out += 0.5*jump_width;
00936         cluster_end->E_out   += 1.5*jump_width;
00937         }
00938         break;
00939       default:
00940         Warning("Legendre_list::widen_cluster",pastenum("Found ",cluster_size)+
00941         pastenum(" links in a cluster, check ENDL_EPSILON and ENDL_JUMP_WIDTH values or the data is broken at E_out=",
00942         cluster_start->E_out)); 
00943         return;
00944     }
00945   }
00946 }
00947 
00948 // ----------- Legendre_list::expand_interp ---------
00949 void Legendre_list::expand_interp( int LEP )
00950 // Expand the interpolation with respect to energy of 
00951 // the outgoing particle
00952 {
00953 
00954   if ( LEP == 2 ) // lin-lin
00955   {
00956   }
00957   else if ( LEP == 1 ) // histogram
00958   {
00959     Legendre_list::iterator data_ptr = begin( );
00960 
00961     // We could be finished already
00962     if( data_ptr == end( ) )
00963     {
00964       return;
00965     }
00966 
00967     // loop through the list
00968     Legendre_list::iterator prev_ptr = begin( );
00969     ++data_ptr;
00970     Legendre_list::iterator next_ptr = data_ptr;
00971     ++next_ptr;
00972 
00973     for(  ; data_ptr != end( );
00974         prev_ptr = data_ptr, data_ptr = next_ptr, ++next_ptr )
00975     {
00976       Legendre_item new_link;
00977       insert( data_ptr, new_link );
00978       Legendre_list::iterator new_ptr = data_ptr;
00979       --new_ptr;  //  points to the new link
00980 
00981       // how wide the jump
00982       double dE_L = data_ptr->E_out - prev_ptr->E_out;
00983       double dE_R = ( next_ptr == end( ) ) ? data_ptr->E_out :
00984         next_ptr->E_out - data_ptr->E_out;
00985       double dE = (dE_L < dE_R) ? dE_L : dE_R;
00986 
00987       if(dE <= 0.0)
00988       {
00989         SevereError("Legendre_list::expand_interp", "bad histogram data");
00990       }
00991 
00992       // set smoothing dE to be smallest dE we can see in output file
00993       dE = ENDL_EPSILON( data_ptr->E_out );
00994 
00995       new_ptr->E_out = data_ptr->E_out - dE;
00996       data_ptr->E_out += dE;
00997       new_ptr->copy_coef( *prev_ptr );  // copy the Legendre coeficients
00998     }
00999   }
01000   else
01001   {
01002     SevereError("Legendre_list::expand_interp",
01003         pastenum("Implement interpolation type: ",LEP));
01004   }
01005 }
01006 // ----------- Legendre_list::unit_base ---------
01007 void Legendre_list::unit_base( )
01008 // map to unit base, 0 <= E' <= 1
01009 {
01010   least_E = begin( )->E_out;
01011   Legendre_list::iterator list_ptr = end( );
01012   --list_ptr;
01013   most_E = list_ptr->E_out;
01014   double scale = most_E - least_E;
01015   if( scale <= 0.0 )
01016   {
01017     SevereError( "Legendre_list::unit_base",
01018          "invalid scale factor");
01019   }
01020 
01021   for( list_ptr = begin( ); list_ptr != end( ); ++list_ptr )
01022   {
01023     list_ptr->E_out = ( list_ptr->E_out - least_E )/scale;
01024     list_ptr->coefs *= scale;
01025   }
01026 }
01027 // ----------- Legendre_list::rescale ---------
01028 void Legendre_list::rescale( )
01029 // undo the unit base transfoprmation
01030 {
01031   double scale = most_E - least_E;
01032   if( scale <= 0.0 )
01033   {
01034     SevereError( "Legendre_list::rescale",
01035          "invalid scale factor");
01036   }
01037 
01038   for( Legendre_list::iterator list_ptr = begin( );
01039     list_ptr != end( ); ++list_ptr )
01040   {
01041     list_ptr->E_out = least_E + scale*list_ptr->E_out;
01042     list_ptr->coefs *= 1.0/scale;
01043   }
01044 }
01045 // ----------- Legendre_list::copy ---------
01046 void Legendre_list::copy( Legendre_list& to_copy )
01047 // copy the Legendre coefficients
01048 {
01049   order = to_copy.order;
01050   interp_type = to_copy.interp_type;
01051   Legendre_item new_link;
01052 
01053   for( Legendre_list::iterator copy_ptr = to_copy.begin( );
01054     copy_ptr != to_copy.end( ); ++copy_ptr )
01055   {
01056     insert( end( ), new_link );
01057     Legendre_list::iterator list_ptr = end( );
01058     --list_ptr;  // now points to the new link
01059 
01060     list_ptr->E_out = copy_ptr->E_out;
01061     list_ptr->copy_coef( *copy_ptr );
01062   }
01063 }
01064 // ----------- Legendre_list::operator*= ---------
01065 Legendre_list& Legendre_list::operator*=( double alpha )
01066 // scale the Legendre coefficients by alpha
01067 {
01068   for( Legendre_list::iterator list_ptr = begin( );
01069     list_ptr != end( ); ++list_ptr )
01070   {
01071     list_ptr->coefs *= alpha;
01072   }
01073   return *this;
01074 }
01075 // ----------- Legendre_list::operator+= ---------
01076 Legendre_list& Legendre_list::operator+=( Legendre_list& to_add )
01077 // scale the Legendre coefficients by alpha
01078 {
01079   Legendre_list::iterator add_ptr = to_add.begin( );
01080   for( Legendre_list::iterator list_ptr = begin( );
01081     list_ptr != end( ); ++list_ptr, ++add_ptr )
01082   {
01083     if( ( list_ptr->E_out != add_ptr->E_out ) ||
01084     (add_ptr == to_add.end( ) ) )
01085     {
01086       SevereError( "Legendre_list::operator+=",
01087            "summands don't agree" );
01088     }
01089     list_ptr->coefs += add_ptr->coefs;
01090   }
01091   return *this;
01092 }
01093 // ----------- Legendre_list::chop_E_out ---------
01094 void Legendre_list::chop_E_out( double max_E_out )
01095 // deletes entries with E_out > max_E_out
01096 {
01097   // I do not expect that all of the entries will have energy too big
01098   double dE = ENDL_EPSILON( max_E_out );
01099   if( begin( )->E_out > max_E_out + dE )
01100   {
01101     Warning( "Legendre_list::chop_E_out",
01102          "all outgoing energies are too big" );
01103   }
01104 
01105   Legendre_list::iterator last_ptr = end( );
01106   --last_ptr;
01107   if( last_ptr->E_out > max_E_out + dE )
01108   {
01109     // loop through the incident-energy lists
01110     for( Legendre_list::iterator list_ptr = begin( );
01111          list_ptr != end( ); ++list_ptr )
01112     {
01113       if( list_ptr->E_out > max_E_out + dE )
01114       {
01115         // the previous list may be at max_E_out
01116         Legendre_list::iterator prev_ptr = list_ptr;
01117         --prev_ptr;
01118         if( prev_ptr->E_out > max_E_out - dE )
01119         {
01120       // are there any others with big enough E_out?
01121           Legendre_list::iterator prev_prev_ptr = prev_ptr;
01122           --prev_prev_ptr;
01123           for( ; prev_prev_ptr->E_out > max_E_out - dE; --prev_prev_ptr )
01124       {
01125             list_ptr = prev_ptr;
01126             prev_ptr = prev_prev_ptr;
01127       }
01128       prev_ptr->E_out = max_E_out;
01129           erase( list_ptr, end( ) );
01130     }
01131         else
01132     {
01133           // interpolate and make a new link
01134           Legendre_item new_link;  // for creating new links
01135           insert( list_ptr, new_link );
01136           Legendre_list::iterator new_ptr = list_ptr;
01137           --new_ptr;
01138           new_ptr->E_out = max_E_out;
01139           new_ptr->coefs.get_space( order + 1 );
01140           new_ptr->interpolate( *prev_ptr, *list_ptr );
01141           erase( list_ptr, end( ) );
01142     }
01143         break;
01144       }
01145     }
01146   }
01147 }
01148 // ----------- Legendre_list::print ---------
01149 void Legendre_list::print( )
01150 // print for debugging
01151 {
01152   cout.setf(ios::scientific,ios::floatfield);
01153   for( Legendre_list::iterator list_ptr = begin( );
01154     list_ptr != end( ); ++list_ptr )
01155   {
01156     cout << ENDL.data( list_ptr->E_out ) << ":  ";
01157     list_ptr->coefs.print( );
01158   }
01159 }
01160 
01161 // *********** class mf6_Legendre_raw ***********
01162 // ----------- mf6_Legendre_raw::read_data ---------
01163 void mf6_Legendre_raw::read_data( int NR, int num_E_in,
01164   int LEP, mf6_file& inFile )
01165 // Reads the Legendre data for all incident energies
01166 {
01167   bool done = false;
01168 
01169   // read the interpolation regions
01170   inFile.get_regions( NR, NBT, INT );
01171 
01172   // convert the data into a linked list
01173   for( int count = 0; count < num_E_in; ++count )
01174   {
01175     Legendre_list one_E_in;
01176     if( !done )
01177     {
01178       insert( end( ), one_E_in );
01179       mf6_Legendre_raw::iterator new_ptr = end( );
01180       --new_ptr;  // now points to the new link
01181       new_ptr->read_data( LEP, inFile, &done );
01182     }
01183     else
01184     {
01185       one_E_in.read_data( LEP, inFile, &done );
01186     }
01187   }
01188 }
01189 // ----------- mf6_Legendre_raw::get_max_order ---------
01190 int mf6_Legendre_raw::get_max_order( )
01191 // Gets the maximum Legendre order
01192 {
01193   int max_order = -1;
01194   // loop through the incident-energy lists
01195   for( mf6_Legendre_raw::iterator list_ptr = begin( );
01196        list_ptr != end( ); ++list_ptr )
01197   {
01198     if( list_ptr->order > max_order )
01199     {
01200       max_order = list_ptr->order;
01201     }
01202   }
01203   return max_order;
01204 }
01205 // ----------- mf6_Legendre_raw::expand_interp ---------
01206 void mf6_Legendre_raw::expand_interp( )
01207 // Expand the interpolation for the ENDF lists with respect to E_in
01208 {
01209   // Set the interpolation with respect to E_in
01210   int count = 0;
01211   int INT_index = 0;
01212   if( INT[ INT_index ] == 12 )
01213   {
01214     Info("mf6_Legendre_raw::expand_interp", "type 12 interpolation used");
01215   }
01216   else if( ( INT[ INT_index ] != 2 ) && ( INT[ INT_index ] != 22 ) )
01217   {
01218     Unimplemented("mf6_Legendre_raw::expand_interp",
01219         pastenum("Write code to expand interpolation ",INT[ INT_index ]));
01220   }
01221 
01222   // loop through the list
01223   for( mf6_Legendre_raw::iterator this_link = begin( );
01224       this_link != end( ); ++this_link, ++count )
01225   {
01226     // do we change interpolation types?
01227     if ( count >= NBT[ INT_index ] )
01228     {
01229       ++INT_index;
01230       if ( INT_index >= INT.size( ) )
01231       {
01232         SevereError("mf6_Legendre_raw::expand_interp","INT_index overflow");
01233       }
01234       if( ( INT[ INT_index ] != 2 ) && ( INT[ INT_index ] != 22 ) )
01235       {
01236         Unimplemented("mf6_Legendre_raw::expand_interp",
01237             pastenum("write code to expand interpolation ",INT[ INT_index ]));
01238       }
01239     }
01240     this_link->interp_type = INT[ INT_index ];
01241   }
01242 
01243   // Write code here to expand the interpolation with respect to E_in
01244 
01245 }
01246 
01247 
01248 // ----------- mf6_Legendre_raw::widen_jumps ---------
01249 void mf6_Legendre_raw::widen_jumps( )
01250 {
01251   // loop through the incident-energy lists
01252   for( mf6_Legendre_raw::iterator list_ptr = begin( );
01253        list_ptr != end( ); ++list_ptr )
01254   {
01255     list_ptr->widen_jumps( );
01256   }
01257 }
01258 
01259 
01260 // ----------- mf6_Legendre_raw::renorm ---------
01261 void mf6_Legendre_raw::renorm( )
01262 // Normalizes all of the lists
01263 {
01264   // loop through the incident-energy lists
01265   for( mf6_Legendre_raw::iterator list_ptr = begin( );
01266        list_ptr != end( ); ++list_ptr )
01267   {
01268     list_ptr->renorm( );
01269   }
01270 }
01271 // ----------- mf6_Legendre_raw::chop_E_in ---------
01272 void mf6_Legendre_raw::chop_E_in( double max_E_in )
01273 // deletes entries with E_in > max_E_in
01274 {
01275   double dE = ENDL_EPSILON( max_E_in );
01276   // All of the data may have E_in too big
01277   if( begin( )->E_in > max_E_in + dE )
01278   {
01279     ENDL.write_file = false;
01280     return;
01281   }
01282 
01283   mf6_Legendre_raw::iterator last_ptr = end( );
01284   --last_ptr;
01285   if( last_ptr->E_in > max_E_in + dE )
01286   {
01287     mf6_Legendre_raw::iterator prev_ptr = last_ptr;
01288     --prev_ptr;
01289     interpolate( max_E_in, prev_ptr, last_ptr );
01290     erase( last_ptr );
01291   }
01292 }
01293 // ----------- mf6_Legendre_raw::interpolate ---------
01294 void mf6_Legendre_raw::interpolate( double E_in,
01295   mf6_Legendre_raw::iterator prev_ptr,
01296   mf6_Legendre_raw::iterator next_ptr )
01297 // Insert a new interpolated link
01298 {
01299   Legendre_list new_list;
01300   insert( next_ptr, new_list );
01301   mf6_Legendre_raw::iterator new_ptr = next_ptr;
01302   --new_ptr; // now points to the new link
01303 
01304   // copy the prev_ptr data
01305   new_ptr->copy( *prev_ptr );
01306   new_ptr->E_in = E_in;
01307   // map to unit base
01308   new_ptr->unit_base( );
01309   next_ptr->unit_base( );
01310 
01311   // collect all of the outgoing energies
01312   list< double > E_outgoing;
01313   Legendre_list::iterator list_ptr;
01314   for( list_ptr = new_ptr->begin( ); 
01315       list_ptr != new_ptr->end( ); ++list_ptr )
01316   {
01317     E_outgoing.push_back( list_ptr->E_out );
01318   }
01319   for( list_ptr = next_ptr->begin( ); 
01320       list_ptr != next_ptr->end( ); ++list_ptr )
01321   {
01322     E_outgoing.push_back( list_ptr->E_out );
01323   }
01324   // sort the outgoing energies and remove duplicates
01325   E_outgoing.sort( );
01326   E_outgoing.unique( );
01327   // enforce common outgoing energies
01328   new_ptr->fill_with( E_outgoing );
01329   next_ptr->fill_with( E_outgoing );
01330 
01331   // take the average
01332   double alpha = ( E_in - prev_ptr->E_in ) /
01333     ( next_ptr->E_in - prev_ptr->E_in );
01334   *new_ptr *= 1.0 - alpha;
01335   *next_ptr *= alpha;
01336   *new_ptr += *next_ptr;
01337   new_ptr->least_E = ( 1.0 - alpha )*new_ptr->least_E +
01338     alpha*next_ptr->least_E;
01339   new_ptr->most_E = ( 1.0 - alpha )*new_ptr->most_E +
01340     alpha*next_ptr->most_E;
01341   // undo unit base
01342   new_ptr->rescale( );
01343 }
01344 // ----------- mf6_Legendre_raw::chop_E_out ---------
01345 void mf6_Legendre_raw::chop_E_out( double max_E_out )
01346 // deletes entries with E_out > max_E_out
01347 {
01348   for( mf6_Legendre_raw::iterator list_ptr = begin( );
01349        list_ptr != end( ); ++list_ptr )
01350   {
01351     list_ptr->chop_E_out( max_E_out );
01352   }
01353 }
01354 // ----------- mf6_Legendre_raw::print ---------
01355 void mf6_Legendre_raw::print( )
01356 // print for debugging
01357 {
01358   for( mf6_Legendre_raw::iterator list_ptr = begin( );
01359     list_ptr != end( ); ++list_ptr )
01360   {
01361     cout << ENDL.data( list_ptr->E_in ) << ":\n";
01362     list_ptr->print( );
01363   }
01364 }
01365 // *********** class mf6_one_order ***********
01366 // ----------- mf6_one_order::null_coefs ---------
01367 bool mf6_one_order::null_coefs( )
01368 // returns true if all entries are zero
01369 {
01370   for( mf6_one_order::iterator this_list = begin( );
01371        this_list != end( ); ++this_list)
01372   {
01373     double Norm = this_list->get_norm( );
01374     if( Norm != 0.0 )
01375     {
01376       return false;
01377     }
01378   }
01379   // they all were zero
01380   return true;
01381 }
01382 
01383 // *********** class mf6_Legendre ***********
01384 // ----------- mf6_Legendre::master ---------
01385 void mf6_Legendre::master( mf6_file& inFile, int LEP,
01386   int NR, int NE, bool res_copy )
01387 // Handles all the data
01388 {
01389   // Read all of the data
01390   ENDF_data.read_data( NR, NE, LEP, inFile );
01391   // delete the high incident energies
01392   ENDF_data.chop_E_in( ENDL.Max_E_in );
01393   // delete the high outgoing energies
01394   ENDF_data.chop_E_out( ENDL.Max_E_out );
01395 
01396   order = -1;  // default
01397   if( !ENDL.write_file )
01398   {
01399     return;  // this is data for the residual nucleus
01400   }
01401   order = ENDF_data.get_max_order( );
01402 
01403   // expand the interpolation with respect to E_in
01404   ENDF_data.expand_interp( );
01405   ENDF_data.widen_jumps( );  
01406   ENDF_data.renorm( );
01407 
01408   // convert to ENDL format
01409   reformat( );
01410 
01411   // remove redunant zeros
01412   reduce_order( );
01413 
01414   // print the ENDL file
01415   write_endl( );
01416 
01417   // Do we need to write a copy for the residual as particle?
01418   if( res_copy )
01419   {
01420     ENDL.outgoing_particle += 10;
01421     write_endl( );
01422   }
01423 }
01424 // ----------- mf6_Legendre::reformat ---------
01425 void mf6_Legendre::reformat( )
01426 // copy ENDF_data into ENDL_data
01427 {
01428   mf6_Legendre_raw::iterator ENDF_ptr;
01429 
01430   // pointers to the ENDL lists
01431   mf6_one_order::iterator ENDL_E_in[ order + 1 ];
01432 
01433   // set up space for ENDL_data
01434   ENDL_data.resize( order + 1 );
01435 
01436   // go through the ENDF data
01437   for( mf6_Legendre_raw::iterator ENDF_ptr = ENDF_data.begin( );
01438        ENDF_ptr != ENDF_data.end( ); ++ENDF_ptr )
01439   {
01440     // make a new 1-d list for each Legendre order
01441     for( int count = 0; count <= order; ++count )
01442     {
01443       one_d_table new_E_out;
01444       ENDL_data[ count ].insert( ENDL_data[ count ].end( ),
01445         new_E_out );
01446       ENDL_E_in[ count ] = ENDL_data[ count ].end( );
01447       --ENDL_E_in[ count ];
01448       ENDL_E_in[ count ]->E_in( ) = ENDF_ptr->E_in;
01449     }
01450 
01451     // now loop through the ENDF E_out links
01452     for( Legendre_list::iterator ENDF_Eout_ptr = ENDF_ptr->begin( );
01453          ENDF_Eout_ptr != ENDF_ptr->end( ); ++ENDF_Eout_ptr )
01454     {
01455       dd_link XYdata;
01456       XYdata.x = ENDF_Eout_ptr->E_out;
01457       // loop through the Legendre orders
01458       for( int ord_count = 0; ord_count <= ENDF_ptr->order;
01459         ++ord_count )
01460       {
01461         XYdata.y = ENDF_Eout_ptr->coefs[ ord_count ];
01462         ENDL_E_in[ ord_count ]->insert( ENDL_E_in[ ord_count ]->end( ),
01463           XYdata );
01464       }
01465       // we may need to fill out the list with zeros
01466       XYdata.y = 0.0;
01467       for( int ord_count = ENDF_ptr->order + 1; ord_count <= order;
01468         ++ord_count )
01469       {
01470         ENDL_E_in[ ord_count ]->insert( ENDL_E_in[ ord_count ]->end( ),
01471           XYdata );
01472       }
01473     }
01474   }
01475 }
01476 // ----------- mf6_Legendre::reduce_order ---------
01477 void mf6_Legendre::reduce_order( )
01478 // Reduces the order if high-order Legendre coefficients are all zero
01479 {
01480   int L_count;
01481 
01482   // print the data
01483   for( L_count = order; L_count > 0; --L_count )
01484   {
01485     if( !ENDL_data[ L_count ].null_coefs( ) )
01486     {
01487       // we found something nonzero at this order
01488       break;
01489     }
01490   }
01491   // reset the order
01492   order = L_count;
01493 }
01494 // ----------- mf6_Legendre::write_endl ---------
01495 void mf6_Legendre::write_endl( )
01496 // print the data in ENDL format
01497 {
01498   ENDL.set_I_number( 4 );
01499 
01500   fstream endl_file;
01501   string file_name = ENDL.file_name;
01502 
01503   if ( ENDL.new_file() )
01504   {
01505     endl_file.open(file_name.c_str(),ios::out);
01506     Info("mf6_Legendre::write_endl","Opening ENDL file "+file_name);
01507   }
01508   else
01509   {
01510     endl_file.open(file_name.c_str(),ios::out|ios::app);
01511     Info("mf6_Legendre::write_endl","Appending ENDL file "+file_name);
01512   }
01513 
01514   //Shove the header info in
01515   endl_file << ENDL.header_line_1 << endl;
01516   endl_file << ENDL.header_line_2 << endl;
01517   endl_file.setf(ios::scientific,ios::floatfield);
01518 
01519   // print the data
01520   for( int L_count = 0; L_count <= order; ++L_count )
01521   {
01522     ENDL_data[ L_count ].out_data( 4, endl_file, 1.0*L_count );
01523   }
01524 
01525   //Put on end of file/section line into output file
01526   endl_file << ENDL.eof_line << endl;
01527 
01528   //Finally, we close the output file
01529   Info("mf6_Legendre::write_endl","Closing ENDL file "+file_name);
01530   endl_file.close();
01531 }

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