Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev doeclim #206

Merged
merged 111 commits into from Jan 5, 2018
Merged

Dev doeclim #206

merged 111 commits into from Jan 5, 2018

Conversation

cahartin
Copy link
Contributor

@cahartin cahartin commented Nov 22, 2017

This PR includes the a new temperature component (DOECLIM) to better represent ocean heat uptake and global mean temperature change.

This document contains more detailed information on the changes.

bpbond and others added 30 commits January 19, 2016 07:35
Project file to Xcode 6.; C++ runtime used is now compiler default
(clang) instead of GNU C++; cleaned up header search paths; added
linker flags for boost `filesystem` and `system`. This allows building
on Mac OS X 10.11, Boost 1.60, and GSL 2.1.
linking boost and gsl libraries in both hector and  hector-lib project
files
See issue #136. This commit changes `main.cpp` so it returns nonzero
exit codes (1=program exception, 2=standard exception, 3=other
exception).
- 'SOx', 'NH3', 'C6F14', 'HALON1202'
Remove input variables which are not being used
boost (header only).  This opens the door to release hector under
different licenses that GPLv2.
Replace GSL algorithms including ODE integration with various libs from
information instead of including the license in each file.  This will
make less version control headache to release under different licenses.
Have header and source files reference LICENSE.md for licensing
instead just use the logger with cout echo turned on.  This closes #123.
Remove duplicative cout statements in the carbon-cycle-solver
…windows for that matter) the Xcode and xcode directories get merged as one causing extra confusion.
Remove extra visual studio and Xcode project files.
@cahartin cahartin added the enhancement Changes to the Hector software not affecting the representation of the Earth system label Nov 22, 2017
@cahartin cahartin added this to the v2.0 milestone Nov 22, 2017
Copy link
Member

@bpbond bpbond left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a great improvement to Hector, and nice job on the authorea document! Need more clarity in some spots, and more defensive programming in others (e.g. use of const).

