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

Thermal energy based temperature system #27387

Merged
merged 92 commits into from Mar 14, 2019

Conversation

Projects
None yet
@Hirmuolio
Copy link
Contributor

commented Dec 31, 2018

Summary

Each item gets its temperature and thermal energy tracked for better phase changes. Items also cool/heat based on energy flow to/from the enviroment.

SUMMARY: Balance "Item temperatures are now based on their thermal energy"

Purpose of change

In current system items freeze/unfreeze instantly after reaching the required temperature.

Also in current system the cooling/heating happens purely based on the temperature difference. As a result all items cool and heat at identical rates.

Describe the solution

The new heating/cooling are based on energy flow which is based on item volume and mass.

For liquid and solid items the temperature change is calculated with solution which is based on Newton's law of cooling and rate of heat flow.
T(t) = T_e + ( T_0 - T_e ) * exp( - t * I / ( m * c ) )

For partially frozen items the energy change is calculated with rate of heat flow and the phase change is calculated from the energy.
E(t) = E_0 + I * m * ( T_0 - T_e ) * t / m

where T_e is enviroment temperature, T_0 is item temperature at beginning, t is time, I is conductivity term, m is mass and c is specific heat (either liquid or solid).

The conductivity_term is constant chosen so that 1 l of water cools from 55 °C to 35 °C in about 75 minutes ( to match https://www.researchgate.net/publication/282841499_Study_on_heat_transfer_coefficients_during_cooling_of_PET_bottles_for_food_beverages). Greater values make items change temperature faster. Surface area is calculated into the conductivity term. This value is subjective and can be changed.

Item temperature is calculated using the item's mass and freezing temperature and also the average of the item's materials' specific heat (both liquid and solid) and latent heat of fusion. If specific heats or latent heat are not specified for the item the values of water are used.

The new the freezing/unfreezing happens more realistically based on thermal energy in the item. If the item has enough energy to be at least 50% liquid then it will be considered to be liquid.

Temperature tags are assigned based on temperatures defined in game_constants.cpp:
"FROZEN" = Below freezing temperature
"COLD" = 4.4 °C
"HOT" = 38 °C

Describe alternatives you've considered

If item volume and mass do not have meaningful impact on the temperature system then the calculations can be simplified so that all items again heat/cool at same rate while still keeping energy based temperature system.

The average of the materials of the item is not the best solution. But some items get their vitamins from the average of their materials so adding new materials to them would change their vitamin contents.
Better system would be to use the first material of the item. Or to add a new field on the items that decides what is the main material it is made of.

Additional context

The heat flow is based on https://en.wikipedia.org/wiki/Rate_of_heat_flow and https://en.wikipedia.org/wiki/Newton's_law_of_cooling. All the variables that can not be easily aquired in game are lumped in the conductivity_term constant.

@Hirmuolio

This comment has been minimized.

Copy link
Contributor Author

commented Dec 31, 2018

More things to do/check.

In item.cpp in std::string item::info there is omething about the temperature tags and item_counters but I don't know what it does.

No item has its thermal properties yet. So all items behave as if they were water.

When item is spawned it starts at temperature of 0 K and negative energy (but no tags or anything so it behaves like normal room temperature item). The new items are set to enviroment temperature at next temperature check. Up to 5 minutes later. (Cooked items that become hot on cooking are set immediately).

game_constants.h has constants for hot (38 C), cold (4.4 C) and freezing (0 C).
I didn't use them since there was no constant for warm and the hot one seems too low. I don't know if they are used somewhere else so I didn't start changing them.

@kevingranade

This comment has been minimized.

Copy link
Member

commented Dec 31, 2018

This pull request has been mentioned on Cataclysm: Dark Days Ahead. There might be relevant details there:

https://discourse.cataclysmdda.org/t/the-current-system-for-food-temperatures-is-flawed/17119/30

@Inglonias

This comment has been minimized.

Copy link
Contributor

commented Dec 31, 2018

This is neat, but we need to do some heavy testing to ensure that this doesn't break existing games. I don't want to see a repeat of the era a few months back where food temperature was going haywire.

Hirmuolio added some commits Dec 31, 2018

Freezeburn, temperature for newly spawned items
Freezeburn is again applied when items melt
Newly spawned items should set their temperatures faster now
@mlangsdorf
Copy link
Contributor

left a comment

Please follow CDDA's manual of code style and make sure ( ) are separated by spaces. I gave suggestions for a couple but there's many more.

also consider storing temperature as an integer in milliKelvins and passing energy as an integer in milli or centi Joules.

Show resolved Hide resolved src/item.cpp Outdated
Show resolved Hide resolved src/item.cpp Outdated
Show resolved Hide resolved src/item.cpp Outdated
Show resolved Hide resolved src/item.cpp Outdated
@Hirmuolio

This comment has been minimized.

Copy link
Contributor Author

commented Dec 31, 2018

I already said that we can't go to smaller unit of energy without causing 200 liter water tank energy to overflow. And breaking temperatures for items that are in vanilla would be bad.
Energy in 200 l of liquid water at 0 °C = 200000 g * ( 273.15 K * 2.108 J/gK + 334 J/g ) = 181960040 J. Both milli and centi joules would overflow.
At 100 °C the energy would be 265680040 and even deci joules would overflow.

The temperature does not really need any extra precision. Comparing item temperature to enviroment temperature is practically the only place where the "exact" temperature is used. But since high temperatures would never be used we could go for more precision without worrying about temperature overflowing.

And I used farenheits for it to make it easier to ineract with other systems that use farenheit without need to do conversion. So if we don't use farenheits we might as well convert from celcius or kelvin instead of from milli farenheit. (Also using metric prefixes with imperial units!)

mlangsdorf and others added some commits Dec 31, 2018

spaces for ()
Co-Authored-By: Hirmuolio <hirmuolio@gmail.com>
spaces for ()
Co-Authored-By: Hirmuolio <hirmuolio@gmail.com>
spaces for ()
Co-Authored-By: Hirmuolio <hirmuolio@gmail.com>
spaces for ()
Co-Authored-By: Hirmuolio <hirmuolio@gmail.com>
@nexusmrsep

This comment has been minimized.

Copy link
Contributor

commented Jan 1, 2019

Simulation like this doesn't have to account for every nook and cranny to do NASA style calculations. If you just take item weight into account to simulate that your steak will freeze a bit quicker then your freshly killed turkey, and your small bottle of water will freeze faster then then a barrel full of water then you are in the clear.

Hirmuolio added some commits Jan 1, 2019

Show resolved Hide resolved src/item.cpp Outdated
Show resolved Hide resolved src/item.cpp Outdated
Show resolved Hide resolved src/item.cpp Outdated
Show resolved Hide resolved src/item.cpp Outdated
Show resolved Hide resolved src/item.cpp Outdated
Show resolved Hide resolved src/item.cpp Outdated
Show resolved Hide resolved src/item.cpp Outdated
Show resolved Hide resolved src/item.cpp Outdated
Show resolved Hide resolved src/item.cpp Outdated
Show resolved Hide resolved src/item.cpp Outdated
Show resolved Hide resolved src/item.cpp Outdated
Show resolved Hide resolved src/item.cpp Outdated
@kevingranade

This comment has been minimized.

Copy link
Member

commented Mar 9, 2019

I've come to the conclusion that I cannot merge this until we have some unit tests for it, I'm not going to be able to develop the appropriate level of confidence in it's correctness until I do that.

@Hirmuolio

This comment has been minimized.

Copy link
Contributor Author

commented Mar 9, 2019

I don't know much about tests. What kind of things the tests should cover?

Something like this?:
Spawn item meat pie
Check its attributes (specific heats and latent heat of fusion)
Let the item be in a certain temperature for a set time. Check the temperature after.
Repeat the above for different cases (liquid, solid, melting, freezing, durations)

@kevingranade

This comment has been minimized.

Copy link
Member

commented Mar 9, 2019

Exactly that kind of thing, the overall form is:
Set a scenario, i.e. "room temperature water sitting in -5C temperature".
An action occurs, i.e. "30 minutes pass".
.Make an assertion about the outcome, i.e. "the water temperature has dropped to X".

We need a variety of these focusing on scenarios typically encountered by the player, i.e. how quickly food and water become inedible in cold weather and how quickly it can be thawed.

Hirmuolio added some commits Mar 11, 2019

@Hirmuolio

This comment has been minimized.

Copy link
Contributor Author

commented Mar 12, 2019

There are some tests now.

Test 1: Spawn item.
Check its attributes.
Process item once.
Check temperature and energy.

Test 2: Water (250 ml) 55 C in 20 C enviroment.
It should cool down to ~30 C in 75 minutes if we want realistic values. With our values it cools to 29.4 C.
Also checks that the interval has no effect on result (water 2 = water 1).

Test 3 section 1: Meat 50 C in -20 C enviroment.
Checks that the math stays consistent for liquid -> freezing ->solid and tags are applied right.
Also checks that the time interval has no effect on result (meat 2 = meat 1).

Test 2 section 2: Meat -20 C in 20 C enviroment.
Checks that the math stays consistent for solid -> melting -> liquid and tags are applied right.
Also checks that the interval has no effect on result (meat 2 = meat 1).

Hirmuolio added some commits Mar 12, 2019

@Hirmuolio

This comment has been minimized.

Copy link
Contributor Author

commented Mar 12, 2019

Strange that I would get different result from the tests compared to Travis.

Most of them are off by 1/100000 K but two of them are stranger and are off by whole 1 K.
The test now checks that the result is within 0.1% of the expected value.
At "normal" temperatures this is insignificant difference.

Hirmuolio added some commits Mar 12, 2019

@kevingranade

This comment has been minimized.

Copy link
Member

commented Mar 13, 2019

We have a lot of RNG influence scattered around so a little fuzziness is expected. Over time we can remove the randomness and tighten up the tests, but we don't have to do it right now.

The tests are exactly the kind of thing I was looking for.

Hirmuolio added some commits Mar 13, 2019

@Hirmuolio

This comment has been minimized.

Copy link
Contributor Author

commented Mar 13, 2019

Well I think it is now ready.

Some foods will have slightly odd values until the json pull request is merged too. (that one may have some conflicts with this. Nothing major. Needs to be checked after this is merged)

@kevingranade kevingranade merged commit a868b99 into CleverRaven:master Mar 14, 2019

3 checks passed

continuous-integration/appveyor/pr AppVeyor build succeeded
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
gorgon-ghprb Build finished.
Details
@adamkad1

This comment has been minimized.

Copy link

commented Mar 15, 2019

cooling clothes when?

@Hirmuolio Hirmuolio deleted the Hirmuolio:Hirmuolio-temperature branch Mar 21, 2019

@kevingranade

This comment has been minimized.

Copy link
Member

commented Mar 29, 2019

This pull request has been mentioned on Cataclysm: Dark Days Ahead. There might be relevant details there:

https://discourse.cataclysmdda.org/t/water-drawn-from-ponds-may-be-frozen-in-summer/19432/7

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.