ShotgunNinja / Kerbalism

Hundreds of Kerbals were killed in the making of this mod.
The Unlicense
43 stars 20 forks source link

Thermal control #83

Open ShotgunNinja opened 7 years ago

ShotgunNinja commented 7 years ago

This issue outline the details of the new thermal control (TC) mechanics to introduce in the near future. Comments and suggestions are welcomed.

The objective is to model approximately heat, and to force the user into taking engineering decisions and compromises similar to those done in reality on the matter of thermal control on spacecrafts.

Technically, it will be implemented on top of current infrastructure to minimize work and potential bugs, and will be exposed to the user by extension of the current Rule Framework capabilities.

While thermal control, in reality, is not an exclusive of manned habitats (every device and instrument has its own operative temperature range to be maintained), for simplicity only the crew and its survival temperature range is taken into account. This avoid a total redesign of the rule framework, that is way beyond the time and attention budget allocated for this new mechanic.

You know those radiators that are barely used only if you go to the inner solar system, or if you deal with the stock ISRU? I'm talking about these things: We are going to make these useful.

How it works

The habitat system is extended so that every habitat part would have capacity to store Heat, a special non-visible mass-less resource, in function of the volume of its internal space. This is similar to what happen right now with the Atmosphere and WasteAtmosphere resources.

The Heat resource would then be generated by:

and consumed by:

The internal habitat temperature will then be determined from the Heat level (that being the Heat amount versus capacity) over the set of enabled habitat parts.

Modifiers changes

The old temperature modifier is removed, and new ones added:

Rules changes

The climatization rule is replaced by two new rules: freezing and burning. Both of them are resource-less rules, that will use the respective _coolingneed and _heatingneed modifiers so that, when internal habitat temperature is above/below the survival range, they will degenerate (up until death) and when the internal habitat temperature is inside the survival range, they will recover (as degeneration will be zero in that case).

Processes changes

Some new processes are added:

Process Consume Produce Modifiers
IncomingFlux Heat _incomingflux, _halfsurface
OutgoingFlux Heat surface
Metabolism Heat _crewcount
Heater EC Heat _heatingneed, _Heater
Radiator Heat _coolingneed, _Radiator

In every other 'non-chemical' process where EC is consumed, Heat will be generated. This is not made automatic (albeit it could) to allow greater flexibility.

All chemical reaction processes, instead, will either produce or consume Heat in relation of them being endothermic or exothermic in nature.

A new 'heater' ProcessController module, and relative Configure setup, will be added to manned pods.

Stock radiator modules will be removed without mercy, and replaced with 'radiator' ProcessControllers instead.

Planner changes

A new panel is added, to convey informations about Heat generation and consumption, according to the body/situation/sunlight environment as specified in the planner ui, and the simulation of rules and processes for the vessel in the editor.

Monitor changes

The telemetry panel in monitor will show the internal atmosphere temperature, as determined by the level of Heat stored.

Maxzhao1999 commented 7 years ago

I would be happy to help checking real life data or doing calculations for enthalpy changes/ thermodynamics if you'd like. Will all ships be modeled as black bodies or will emmisivity and albedos be considered? Don't know if it'll be hard to implement thermaldynamics based on the surface properties of the vessel?

ShotgunNinja commented 7 years ago

Vessels are already assumed to be black bodies, for the purpose of temperature measurement (the 'environment temperature at vessel position' you already see in the telemetry panel of Monitor).

In the new mechanics, albedo of vessels should be taken into account in the IncomingFlux process. It will be hard-coded to some reasonably generic value, because adding an 'albedo' metadata to all stock parts is time-consuming, and adding it to all existing and future third-party parts is impossible.

I through of using the bottom layer of the mipmap pyramid of all parts texture (that can be understood as the 'average color') to extrapolate some kind of per-part albedo automagically. From the average RGB color, a luminance value could be obtained using this function (here in GLSL code):

// calculate luminance of a pixel from rgb values (from ITU-R BT.709)
// - clr: original color in RGB color-space
float luma(const vec3 clr)
{
  return dot(clr, vec3(0.1762044, 0.8129847, 0.0108109));
}

and from there some sort of satisfatory pseudo-albedo for the part could be obtained. Then, it will only be a matter of determining the surface-weighed average among all parts.

However, I believe that going with a generic, hard-coded albedo value for all vessels will be enough, at least for the moment. The automagical albedo could be implemented in a second moment, eventually.

eberkain commented 7 years ago