@@ -26,6 +26,7 @@
#define OH_COMPONENT_NAME "OH"
#define N2O_COMPONENT_NAME "N2O"
#define TEMPERATURE_COMPONENT_NAME "temperature"
#define TEMP_DOECLIM_COMPONENT_NAME "temp_doeclim"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use a more meaningful name?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, the "DOE" here doesn't refer to the department of energy. OK then.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bpbond and @rplzzz yea it's diffusive ocean energy climate model. are there any licensing issues we need to be aware of of linking this one model with Hector? Can we still call it Hector?
https://github.com/scrim-network/BRICK

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are using DOEClim with the permission of its authors, right? If so, then it's fine. We should, however, acknowledge the code they donated. I have a note about that elsewhere.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have not done any investigations into permissions. DOECLIM has been used several times by Klaus Keller's group and I adapted their C++ implementation here. I'll check in with Ryan and Klaus about it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like one or more versions of DOECLIM have been released under GPLv3. Just get verbal confirmation from one of the original authors that they're ok with us releasing it under GPLv2. (The differences aren't really relevant to what we're doing; I like v2 because it's shorter and written in plain language.) Then we can just indicate that the code is used with permission.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renamed component. Still need to double check licensing.
(CH - tracking her changes)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A short update on the permissions: we now have emailed permission from Elmar Kriegler (original creator of DOECLIM) to use DOECLIM in Hector under GPLv2. I'm waiting for a response from Klaus Keller (coauthor of the paper for which the GPLv3 version was written).

Copy link
Contributor

@bvegawe bvegawe Dec 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We now also have emailed permission from the author of the DOECLIM version released under GPLv3

unitval k_max; //!< maximum ocean heat uptake efficiency, W/m2/K
unitval k_min; //!< minimum ocean heat uptake efficiency, W/m2/K
unitval slope; //!< slope of the curve, 1/K
// unitval cp; //!< Specific heat
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this commented out? Remove?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, i missed that one.

double ak; // slope in climate feedback - land-sea heat exchange linear relationship
double bk; // offset in climate feedback - land-sea heat exchange linear relationship, W/m2/K
double csw; // specific heat capacity of seawater W*yr/m3/K
double earth_area; // m2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like many of these should be const

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of doubles?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I mean, something like const double earth_area = x.xxx;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on @rplzzz 's comment below it looks like we should move these initializations to the header (some are called in more than one function so if we want to keep them together they need to be there). Those with well-known values will have const static, while those that are potentially tweakable will have const. Does that sound like what we want?

double A[4];
double IB[4];

//Dependent DOECLIM parameters
Copy link
Member

@bpbond bpbond Nov 22, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Space after //. Dependent on what? What's the difference between ocean_area below and the same variable name above? misread

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bpbond If these are just consts then we don't actually need them in the header?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmm. Feeling fuzzy on my C++. I think actually we'd want static const x = .... As for header or not, it depends; is it referred to in multiple component functions? If not, right, just move into the run method or wherever.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const means that once it's initialized, it can't be changed. static means that there is one copy for the entire class, instead of one for each object created. A member can be either const, static, neither, or both, depending on what you are trying to accomplish. For physical constants like the area of the earth or the specific heat of seawater, static const is the way to go. For something that might be a settable parameter (ak, perhaps?), you would generally do that as a normal (i.e., not static) member.

A static member is initialized just like a global variable, irrespective of whether or not it happens to be const. In fact, static members are basically just namespaced global variables, except that C++ does respect their private or protected visibility.

A member that is const, but not static must be initialized in the constructor. This is one of the rare cases in which the distinction between initialization and assignment matters. In this case you have to use the : notation to make it an initialization instead of an assignment. If you can't do that for some reason, such as because you have to construct the object before the initialization data is available, then you can't make the members const. Your best bet in this case is to make them ordinary members and to add a comment to the effect that once they are set they should be treated as const.

A constant that is only used in one method could be moved into that method, as Ben suggests, but sometimes it's best to make them const or static const. The reason why is that if someone wants to know, what are they using for the xyz parameter, it's a lot easier to find it if it's with all the other constants, rather than tucked away at the beginning of some particular method they might not know the name of. Also, if you end up refactoring so that more than one method uses the constant, then you'll have to make the constant a member anyhow. Starting it off that way future proofs your design a bit.

* \param[in] y Inverted 1-d matrix
* \returns void, inverse is stored in y
*/
void TempDOECLIMComponent::invert_1d_2x2_matrix(double * x, double * y) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we depend on Boost anyway, why not use its ublas library?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any Boost inversion implementation I saw in my cursory google search looked a good deal more complex than this simple algorithm for 2x2 inversion. But I could be wrong!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's correct. If you know the matrix is 2x2, you can invert it very simply using analytic formulae. It's similar to how you could solve an equation using the Newton-Raphson method, but if you happen to know it's quadratic, it's simpler to use the quadratic formula.

tauksl = (1.0 - flnd) * cas / kls;
taukls = flnd * cal / kls;

// First order
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some more documentation needed here--what's going on?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bvegawe can you add a few comments here? thank you!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My guess is that this has all been explained in a paper somewhere. We should include a pointer to the paper and document any mappings between names used in the paper and names used here that aren't obvious.

//// to match a temperature record), need to track the Ftot that *would* have
//// produced the observed temperature record. This way there's a smooth
//// transition when we exit the constraint period, after which internal_Ftot
//// will rise in parallel with the value reported by ForcingComponent.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice commenting and logic.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bpbond i think that was you back in the day!

@bpbond
Copy link
Member

bpbond commented Nov 22, 2017

Note also my comment about using Boost–I doubt we want to roll our own matrix-inversion functions, but will defer to @rplzzz here.

Copy link
Contributor

@rplzzz rplzzz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lots of cleanup needed in various places, though most of it shouldn't be too much work. I did have a question about ocean heat flux that I would like to see some discussion on, but everything else is minor.

@@ -0,0 +1,401 @@
; Config file for hector model: RCP85
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the story with this file? We have already added DOEclim to the rcp85.ini file above, so why is this one necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point. this was our initial test case file.

@@ -1,87 +0,0 @@
/* Hector -- A Simple Climate Model
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really don't love that we are deleting the original temperature component entirely. The whole idea behind Hector's design is that we are supposed to be able to add and drop components as needed. I get that we don't want components to proliferate because then we have to maintain them all, but so far maintaining components hasn't been a huge amount of effort. Is the original temperature component really unable to coexist with the DOEClim temperature (in the code base, I mean; obviously only one of them can be active in any single run)?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my experience, it works fine with both components and just specifying which version you want to use in the .ini file. It does lead to a couple warnings like below:
WARNING:registerCapability: temperature is declaring capability Tgav previously registered

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They can exist together and do currently. My concern is that the old way was a hack with a bunch of bugs that were found. I don't think I want people having an easy option to get back incorrect results by turning on that old component.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds reasonable. Since that leaves the doeclim temperature component as the only temperature component, maybe we should just rename it to "temperature_component". (We would still explain its doeclim origins in comments in the source file, of course.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


lastflux_annualized.set( 0.0, U_PGC );

// Register the data we can provide
core->registerCapability( D_OCEAN_CFLUX, getComponentName() );
core->registerCapability( D_OCEAN_C, getComponentName() );
core->registerCapability( D_HEAT_FLUX, getComponentName() );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I take it these heat flux capabilities have been moved to the DOEClim component?

Edit: Actually, it doesn't look like they have. Are we just not supporting retrieving the ocean heat flux anymore, or is it going to known by a different name going forward? Apart from being a serious backward-incompatible change, it would be kind of unfortunate if we could no longer get this information from the model.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With DOECLIM, we calculate a flux into the mixed layer and a flux into the interior. For backward compatibility, I'll make a note to also do a total heat flux.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heat flux is calculated in the DOECLIM component now. @bvegawe that's a good idea to have total heat flux into the ocean.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

/*! \brief Calculates inverse of x and stores in y
* \param[in] x Assume x is setup like x = [a,b,c,d] -> x = |a, b|
* |c, d|
* \param[in] y Inverted 1-d matrix
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be documented as param[out] or param[inout], depending on whether the function expects y to be initialized.

/*! \brief Calculates element-wise sum of matrix x and y, stores in z
* \param[in] x,y Assume x,y setup like x = [a,b,c,d] -> x = |a, b|
* |c, d|
* \param[in] z Summed 1-d matrix
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also is param[out].

//
// If the user has supplied temperature data, use that (except if past its end)
if( tgav_constrain.size() && runToDate <= tgav_constrain.lastdate() ) {
// H_LOG( logger, Logger::NOTICE ) << "** Using user-supplied temperature" << std::endl;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete this line. Saving an old version of an error message in a commented line is perhaps the most egregious example of code hoarding I can think of.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bpbond @rplzzz we should probably get this constraint working again in the new component. for now i'll leave the comments in and we can test this later.

// H_LOG( logger, Logger::NOTICE ) << "** Using user-supplied temperature" << std::endl;
H_LOG( logger, Logger::NOTICE ) << "** ERROR - DOECLIM can't currently handle user-supplied temperature" << std::endl;
}
// tgav = tgav_constrain.get( runToDate );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lots of commented-out code from here to line 385. Clean it up.

double aero_forcing = double(core->sendMessage( M_GETDATA, D_RF_BC ).value( U_W_M2 )) + double(core->sendMessage( M_GETDATA, D_RF_OC ).value( U_W_M2 )) + double(core->sendMessage( M_GETDATA, D_RF_SO2d ).value( U_W_M2 )) + double(core->sendMessage( M_GETDATA, D_RF_SO2i ).value( U_W_M2 ));
forcing[tstep] = double(core->sendMessage( M_GETDATA, D_RF_TOTAL ).value( U_W_M2 )) - ( 1.0 - alpha ) * aero_forcing;

// Initialize variables for time-stepping through the model
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the next 80 lines or so copied/translated from the original DOEClim code base? If so, we should maybe include a pointer to that code, both so that anyone who wants to look at it can, and also to document that it was copied with the knowledge and permission of its authors and maintainers.

@@ -26,6 +26,7 @@
#define OH_COMPONENT_NAME "OH"
#define N2O_COMPONENT_NAME "N2O"
#define TEMPERATURE_COMPONENT_NAME "temperature"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are removing the old temperature component, then shouldn't we also remove this #define?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -26,6 +26,7 @@
#define OH_COMPONENT_NAME "OH"
#define N2O_COMPONENT_NAME "N2O"
#define TEMPERATURE_COMPONENT_NAME "temperature"
#define TEMP_DOECLIM_COMPONENT_NAME "temp_doeclim"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are using DOEClim with the permission of its authors, right? If so, then it's fine. We should, however, acknowledge the code they donated. I have a note about that elsewhere.

Copy link
Contributor

@rplzzz rplzzz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition to what I wrote before (which seems to be interspersed with the line comments for some reason, so you have to hunt for it a bit), here are two more things.

  1. Can we please get rid of this junk:
Wed Nov 22 02:46:24 2017:NOTICE:run: Attempting ODE solver 1878->1879 (1878->1879)
Wed Nov 22 02:46:24 2017:NOTICE:run: Success: we have reached 1879
Wed Nov 22 02:46:24 2017:NOTICE:run: ODE solver success at t= 1879  last dt= 0.5

As far as I can tell, it's useful only when something goes wrong, so we should downgrade it to debug level and make notice level output the default.

  1. The code is failing its tests, presumably because we've changed the model, so naturally the outputs no longer match. Once we are satisfied with the results using the new model, we need to update the comparison data for the tests.

@cahartin cahartin changed the base branch from master to rc2.0.0 November 29, 2017 18:30
@rgieseke rgieseke mentioned this pull request Nov 30, 2017
bvegawe and others added 8 commits November 30, 2017 15:35
additional descriptions of model parameters and calculations. added a
total ocean heat flux output parameter to match the parameter output by
the original temperature component
Dev doeclim: improved DOECLIM descriptions, total heat flux output
renamed temp_doeclim to temperature in code and ini files
updates to header to include a few more parameters not specified
Copy link
Contributor

@rplzzz rplzzz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My biggest comment has been addressed. There were a couple other things, but the world won't come to an end if they're not addressed, and we should move this thing along.

Forgot to add the factor for the slightly smaller surface area of the
interior ocean
includes full citations and the fact that we have permission.
set hard-coded DOECLIM parameters to const; moved their initializations
to the header. if these initializations are static I get a warning, so
just const for now.
@cahartin cahartin added this to To Do in checklist for v2.0 Jan 5, 2018
dev_doeclim: a bug fix, const parameters, updated references
@cahartin cahartin merged commit b5e7c3b into rc2.0.0 Jan 5, 2018
@cahartin cahartin moved this from To Do to Done in checklist for v2.0 Jan 8, 2018
@rplzzz rplzzz deleted the dev_doeclim branch June 20, 2018 13:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Changes to the Hector software not affecting the representation of the Earth system
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

None yet

7 participants