src/simpleNbox.cpp
//------------------------------------------------------------------------------
/*! \brief                  Transfer new model pools from ODE solver array back to model pools
 *  \param[in] t            Time, double, the ending date of the solver
 *  \param[in] double       Flat array of carbon pools (no units)
 *  \exception h_exception  If ocean model diverges from our pool tracking all ocean C
 *  \exception h_exception  If mass is not conserved
 *
 *  \details Transfer solver pools (no units) back to our pools (with units), and run
 *  a sanity check to make sure mass has been conserved.
 */


\details Transfer solver pools (no units) back to our pools (with units), and run
a sanity check to make sure mass has been conserved.
\ details Transfer solver pools ( no units ) back to our pools ( with units ) and run a sanity check to make sure mass has been conserved .
void SimpleNbox::stashCValues( double t, const double c[] )
{
    const double yf = ( t - ODEstartdate );
    H_ASSERT( yf >= 0 && yf <= 1, "yearfraction out of bounds" );
    H_LOG( logger,Logger::DEBUG ) << "Stashing at t=" << t << ", solver pools at " << t << ": " << c[ 0 ]
    << " " << c[ 1 ] << " " << c[ 2 ] << " " << c[ 3 ] << " " << c[ 4 ] << " " << c[ 5 ] << std::endl;
    log_pools( t );
    atmos_c.set( c[ SNBOX_ATMOS ], U_PGC );
    const unitval npp_rh_total = sum_npp() + sum_rh(); 
    const unitval newveg( c[ SNBOX_VEG ], U_PGC );
    const unitval newdet( c[ SNBOX_DET ], U_PGC );
    const unitval newsoil( c[ SNBOX_SOIL ], U_PGC );
    unitval veg_delta = newveg - sum_map( veg_c );  
    unitval det_delta = newdet - sum_map( detritus_c );  
    unitval soil_delta = newsoil - sum_map( soil_c );  
    H_LOG( logger,Logger::DEBUG ) << "veg_delta = " << veg_delta << std::endl;
    H_LOG( logger,Logger::DEBUG ) << "det_delta = " << det_delta << std::endl;
    H_LOG( logger,Logger::DEBUG ) << "soil_delta = " << soil_delta << std::endl;
    for( unitval_stringmap::const_iterator it = veg_c.begin(); it != veg_c.end(); it++ ) {
        std::string biome = it->first;
        const double wt     = ( npp( biome ) + rh( biome ) ) / npp_rh_total;
        veg_c[ biome ]      = veg_c[ biome ] + veg_delta * wt;
        detritus_c[ biome ] = detritus_c[ biome ] + det_delta * wt;
        soil_c[ biome ]     = soil_c[ biome ] + soil_delta * wt;
        H_LOG( logger,Logger::DEBUG ) << "Biome " << biome << " weight = " << wt << std::endl;
    }
    log_pools( t );
    omodel->stashCValues( t, c );   
    earth_c.set( c[ SNBOX_EARTH ], U_PGC );
    log_pools( t );
    double sum=0.0;
    for( int i=0; i<ncpool(); i++ ) {
        sum += c[ i ];
    }
    const double diff = fabs( sum - masstot );
    H_LOG( logger,Logger::DEBUG ) << "masstot = " << masstot << ", sum = " << sum << ", diff = " << diff << std::endl;
    if(masstot > 0.0 && diff > MB_EPSILON) {
        H_LOG( logger,Logger::SEVERE ) << "Mass not conserved in " << getComponentName() << std::endl;
        H_LOG( logger,Logger::SEVERE ) << "masstot = " << masstot << ", sum = " << sum << ", diff = " << diff << std::endl;
        H_THROW( "Mass not conserved! (See log.)" );
    }
    masstot = sum;
    if( !core->inSpinup() && Ca_constrain.size() && t <= Ca_constrain.lastdate() ) {
        H_LOG( logger, Logger::WARNING ) << "** Constraining atmospheric CO2 to user-supplied value" << std::endl;
        unitval atmos_cpool_to_match( Ca_constrain.get( t ).value( U_PPMV_CO2 ) / PGC_TO_PPMVCO2, U_PGC );
        residual = atmos_c - atmos_cpool_to_match;
        H_LOG( logger,Logger::DEBUG ) << t << "- have " << Ca << " want " << Ca_constrain.get( t ).value( U_PPMV_CO2 ) << std::endl;
        H_LOG( logger,Logger::DEBUG ) << t << "- have " << atmos_c << " want " << atmos_cpool_to_match << "; residual = " << residual << std::endl;
        H_LOG( logger,Logger::DEBUG ) << "Sending residual of " << residual << " to deep ocean" << std::endl;
        core->sendMessage( M_DUMP_TO_DEEP_OCEAN, D_OCEAN_C, message_data( residual ) );
        atmos_c = atmos_c - residual;
        Ca.set( atmos_c.value( U_PGC ) * PGC_TO_PPMVCO2, U_PPMV_CO2 );
    } else {
        residual.set( 0.0, U_PGC );
    }
    ODEstartdate = t;
}
void SimpleNbox :: stashCValues ( double t , const double c [ ] ) { const double yf = ( t - ODEstartdate ) ; H_ASSERT ( yf >= 0 && yf <= 1 , " " ) ; H_LOG ( logger , Logger :: DEBUG ) << " " << t << " " << t << " " << c [ 0 ] << " " << c [ 1 ] << " " << c [ 2 ] << " " << c [ 3 ] << " " << c [ 4 ] << " " << c [ 5 ] << std :: endl ; log_pools ( t ) ; atmos_c . set ( c [ SNBOX_ATMOS ] , U_PGC ) ; const unitval npp_rh_total = sum_npp ( ) + sum_rh ( ) ; const unitval newveg ( c [ SNBOX_VEG ] , U_PGC ) ; const unitval newdet ( c [ SNBOX_DET ] , U_PGC ) ; const unitval newsoil ( c [ SNBOX_SOIL ] , U_PGC ) ; unitval veg_delta = newveg - sum_map ( veg_c ) ; unitval det_delta = newdet - sum_map ( detritus_c ) ; unitval soil_delta = newsoil - sum_map ( soil_c ) ; H_LOG ( logger , Logger :: DEBUG ) << " " << veg_delta << std :: endl ; H_LOG ( logger , Logger :: DEBUG ) << " " << det_delta << std :: endl ; H_LOG ( logger , Logger :: DEBUG ) << " " << soil_delta << std :: endl ; for ( unitval_stringmap :: const_iterator it = veg_c . begin ( ) ; it != veg_c . end ( ) ; it ++ ) { std :: string biome = it -> first ; const double wt = ( npp ( biome ) + rh ( biome ) ) / npp_rh_total ; veg_c [ biome ] = veg_c [ biome ] + veg_delta * wt ; detritus_c [ biome ] = detritus_c [ biome ] + det_delta * wt ; soil_c [ biome ] = soil_c [ biome ] + soil_delta * wt ; H_LOG ( logger , Logger :: DEBUG ) << " " << biome << " " << wt << std :: endl ; } log_pools ( t ) ; omodel -> stashCValues ( t , c ) ; earth_c . set ( c [ SNBOX_EARTH ] , U_PGC ) ; log_pools ( t ) ; double sum = 0.0 ; for ( int i = 0 ; i < ncpool ( ) ; i ++ ) { sum += c [ i ] ; } const double diff = fabs ( sum - masstot ) ; H_LOG ( logger , Logger :: DEBUG ) << " " << masstot << " " << sum << " " << diff << std :: endl ; if ( masstot > 0.0 && diff > MB_EPSILON ) { H_LOG ( logger , Logger :: SEVERE ) << " " << getComponentName ( ) << std :: endl ; H_LOG ( logger , Logger :: SEVERE ) << " " << masstot << " " << sum << " " << diff << std :: endl ; H_THROW ( " " ) ; } masstot = sum ; if ( ! core -> inSpinup ( ) && Ca_constrain . size ( ) && t <= Ca_constrain . lastdate ( ) ) { H_LOG ( logger , Logger :: WARNING ) << " " << std :: endl ; unitval atmos_cpool_to_match ( Ca_constrain . get ( t ) . value ( U_PPMV_CO2 ) / PGC_TO_PPMVCO2 , U_PGC ) ; residual = atmos_c - atmos_cpool_to_match ; H_LOG ( logger , Logger :: DEBUG ) << t << " " << Ca << " " << Ca_constrain . get ( t ) . value ( U_PPMV_CO2 ) << std :: endl ; H_LOG ( logger , Logger :: DEBUG ) << t << " " << atmos_c << " " << atmos_cpool_to_match << " " << residual << std :: endl ; H_LOG ( logger , Logger :: DEBUG ) << " " << residual << " " << std :: endl ; core -> sendMessage ( M_DUMP_TO_DEEP_OCEAN , D_OCEAN_C , message_data ( residual ) ) ; atmos_c = atmos_c - residual ; Ca . set ( atmos_c . value ( U_PGC ) * PGC_TO_PPMVCO2 , U_PPMV_CO2 ) ; } else { residual . set ( 0.0 , U_PGC ) ; } ODEstartdate = t ; }
\brief                  Transfer new model pools from ODE solver array back to model pools
  \param[in] t            Time, double, the ending date of the solver
  \param[in] double       Flat array of carbon pools (no units)
  \exception h_exception  If ocean model diverges from our pool tracking all ocean C
  \exception h_exception  If mass is not conserved
\ brief Transfer new model pools from ODE solver array back to model pools \ param [ in ] t Time double the ending date of the solver \ param [ in ] double Flat array of carbon pools ( no units ) \ exception h_exception If ocean model diverges from our pool tracking all ocean C \ exception h_exception If mass is not conserved
// Solver has gone from ODEstartdate to t // Store solver pools into our internal variables // The solver just knows about one vegetation box, one detritus, and one // soil. So we need to apportion new veg C pool (set by the solver) to // as many biomes as we have. This is not ideal. // TODO: Solver actually solves all boxes in multi-biome system // Apportioning is done by NPP and RH // i.e., biomes with higher values get more of any C change // these are both positive // TODO: make const // TODO: make const // TODO: make const // tell ocean model to store new C values // Each time the model pools are updated, check that mass has been conserved // If user has supplied Ca values, adjust atmospheric C to match // Transfer C from atmosphere to deep ocean and update our C and Ca variables // All good! t will be the start of the next timestep, so