I know this was the first thing you said, but unlike the other elements of life support that the mod simulates. Heating the electronics on space probes and mars rovers is a big concern for NASA. The rule framework outlines what happens to a Kerbal when the rule is broken, could you modify the rule definitions to have a type = manned / unmanned. If the rule type is manned it applies to Kerbals, and if it us unmanned it applies to Probe Cores. In this context we are really just talking about a point of control for the vessel, so while different parts of the vessel should be subject to different thermal limits, batteries are different than cps for example, I would think that just effecting the probe core would be well enough.

I imagine on a vessel that has no crew that the window would instead display a list of all the probe cores, and instead of displaying a full array of status icons, it would only show the icons that correspond to the unmanned rules, just heat and radiation I would assume. Anyhow I know Its probably not going to happen, but it would be really great to see some of the Kerbalism systems apply to unmanned vessels.

gotmachine commented 7 years ago

I'm all for a good system that encourage managing heat in a coherent fashion, so I highly support the initiative.

First, what will happen to the stock heat management ? It still is needed for atmospheric situations but will be redundant in near-kerbol heating situations. Also, the stock radiators modules will still be needed for mods relying on the stock heat system (like NFE or KSPI).

I believe that going with a generic, hard-coded albedo value for all vessels will be enough, at least for the moment. The automagical albedo could be implemented in a second moment, eventually.

Please stay with a hardcoded value, otherwise it will be the same kind issues that we had with the automagically calculated habitat volume : nice realism-wise, very wrong balance-wise. I don't see the added value.

If I understand things correctly, since the only consequence seems to be kerbal death, the whole system is pointless if there is no kerbal aboard. Management of the heat from producers and converters could be bypassed by simply doing it in an unmanned vessel, which is very weird. Also, what happens when there is no habitat at all in the vessel (seems mandatory for heat capacity & "*_need" modifiers) and endothermic processes have a "input=heat@x.x" ?

I understand that you are trying to implement this with minimal new infrastructure and within the existing rule system, but to do a summary of what it would be nice to have : (1) Evaluating the solar flux (2) Evaluating the "machinery-related" flux (3) Managing the consequence of temperature on habitats (kerbal death) (4) Managing the consequence of temperature on "machinery" (converter/producers shutdown)

In what you propose, (1) & (3) are allright, (2) is going to be troublesome, incomplete and inconsistent between manned/unmanned, (4) is absent. I agree that the stock coreheat system is bad, but this is no replacement !

To expand on my statement on (2), the "EC consumption produce heat" automatic rule seems problematic, even with an opt-out possibility : no balancing possible, no special cases : what about things like RTG or mod-added parts/modules that use the stock "core heat" system or consume large amounts of EC ? This seems to be better done in a HeatGenerator partmodule with the following properties :

This would open the possibility to support (in a basic linear way) all modules that I can think of.

As for (4), maybe consider expanding the already existing Reliability module with the following properties :

ShotgunNinja commented 7 years ago

Thanks guys, the suggestions are interesting and the critique make sense.

Scope of this It will be better to clarify that this is meant to simulate heat inside manned habitats. That is possible with minimal extensions of current architecture. If heat and its consequences are simulated on all vessel, probe cores and in general on every module, it will require a total refactor. I like these suggestions a lot, and I'm not excluding that another total refactor may happen at some point in future. But for now I will be inclined to go the simple route, and then whatever comes out of it may provide useful insight for a future refactor.

Some practical example of why a total refactor would be necessary:

While simulating heat only inside the habitat would only require more or less what's outlined in the OP.

Input heat in processes You are totally right, this is problematic. It is better then to maintain the current EC input (representing energy required, you can image it as an embedded heater) in endothermic processes. So, no process will have Heat as input (except the radiator and the vessel radiative cooling ones). The proposed solution is then to keep endothermic chemical processes as EC consumers.

Output heat in processes, when there is no habitat at all Indeed the heat output would be ignored in this case. While not strictly a problem, I can see how the inchoerency is going to be confusing. The proposed solution is then to only add heat production to processes and modules that are conceptually linked to the manned habitat. This will reduce the scope of heat contribution by electric devices, but I don't really see another way out (without the already mentioned total refactor).

EC consumption equal Heat production I agree, and the plan is to not do it automatically. Instead, heat production will be specified per-process, when appropriate. This avoid issues, and is more flexible to balance.

