Merge branch 'sackur-tetrode' into power-net

This commit is contained in:
mwerezak
2014-07-12 20:13:42 -04:00
4 changed files with 122 additions and 12 deletions
@@ -21,16 +21,29 @@ obj/machinery/atmospherics/binary/pump
var/on = 0
var/target_pressure = ONE_ATMOSPHERE
var/power_rating = 7500 //A measure of how powerful the pump is, in Watts. 7500 W ~ 10 HP
//The maximum amount of volume in Liters the pump can transfer in 1 second.
//This is limited by how fast the pump can spin without breaking, and means you can't instantly fill up the distro even when it's empty (at 10000, it will take about 15 seconds)
var/max_volume_transfer = 10000
use_power = 1
idle_power_usage = 10 //10 W for internal circuitry and stuff
var/frequency = 0
var/id = null
var/datum/radio_frequency/radio_connection
New()
..()
active_power_usage = power_rating //make sure this is equal to the max power rating so that auto use power works correctly
highcap
name = "High capacity gas pump"
desc = "A high capacity pump"
target_pressure = 15000000
target_pressure = 15000000 //15 GPa? Really?
power_rating = 112500 //150 Horsepower
on
on = 1
@@ -58,19 +71,65 @@ obj/machinery/atmospherics/binary/pump
return 0
var/output_starting_pressure = air2.return_pressure()
if( (target_pressure - output_starting_pressure) < 0.01)
//No need to pump gas if target is already reached!
if (use_power >= 2)
update_use_power(1)
return 1
var/output_volume = air2.volume
if (network2 && network2.air_transient)
output_volume = network2.air_transient.volume
output_volume = min(output_volume, max_volume_transfer)
//Calculate necessary moles to transfer using PV=nRT
if((air1.total_moles() > 0) && (air1.temperature>0))
if((air1.total_moles() > 0) && (air1.temperature > 0 || air2.temperature > 0))
var/air_temperature = (air2.temperature > 0)? air2.temperature : air1.temperature
var/pressure_delta = target_pressure - output_starting_pressure
var/transfer_moles = pressure_delta*air2.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
//Actually transfer the gas
var/transfer_moles = pressure_delta*output_volume/(air_temperature * R_IDEAL_GAS_EQUATION) //The number of moles that would have to be transfered to bring air2 to the target pressure
//estimate the amount of energy required
var/specific_entropy = air2.specific_entropy() - air1.specific_entropy() //air2 is gaining moles, air1 is loosing
var/specific_power = 0
//src.visible_message("DEBUG: [src] >>> terminal pressures: sink = [air2.return_pressure()] kPa, source = [air1.return_pressure()] kPa")
//src.visible_message("DEBUG: [src] >>> specific entropy = [air2.specific_entropy()] - [air1.specific_entropy()] = [specific_entropy] J/K")
//if specific_entropy >= 0 then gas just flows naturally and we are not limited by how powerful the pump is.
if (specific_entropy < 0)
specific_power = -specific_entropy*air_temperature //how much power we need per mole
//src.visible_message("DEBUG: [src] >>> limiting transfer_moles to [power_rating / (air_temperature * -specific_entropy)] mol")
transfer_moles = min(transfer_moles, power_rating / specific_power)
//Actually transfer the gas
var/datum/gas_mixture/removed = air1.remove(transfer_moles)
air2.merge(removed)
//src.visible_message("DEBUG: [src] >>> entropy_change = [specific_entropy*transfer_moles] J/K")
//if specific_entropy >= 0 then gas is flowing naturally and we don't need to use extra power
if (specific_entropy < 0)
//pump draws power and heats gas according to 2nd law of thermodynamics
var/power_draw = round(transfer_moles*specific_power)
air2.add_thermal_energy(power_draw)
if (power_draw >= power_rating - 5) //if we are close enough to max power just active_power_usage
if (use_power < 2)
update_use_power(2)
else
if (use_power >= 2)
update_use_power(1)
//src.visible_message("DEBUG: [src] >>> Forcing area power update: use_power changed to [use_power]")
if (power_draw > idle_power_usage)
use_power(power_draw)
else
if (use_power >= 2)
update_use_power(1)
//src.visible_message("DEBUG: [src] >>> Forcing area power update: use_power changed to [use_power]")
//src.visible_message("DEBUG: [src] >>> drawing [power_draw] W of power.")
if(network1)
network1.update = 1
@@ -132,6 +191,7 @@ obj/machinery/atmospherics/binary/pump
if("power_toggle" in signal.data)
on = !on
update_use_power(on)
if("set_output_pressure" in signal.data)
target_pressure = between(
+50 -6
View File
@@ -4,16 +4,24 @@ What are the archived variables for?
This prevents race conditions that arise based on the order of tile processing.
*/
#define SPECIFIC_HEAT_TOXIN 200
#define SPECIFIC_HEAT_AIR 20
#define SPECIFIC_HEAT_CDO 30
#define SPECIFIC_HEAT_TOXIN 200 // J/(mol*K)
#define SPECIFIC_HEAT_AIR 20 // J/(mol*K)
#define SPECIFIC_HEAT_CDO 30 // J/(mol*K)
#define HEAT_CAPACITY_CALCULATION(oxygen,carbon_dioxide,nitrogen,phoron) \
max(0, carbon_dioxide * SPECIFIC_HEAT_CDO + (oxygen + nitrogen) * SPECIFIC_HEAT_AIR + phoron * SPECIFIC_HEAT_TOXIN)
//we should really have a datum for each gas instead of a bunch of constants
#define MOL_MASS_O2 0.032 // kg/mol
#define MOL_MASS_N2 0.028 // kg/mol
#define MOL_MASS_CDO 0.044 // kg/mol
#define MOL_MASS_PHORON 0.289 // kg/mol
#define MINIMUM_HEAT_CAPACITY 0.0003
#define QUANTIZE(variable) (round(variable,0.0001))
#define TRANSFER_FRACTION 5 //What fraction (1/#) of the air difference to try and transfer
#define SPECIFIC_ENTROPY_VACUUM 1500 //technically vacuum doesn't have a specific entropy. Just use a really big number here to show that it's easy to add gas to vacuum and hard to take gas out.
/hook/startup/proc/createGasOverlays()
plmaster = new /obj/effect/overlay()
plmaster.icon = 'icons/effects/tile_effects.dmi'
@@ -28,11 +36,11 @@ What are the archived variables for?
slmaster.mouse_opacity = 0
return 1
/datum/gas/sleeping_agent/specific_heat = 40 //These are used for the "Trace Gases" stuff, but is buggy.
/datum/gas/sleeping_agent/specific_heat = 40 //These are used for the "Trace Gases" stuff, but is buggy. //J/(mol*K)
/datum/gas/oxygen_agent_b/specific_heat = 300
/datum/gas/oxygen_agent_b/specific_heat = 300 //J/(mol*K)
/datum/gas/volatile_fuel/specific_heat = 30
/datum/gas/volatile_fuel/specific_heat = 30 //J/(mol*K)
/datum/gas
var/moles = 0
@@ -164,6 +172,42 @@ What are the archived variables for?
return heat_capacity()*(new_temperature - temperature)
//This is so overkill for spessmen it's hilarious.
//While this proc will return an accurate measure of the entropy, it's much easier to use the specific_entropy_change() proc.
/datum/gas_mixture/proc/specific_entropy()
//Purpose: Returning the specific entropy of the gas mix, i.e. the entropy gained or lost per mole of gas added or removed.
//Called by: Anyone who wants to know how much energy it takes to move gases around in a steady state process (e.g. gas pumps)
//Inputs: None
//Outputs: Specific Entropy.
//Jut assume everything is an ideal gas, so we can use the Ideal Gas Sackur-Tetrode equation.
//After we convert to moles and Liters and extract all those crazy constants inside the ln() we end up with:
//S = R * moles * ( ln[ constant * volume / moles * (molecular_mass * internal_energy / moles)^(3/2) ] + 5/2 )
//Where constant is IDEAL_GAS_ENTROPY_CONSTANT defined in setup.dm
//We need to do this calculation for each type of gas in the mix and add them all up, to properly capture the entropy of mixing.
//It would be nice if each gas type was a datum, then we could just iterate through a list
//the number of moles inside the square root gets divided out
var/sp_entropy_oxygen = ( log( IDEAL_GAS_ENTROPY_CONSTANT * volume / (oxygen + 0.001) * sqrt( ( MOL_MASS_O2 * SPECIFIC_HEAT_AIR * (temperature + 1) ) ** 3 ) + 1) + 5/2 )
var/sp_entropy_nitrogen = ( log( IDEAL_GAS_ENTROPY_CONSTANT * volume / (nitrogen + 0.001) * sqrt( ( MOL_MASS_N2 * SPECIFIC_HEAT_AIR * (temperature + 1) ) ** 3 ) + 1 ) + 5/2 )
var/sp_entropy_carbon_dioxide = ( log( IDEAL_GAS_ENTROPY_CONSTANT * volume / (carbon_dioxide + 0.001) * sqrt( ( MOL_MASS_CDO * SPECIFIC_HEAT_CDO * (temperature + 1) + 1 ) ** 3 ) ) + 5/2 )
var/sp_entropy_phoron = ( log( IDEAL_GAS_ENTROPY_CONSTANT * volume / (phoron + 0.001) * sqrt( ( MOL_MASS_PHORON * SPECIFIC_HEAT_TOXIN * (temperature + 1) ) ** 3 ) + 1 ) + 5/2 )
if (total_moles > 0)
var/oxygen_ratio = oxygen/total_moles
var/nitrogen_ratio = nitrogen/total_moles
var/carbon_dioxide_ratio = carbon_dioxide/total_moles
var/phoron_ratio = phoron/total_moles
return R_IDEAL_GAS_EQUATION * ( oxygen_ratio*sp_entropy_oxygen + nitrogen_ratio*sp_entropy_nitrogen + carbon_dioxide_ratio*sp_entropy_carbon_dioxide + phoron_ratio*sp_entropy_phoron )
return SPECIFIC_ENTROPY_VACUUM
/datum/gas_mixture/proc/total_moles()
return total_moles
/*var/moles = oxygen + carbon_dioxide + nitrogen + phoron
+5
View File
@@ -157,6 +157,11 @@ Class Procs:
if(prob(50))
del(src)
//sets the use_power var and then forces an area power update
/obj/machinery/proc/update_use_power(var/new_use_power)
use_power = new_use_power
use_power(0) //force area power update
/obj/machinery/proc/auto_use_power()
if(!powered(power_channel))
return 0
+1
View File
@@ -8,6 +8,7 @@
#define ONE_ATMOSPHERE 101.325 //kPa
#define STEFAN_BOLTZMANN_CONSTANT 0.0000000567 //W/(m^2*K^4)
#define IDEAL_GAS_ENTROPY_CONSTANT 1164 //(mol^3 * s^3) / (kg^3 * L). Equal to (4*pi/(avrogadro's number * planck's constant)^2)^(3/2) / (avrogadro's number * 1000 Liters per m^3).
#define CELL_VOLUME 2500 //liters in a cell
#define MOLES_CELLSTANDARD (ONE_ATMOSPHERE*CELL_VOLUME/(T20C*R_IDEAL_GAS_EQUATION)) //moles in a 2.5 m^3 cell at 101.325 Pa and 20 degC