src/oceanbox.cpp
//------------------------------------------------------------------------------
/*! \brief                  Equilibrate the chemistry model to a given flux
 *  \param[in] Ca           Atmospheric CO2 (ppmv)
 *
 *  \details The global carbon cycle can be spun up with ocean chemistry either
 *  on or off. In the former case, the ocean continually equilibrates with the
 *  atmosphere during spinup, and the entire system should come to steady state.
 *  In the latter case, the ocean is sealed off from the atmosphere during
 *  spinup, with no surface chemistry; this presumes we know exactly how much
 *  carbon should be in the preindustrial ocean. Before chemistry is re-enabled
 *  for the main run, however, we need to adjust ocean conditions (alkalinity)
 *  such that the chemistry model will produce the specified spinup-condition
 *  fluxes. That's what this method does. Note that we pass in current CO2 because
 *  in case the model was NOT spun up, need to set the box's internal tracking var.
 */
\brief                  Equilibrate the chemistry model to a given flux
\param[in] Ca           Atmospheric CO2 (ppmv)

\details The global carbon cycle can be spun up with ocean chemistry either
on or off. In the former case, the ocean continually equilibrates with the
atmosphere during spinup, and the entire system should come to steady state.
In the latter case, the ocean is sealed off from the atmosphere during
spinup, with no surface chemistry; this presumes we know exactly how much
carbon should be in the preindustrial ocean. Before chemistry is re-enabled
for the main run, however, we need to adjust ocean conditions (alkalinity)
such that the chemistry model will produce the specified spinup-condition
fluxes. That's what this method does. Note that we pass in current CO2 because
in case the model was NOT spun up, need to set the box's internal tracking var.
\ brief Equilibrate the chemistry model to a given flux \ param [ in ] Ca Atmospheric CO2 ( ppmv ) \ details The global carbon cycle can be spun up with ocean chemistry either on or off . In the former case the ocean continually equilibrates with the atmosphere during spinup and the entire system should come to steady state . In the latter case the ocean is sealed off from the atmosphere during spinup with no surface chemistry ; this presumes we know exactly how much carbon should be in the preindustrial ocean . Before chemistry is re - enabled for the main run however we need to adjust ocean conditions ( alkalinity ) such that the chemistry model will produce the specified spinup - condition fluxes . That ' s what this method does . Note that we pass in current CO2 because in case the model was NOT spun up need to set the box ' s internal tracking var .
void oceanbox::chem_equilibrate( const unitval current_Ca ) {
	using namespace std;
    Ca = current_Ca;
	H_ASSERT( active_chemistry, "chemistry not turned on" );
	OB_LOG( logger, Logger::DEBUG) << "Equilibrating chemistry for box " << Name << endl;
    unitval dic = mychemistry.convertToDIC( carbon );
	OB_LOG( logger, Logger::DEBUG) << "Ca=" << Ca << ", DIC=" << dic <<  endl;
	double alk_min = 2100e-6, alk_max = 2750e-6;
	double f_target = preindustrial_flux.value( U_PGC_YR );
	OB_LOG( logger, Logger::DEBUG) << "Looking for best-guess alkalinity" << endl;
	const int w = 12;
	OB_LOG( logger, Logger::DEBUG) << setw( w ) << "Alk" << setw( w ) << "FPgC"
        << setw( w ) << "f_target" << setw( w ) << "diff" << endl;
	double min_diff = 1e6;
	double min_point = ( alk_min + alk_max ) / 2.0;
	for( double alk1=alk_min; alk1 <= alk_max; alk1 += (alk_max-alk_min)/20 ) {
		double diff = fmin( alk1, &f_target );
		if( diff < min_diff ) {
			min_diff = diff;
			min_point = alk1;
		}
		OB_LOG( logger, Logger::DEBUG) << setw( w ) << alk1 << setw( w ) << atmosphere_flux
        << setw( w ) << f_target << setw( w ) << diff << endl;
	}
	double alk = min_point;        
	OB_LOG( logger, Logger::DEBUG) << "Best guess minimum is at " << alk << endl;
    FMinWrapper fFunctor(this, f_target);
    const int digits = numeric_limits<double>::digits;
    int get_digits = static_cast<int>(digits * 0.6);
    std::pair<double, double> r = boost::math::tools::brent_find_minima(fFunctor, alk_min, alk_max, get_digits);
	OB_LOG( logger, Logger::DEBUG) << setw( w ) << "Alk" << setw( w ) << "FPgC"
        << setw( w ) << "f_target" << setw( w ) << "diff" << endl;
    OB_LOG( logger, Logger::DEBUG) << setw( w ) << r.first << setw( w ) << atmosphere_flux
        << setw( w ) << f_target << setw( w ) << r.second << endl;
}
void oceanbox :: chem_equilibrate ( const unitval current_Ca ) { using namespace std ; Ca = current_Ca ; H_ASSERT ( active_chemistry , " " ) ; OB_LOG ( logger , Logger :: DEBUG ) << " " << Name << endl ; unitval dic = mychemistry . convertToDIC ( carbon ) ; OB_LOG ( logger , Logger :: DEBUG ) << " " << Ca << " " << dic << endl ; double alk_min = 2100e-6 , alk_max = 2750e-6 ; double f_target = preindustrial_flux . value ( U_PGC_YR ) ; OB_LOG ( logger , Logger :: DEBUG ) << " " << endl ; const int w = 12 ; OB_LOG ( logger , Logger :: DEBUG ) << setw ( w ) << " " << setw ( w ) << " " << setw ( w ) << " " << setw ( w ) << " " << endl ; double min_diff = 1e6 ; double min_point = ( alk_min + alk_max ) / 2.0 ; for ( double alk1 = alk_min ; alk1 <= alk_max ; alk1 += ( alk_max - alk_min ) / 20 ) { double diff = fmin ( alk1 , & f_target ) ; if ( diff < min_diff ) { min_diff = diff ; min_point = alk1 ; } OB_LOG ( logger , Logger :: DEBUG ) << setw ( w ) << alk1 << setw ( w ) << atmosphere_flux << setw ( w ) << f_target << setw ( w ) << diff << endl ; } double alk = min_point ; OB_LOG ( logger , Logger :: DEBUG ) << " " << alk << endl ; FMinWrapper fFunctor ( this , f_target ) ; const int digits = numeric_limits < double > :: digits ; int get_digits = static_cast < int > ( digits * 0.6 ) ; std :: pair < double , double > r = boost :: math :: tools :: brent_find_minima ( fFunctor , alk_min , alk_max , get_digits ) ; OB_LOG ( logger , Logger :: DEBUG ) << setw ( w ) << " " << setw ( w ) << " " << setw ( w ) << " " << setw ( w ) << " " << endl ; OB_LOG ( logger , Logger :: DEBUG ) << setw ( w ) << r . first << setw ( w ) << atmosphere_flux << setw ( w ) << f_target << setw ( w ) << r . second << endl ; }
\brief                  Equilibrate the chemistry model to a given flux
  \param[in] Ca           Atmospheric CO2 (ppmv)
\ brief Equilibrate the chemistry model to a given flux \ param [ in ] Ca Atmospheric CO2 ( ppmv )
// Initialize the box chemistry values: temperature, atmospheric CO2, DIC //	mychemistry.ocean_csys_run( Tbox, carbon ); // Tune the chemistry model's alkalinity parameter to produce a particular flux. // This happens after the box model has been spun up with chemistry turned off, before the chemistry // model is turned on (because we don't want it to suddenly produce a larger ocean-atmosphere flux). // Here we use the Brent algorithm //      http://www.gnu.org/software/gsl/manual/html_node/Minimization-Algorithms.html // to minimize abs(f-f0), where f is computed by the csys chemistry code and f0 passed in // Find a best-guess point; the GSL algorithm seems to need it // this is our best guess // arbitrarily solve unil 60% of the digits are correct.