Replacing 'core heat mechanic' This wasn't my intention. So perhaps the stock radiator module should be maintained alongside the new Radiator process, or somehow the latter should also implement the former. But this is slightly problematic, because then you have these radiator parts doing two different things (cooling 'core heat', and being Heat consumers). Luckily, thanks to how the 'needs_cooling' modifier will work, you can have more radiators than necessary. The same is true for the stock radiator module (I guess). So the user would simply need enough radiators to satisfy both mechanics.

Automagically guessing information Sometimes, you need information that is not available. The information is strictly required, so in a way or another you need to obtain it. Enter heuristic functions, the formalization of educated guessing. These produce information out of thin air, basically, for the greater good of humanity. And while heuristic function generate 'imperfect' data, that is still better than having no data at all. The way we are doing the habitat volume/surface I think is the best we can possibly expect, and should be extended to other metadata as necessary: namely, that the data can be specified per-part, and if it isn't it fall back to the heuristic function.

ShotgunNinja commented 7 years ago

To further clarify: in essence this is meant to be an improvement over the current 'climatization', so that more planning and radiators are required. Then if Heat is added to habitats, it open the possibilities of having various things produce and consume it. That lead naturally to the idea of having chemical processes and electronic devices produce and consume Heat. At the time of writing it made sense, but the issues pointed out are all valid ones. So I think the best course of action is to implement the basic system, and having some token process (eg: the ECLSS ones) and module (eg: the greenhouse) interact with that.

DaveTSG commented 7 years ago

"Stock radiator modules will be removed without mercy, and replaced with 'radiator' ProcessControllers instead."

Will this cause issues for those of us with other mods installed, such as KSP Interstellar Extended, that has nuclear reactors and other parts that need the radiators?

ShotgunNinja commented 7 years ago

@DaveTSG Yes. I'm going to keep the stock radiator module around, or in any case emulate its behaviour to not break these mods.

gotmachine commented 7 years ago

I was thinking about how to solve this, and maybe came up with a not so bad idea : instead of trying to model heat levels resulting from heat flux, only model the heat flux. This result in a system where temperature (and thermal inertia) is ignored, but equilibrium between heat sources and heat sinks must be reach at all times. Technically, this mean reverse the problem by using a massless "coolant" resource to take care of cooling needs, and use EC when heating is required :

Then have two synthetic cooling and heating needs modifiers taking account of all heat flux and habitat parameters, something like that :

Then use them in two rules :

Rule Input Modifier
Burning coolant cooling_need
Freezing EC heating_need

Unless there is something I missed, I can't see why this won't work. It would be a bit more abstract like the current climatization rule is but would be simple to plan for and consistent in all situations. This nullify the issue of the different "operating temperatures" for the crew and the processes (since we only care about flux and not the actual resulting temperature). The various process would be easy to balance for higher / lower cooling requirements by modifying their "coolant" input rate.

A potential problem would be that coolant and radiators would be required at all times, even for small landers or reentry pods. I don't know for sure what is realistic, but I have the intuition that unless there are some active exothermic processes onboard or the vessel is very close to the sun, the freezing rule would apply in most situations (so no need for radiators/cooling), but maybe I'm wrong. And if this is an issue, it could be mitigated by tweaking the degeneration rate so degeneration act as "thermal inertia". Maybe using a modifier based on habitat volume for degeneration (something like "1/volume"), but would also need to implement the feature in issue #81.

Support for various parts / modules would be easier since having a resource input is usually built-in (engines, converters...) so we could MM patch them for an additional "coolant" input.

For the planner / monitor, the output of each modifier should be enough to understand what is going on.

gotmachine commented 7 years ago

[EDIT] more balance tests, and reworked flux formulas. Also : if you want, I can try to code the required modifiers and planner changes in my PR #105. I could try to code the radiators partmodule, but no promise...[/EDIT] Did some prospective work on this, combining my "Coolant" idea and your initial idea. Pseudo-code ahead.

Calculating radiative flux is tricky because a small surface temperature difference can lead to huge coolant / ec requirements. Using this (not very accurate) system guarantee that the radiative flux stays near the sum of incoming flux, and seem to be a not so bad simulation of what would happen IRL :

image

hab_incoming_watts = influx_total; // see spreadsheet formula for influx_total
hab_outgoing_watts = radflux_total ; // see spreadsheet formula for radflux_total

net_flux = influx_total - radflux_total + kerbal_bodies_flux // WATTS
pos_flux = net_flux > 0.0 ? net_flux : 0.0;
neg_flux = net_flux < 0.0 ? Abs(net_flux) : 0.0;

air_heatcap = 1210 // Air volumetric heat capacity (J/m^3/K)
al_heatcap = 897037 // Aluminum mass heat capacity (J/t/K) (* Settings.MassFactor, 0.5 for balance, maybe less)
Settings.SurvivalRange // Survival range (K)

// hab heat capacity in represented as a HabJoule resource
// PhysicsGlobals.StandardSpecificHeatCapacity = 800(kJ/t/K)
// habitat partmodule :
thermal_mass_factor = 0.5
HabJoule amount = Settings.SurvivalRange * part.mass * thermal_mass_factor * PhysicsGlobals.StandardSpecificHeatCapacity * 1000;
HabJoule capacity = amount * 2

process 
name = env_heat_gains
modifier = pos_flux
output = HabJoule@1.0

process 
name = env_heat_losses
modifier = neg_flux
input = HabJoule@1.0

// relative temp difference from ideal temperature
hab_relative_tempdiff = (((HabJoule.capacity * 0.5 ) - HabJoule.amount) / (HabJoule.capacity * 0.5 )) * Settings.SurvivalRange

// return a [0.0;1.0] health degeneration factor with an exponential relation to the hab temperature
// 0.0 if the fractor is low, to allow the accumulator to reset
double factor = Math.Exp(Math.Abs(survival_temp_diff) - Settings.SurvivalRange);
temperature_health =  factor > 0.001 ? factor : 0.0;

heating_need = survival_temp_diff > 0.0 ? 1.0 : 0.0;
cooling_need = survival_temp_diff < 0.0 ? 1.0 : 0.0;

// human with 1.0 mm clothing can survive 36 hours @ -10°C, determine degen/threshold from that ?
// Source : http://www.lboro.ac.uk/microsites/lds/EEC/ICEE/textsearch/1994/Tikuisis-1994.pdf
// Highest temp : https://www.quora.com/What-is-the-highest-temperature-a-human-being-can-survive
// Another source : https://img.purch.com/h/1400/aHR0cDovL3d3dy5saXZlc2NpZW5jZS5jb20vaW1hZ2VzL2kvMDAwLzA0OS85MDcvb3JpZ2luYWwvaHVtYW4tc3Vydml2YWwtbGltaXRzLTEyMDgwOWctMDIuanBnPzEzNDQ1NzE0MzE=
Rule
name = sweating
modifier = heating_need,temperature_health
degeneration = 0.000011574 // 24 hours at 45°C (assume Settings.SurvivalRange = 25 and ideal temp = 20°C)

Rule
name = freezing
modifier = cooling_need,temperature_health
degeneration = 0.000011574 // 24 hours at -5°C (assume Settings.SurvivalRange = 25 and ideal temp = 20°C)

// Clamp climatizer output to joules needed to reach equilibrium & max climatizer capacity
// Settings.ClimatizerCapacity = 2500 //  heating / cooling capacity (in watts) per unit of _Climatizer pseudo-resource
joule_need = Abs((HabJoule.capacity * 0.5) - HabJoule.amount)
clim_capacity = _Climatizer.amount * Settings.ClimatizerCapacity
climatizer_output = joule_need < clim_capacity ? joule_need : clim_capacity;

// ECLSS climatizer processes
process 
name = heater
modifier = heating_need,climatizer_output
input = ElectricCharge@0.001 // 1 ec/s = 1 kW (seems to be more or less inline with stock values)
output = HabJoule@1.0

process 
name = cooler
modifier = cooling_need,climatizer_output
input = Coolant@0.001 // 1 Coolant/s = 1 kW
input = HabJoule@1.0

Here are some simulations using the planner current temperature estimates. Notes :

image image

gotmachine commented 7 years ago

Okay so after some testing I changed my mind again : the "resource" way of tracking habitat temperature is very bulky to implement, so I came with a simpler system that only consist of two rules using the thermal flux (from above post formulas) as a modifier for their inputs, one for negative flux (consume EC), the other for positive flux (consume Coolant).

The rules use a different modifier for the degeneration rates (using the suggestion in issue #81), this modifier account for the thermal inertia of the habitat and the survival temperature range.

I've also implemented a "Radiator" partmodule that output Coolant consuming EC. It works alongside the stock ModuleActiveRadiator and ModuleDeployableRadiator to get its on/off state but I implemented the heat flux calculations independently from the stock system.

The module account for :

This is done coherently in FixedUpdate, BackgroundUpdate and in the planner, I reproduced as much as possible the code from other modules like the greenhouse, emitter, solar panels, etc

EDIT : Since this could be useful anyway, here are the results of my research for fuel cells & waste incinerator processes :

// hydrogen HHV : 141.80 MJ/Kg
  // hydrogen burned : 0,00001798 kg/s
  // -> energy production : 2,549 kW
  // -> conversion to EC at 60% efficiency : 1,5297 kW (EC/s)
  // -> 40% waste heat = 1,0198 kW (Coolant/s)
  Process
  {
    name = fuel cell
    modifier = _FuelCell
    input = Coolant@1.0
    input = Hydrogen@0.2 
    input = Oxygen@0.101319354
    output = Water@0.000160860
    output = ElectricCharge@1.5
    dump = Water
  }

  // Hydrazine HHV : 19.4 MJ/Kg
  // Monoprop burned : 0,000028841 kg/s
  // -> energy production : 0,5595 kW
  // -> conversion to EC at 60% efficiency : 0,336 kW (EC/s)
  // -> 40% waste heat = 0,224 kW (Coolant/s)
  Process
  {
    name = monoprop fuel cell
    modifier = _MonopropFuelCell
    input = Coolant@0.224
    input = Oxygen@0.0204247660
    input = MonoPropellant@0.0000072102 // (Hydrazine@0.0028725741)
    output = Nitrogen@0.0201535252
    output = Water@0.0000324275
    output = ElectricCharge@0.336
  }

  // industrial process efficiency : 180 MJ/kg
  // Hydrogen rate : 0,0000899 kg/s
  // -> energy needed: 16,2 kW (EC/s)
  // -> 10.0 ec/s for balance
  Process
  {
    name = water electrolysis
    modifier = _WaterElectrolysis
    input = ElectricCharge@10.0
    input = Water@0.0008043014
    output = Hydrogen@1.0
    output = Oxygen@0.5065967706
  }

  // "peat" combustion HHV : 6-15 MJ/Kg, assume 10 MJ/Kg
  // Waste burned : 0.0000812 kg/s
  // -> energy production : 0.812 kW
  // -> conversion to EC at 20% efficiency : 0.1624 kW (EC/s)
  // -> 80% waste heat = 0.6496 kW (Coolant/s)
  Process
  {
    name = waste incinerator
    modifier = _WasteIncinerator
    input = Coolant@0.5
    input = Waste@0.0001082667 // H18C82
    input = Oxygen@0.1589194249
    output = CarbonDioxide@0.1497439605
    output = Water@0.0000131259
    output = ElectricCharge@0.15
    dump = Water,ElectricCharge
  }

  Process
  {
    name = sabatier process 
    modifier = _Sabatier
    input = Coolant@0.0035779186 // -165.0 kJ/mol -> 3,577918585 W
    input = ElectricCharge@0.5
    input = CarbonDioxide@0.2514920085
    input = Hydrogen@1.0
    output = Water@0.0004017039
    output = LiquidFuel@0.0001788570195417 // (Methane@0.2494519101)
  }

  Process
  {
    name = haber process 
    modifier = _Haber
    input = Coolant@0.0010862700 // -92,4 kJ/mol -> 1,086269998 W
    input = Nitrogen@0.3328758387
    input = Hydrogen@1.0
    output = Ammonia@0.6584235036
  }

  Process
  {
    name = anthraquinone process
    modifier = _Anthraquinone
    input = Coolant@0.0061401062 // -134.2 kJ/mol -> 6,140106172 W
    input = Hydrogen@1.0
    input = Oxygen@1.0120677706
    output = Oxidizer@0.001516915615 // (HydrogenPeroxide@0.0010461487)
  }

  Process
  {
    name = hydrazine production
    modifier = _HydrazineProduction
    input = Coolant@0.0859285320 // -150.0 kJ/mol (exothermic for sure, arbitrary value) -> 85,92853203 W
    input = Ammonia@3.9863420068
    input = Oxidizer@0.003061324535 // (HydrogenPeroxide@0.0021112583)
    output = Water@0.0032427540
    output = MonoPropellant@0.0036050845115 // (Hydrazine@0.0028725773)
  }
ShotgunNinja commented 7 years ago

@gotmachine Those process rates are going to be very useful, and I also want to take a look at your Radiator module if possible.

gotmachine commented 7 years ago

@ShotgunNinja Since everything I code will need rebasing on your current/future changes and are more a design proposal than a real PR, I'm going to commit everything I made in the #105 PR so we can centralize the discussion in the PR, and you would have the possibility to review the code.

If you want to playtest the changes, you can use the GameData from the patch branch I'm using in the PR