Skip to content
Snippets Groups Projects
Commit a0d11dce authored by lhausamm's avatar lhausamm
Browse files

Cooling is working and able to reproduce grackle paper graphs

parent 6ca9cc65
Branches
No related tags found
Loading
from pyswiftsim import wrapper
import struct import struct
import numpy import numpy
from ctypes import * from ctypes import *
...@@ -52,14 +54,14 @@ class SwiftStruct(struct.Struct): ...@@ -52,14 +54,14 @@ class SwiftStruct(struct.Struct):
Should be implemented for each sub class Should be implemented for each sub class
""" """
raise NotImplementedError("SwiftStruct should not be used") return self.__class__._name
@property @property
def struct_format(self): def struct_format(self):
""" """
String containing the data type of each attribute String containing the data type of each attribute
""" """
raise NotImplementedError("SwiftStruct should not be used") return self.__class__._format
@property @property
def struct_substruct(self): def struct_substruct(self):
...@@ -218,13 +220,18 @@ class SwiftStruct(struct.Struct): ...@@ -218,13 +220,18 @@ class SwiftStruct(struct.Struct):
# # # #
###################################################################### ######################################################################
class ArrayStruct(SwiftStruct): class ArrayStruct(SwiftStruct):
_name = [
"array_data"
]
def __init__(self, struct_format, data, parent, name): def __init__(self, struct_format, data, parent, name):
super().__init__(struct_format, data, parent) super().__init__(struct_format, data, parent)
self._name = name
self._format = struct_format self._format = struct_format
self._name = name
def __getitem__(self, ii): def __getitem__(self, ii):
data = self.unpack(self.data) data = self.unpack(self.data)
data = self._clean(data)
return data[ii] return data[ii]
def __setitem__(self, ii, value): def __setitem__(self, ii, value):
...@@ -232,20 +239,24 @@ class ArrayStruct(SwiftStruct): ...@@ -232,20 +239,24 @@ class ArrayStruct(SwiftStruct):
data[ii] = value data[ii] = value
setattr(self.parent, self._name, data) setattr(self.parent, self._name, data)
def _clean(self, data):
if self._format[-1] == "c":
data = b"".join(data)
# find end of txt character
n = data.index(b"\x00")
data = data[:n].decode("utf-8")
return data
def __str__(self): def __str__(self):
data = self.unpack(self.data) data = self.unpack(self.data)
data = self._clean(data)
return str(data) return str(data)
def getArray(self): def getArray(self):
return self.unpack(self.data) return self.unpack(self.data)
@property
def struct_name(self):
return [
"array_data"
]
@property @property
def struct_format(self): def struct_format(self):
return self._format return self._format
...@@ -257,24 +268,18 @@ class ArrayStruct(SwiftStruct): ...@@ -257,24 +268,18 @@ class ArrayStruct(SwiftStruct):
# # # #
###################################################################### ######################################################################
class UnitSystem(SwiftStruct): class UnitSystem(SwiftStruct):
_format = "ddddd"
_name = [
"UnitMass_in_cgs",
"UnitLength_in_cgs",
"UnitTime_in_cgs",
"UnitCurrent_in_cgs",
"UnitTemperature_in_cgs",
]
def __init__(self, data, parent=None): def __init__(self, data, parent=None):
super().__init__(self.struct_format, data, parent) super().__init__(self.struct_format, data, parent)
@property
def struct_format(self):
return "ddddd"
@property
def struct_name(self):
return [
"UnitMass_in_cgs",
"UnitLength_in_cgs",
"UnitTime_in_cgs",
"UnitCurrent_in_cgs",
"UnitTemperature_in_cgs",
]
###################################################################### ######################################################################
# # # #
...@@ -282,18 +287,8 @@ class UnitSystem(SwiftStruct): ...@@ -282,18 +287,8 @@ class UnitSystem(SwiftStruct):
# # # #
###################################################################### ######################################################################
class Part(SwiftStruct): class Part(SwiftStruct):
def __init__(self, data, parent=None): _format = "qP3d3f3ffffffN7f4c"
super().__init__(self.struct_format, data, parent) _name = [
@property
def struct_format(self):
print("ERROR, need to fix density/time_bin")
return "qP3d3f3ffffffN7f4c"
@property
def struct_name(self):
return [
"id", "id",
"gpart", "gpart",
"pos", "pos",
...@@ -309,6 +304,11 @@ class Part(SwiftStruct): ...@@ -309,6 +304,11 @@ class Part(SwiftStruct):
"time_bin" "time_bin"
] ]
def __init__(self, data, parent=None):
super().__init__(self.struct_format, data, parent)
print("ERROR, need to fix density/time_bin")
###################################################################### ######################################################################
# # # #
# Parameter # # Parameter #
...@@ -327,14 +327,6 @@ class Parameter(SwiftStruct): ...@@ -327,14 +327,6 @@ class Parameter(SwiftStruct):
def __init__(self, data, parent=None): def __init__(self, data, parent=None):
super().__init__(self.struct_format, data, parent) super().__init__(self.struct_format, data, parent)
@property
def struct_format(self):
return Parameter._format
@property
def struct_name(self):
return Parameter._name
###################################################################### ######################################################################
# # # #
...@@ -352,15 +344,6 @@ class Section(SwiftStruct): ...@@ -352,15 +344,6 @@ class Section(SwiftStruct):
def __init__(self, data, parent=None): def __init__(self, data, parent=None):
super().__init__(self.struct_format, data, parent) super().__init__(self.struct_format, data, parent)
@property
def struct_format(self):
return Section._format
@property
def struct_name(self):
return Section._name
###################################################################### ######################################################################
# # # #
# SwiftParams # # SwiftParams #
...@@ -384,15 +367,6 @@ class SwiftParams(SwiftStruct): ...@@ -384,15 +367,6 @@ class SwiftParams(SwiftStruct):
def __init__(self, data, parent=None): def __init__(self, data, parent=None):
super().__init__(self.struct_format, data, parent) super().__init__(self.struct_format, data, parent)
@property
def struct_format(self):
return SwiftParams._format
@property
def struct_name(self):
return SwiftParams._name
@property @property
def struct_substruct(self): def struct_substruct(self):
sec = { sec = {
...@@ -439,11 +413,29 @@ class PhysConst(SwiftStruct): ...@@ -439,11 +413,29 @@ class PhysConst(SwiftStruct):
def __init__(self, data, parent=None): def __init__(self, data, parent=None):
super().__init__(self.struct_format, data, parent) super().__init__(self.struct_format, data, parent)
@property
def struct_format(self):
return PhysConst._format
class CoolingFunctionData(SwiftStruct):
cooling_type = wrapper.configGetCooling()
if cooling_type == "const_lambda":
_format = "dffff"
_name = [
"lambda",
"hydrogen_mass_abundance",
"mean_molecular_weight",
"min_energy",
"cooling_tstep_mult"
]
elif cooling_type == "grackle":
_format = "200cidd"
_name = [
"GrackleCloudyTable",
"UVbackground",
"GrackleRedshift",
"GrackleHSShieldingDensityThreshold"
]
else:
raise ValueError(
"Cooling Type %s not implemented" % cooling_type)
@property def __init__(self, data, parent=None):
def struct_name(self): super().__init__(self.struct_format, data, parent)
return PhysConst._name
...@@ -13,13 +13,21 @@ import numpy ...@@ -13,13 +13,21 @@ import numpy
os.environ["CC"] = "mpicc" os.environ["CC"] = "mpicc"
# deal with arguments # deal with arguments
swift_path = None def parseCmdLine(arg, store=False):
swift_arg = "--with-swift" ret = False
if swift_arg in sys.argv: if arg in sys.argv:
i = sys.argv.index(swift_arg) if store:
swift_path = sys.argv[i+1] i = sys.argv.index(arg)
sys.argv.remove(swift_arg) ret = sys.argv[i+1]
sys.argv.remove(swift_path) sys.argv.remove(ret)
else:
ret = True
sys.argv.remove(arg)
return ret
swift_path = parseCmdLine("--with-swift", store=True)
# python lib dependency # python lib dependency
install_requires=["numpy"] install_requires=["numpy"]
...@@ -37,7 +45,7 @@ def getValueFromMakefile(swift_root, value): ...@@ -37,7 +45,7 @@ def getValueFromMakefile(swift_root, value):
raise ValueError("Value %s not found in Makefile" % value) raise ValueError("Value %s not found in Makefile" % value)
if swift_path is not None: if swift_path:
hdf5_root = getValueFromMakefile(swift_path, "H5CC = ") hdf5_root = getValueFromMakefile(swift_path, "H5CC = ")
# link to non pypi dependencies # link to non pypi dependencies
...@@ -46,7 +54,7 @@ dependency_links = [] ...@@ -46,7 +54,7 @@ dependency_links = []
# C includes # C includes
include = [numpy.get_include()] include = [numpy.get_include()]
if swift_path is not None: if swift_path:
# swift # swift
include.extend([ include.extend([
swift_path + "/src", swift_path + "/src",
...@@ -56,19 +64,22 @@ if swift_path is not None: ...@@ -56,19 +64,22 @@ if swift_path is not None:
# hdf5 # hdf5
include.append(hdf5_root + "/include") include.append(hdf5_root + "/include")
# grackle
grackle_inc = getValueFromMakefile(swift_path, "GRACKLE_INCS = -I")
include.append(grackle_inc)
# C libraries # C libraries
lib = ["m", lib = ["m",
"swiftsim", "swiftsim",
"hdf5" "hdf5",
] ]
lib_dir = [] lib_dir = []
if swift_path is not None: if swift_path:
lib_dir.append(swift_path + "/src/.libs") lib_dir.append(swift_path + "/src/.libs")
lib_dir.append(hdf5_root + "/lib") lib_dir.append(hdf5_root + "/lib")
# src files # src files
c_src = [] c_src = []
......
...@@ -3,24 +3,29 @@ ...@@ -3,24 +3,29 @@
#include <cooling.h> #include <cooling.h>
#include <cooling_struct.h> #include <cooling_struct.h>
#include <equation_of_state.h>
#include <numpy/arrayobject.h>
PyObject* pycooling_init(PyObject* self, PyObject* args) { PyObject* pycooling_init(PyObject* self, PyObject* args) {
PyObject* pyparams; PyObject *pyparams;
PyObject* pyus; PyObject *pyus;
PyObject* pypconst; PyObject *pypconst;
if (!PyArg_ParseTuple(args, "OOO", &pyparams, &pyus, &pypconst)) if (!PyArg_ParseTuple(args, "OOO", &pyparams, &pyus, &pypconst))
return NULL; return NULL;
struct swift_params *params = pytools_construct(pyparams, class_swift_params); struct swift_params *params = (struct swift_params*) pytools_construct(pyparams, class_swift_params);
if (params == NULL) if (params == NULL)
return NULL; return NULL;
struct unit_system *us = pytools_construct(pyus, class_unit_system); struct unit_system *us = (struct unit_system*) pytools_construct(pyus, class_unit_system);
if (us == NULL) if (us == NULL)
return NULL; return NULL;
struct phys_const *pconst = pytools_construct(pypconst, class_phys_const); struct phys_const *pconst = (struct phys_const*) pytools_construct(pypconst, class_phys_const);
if (pconst == NULL) if (pconst == NULL)
return NULL; return NULL;
...@@ -34,6 +39,80 @@ PyObject* pycooling_init(PyObject* self, PyObject* args) { ...@@ -34,6 +39,80 @@ PyObject* pycooling_init(PyObject* self, PyObject* args) {
return pycooling; return pycooling;
} }
PyObject* pycooling_rate(PyObject* self, PyObject* args) { PyArrayObject* pycooling_rate(PyObject* self, PyObject* args) {
pyerror("Not implemented"); IMPORT_ARRAY();
PyObject *pycooling;
PyObject *pyus;
PyObject *pypconst;
PyArrayObject *rho;
PyArrayObject *energy;
float dt = 1e-3;
if (!PyArg_ParseTuple(args,
"OOOOO|f",
&pypconst,
&pyus,
&pycooling,
&rho,
&energy,
&dt))
return NULL;
if (pytools_check_array(energy, 1, NPY_FLOAT) != SUCCESS)
{
return NULL;
}
if (pytools_check_array(rho, 1, NPY_FLOAT) != SUCCESS)
{
return NULL;
}
if (PyArray_DIM(energy, 0) != PyArray_DIM(rho, 0))
{
pyerror("Density and energy should have the same dimension");
}
size_t N = PyArray_DIM(energy, 0);
struct cooling_function_data *cooling = (struct cooling_function_data*) pytools_construct(pycooling, class_cooling_function_data);
if (cooling == NULL)
return NULL;
struct unit_system *us = (struct unit_system*) pytools_construct(pyus, class_unit_system);
if (us == NULL)
return NULL;
struct phys_const *pconst = (struct phys_const*) pytools_construct(pypconst, class_phys_const);
if (pconst == NULL)
return NULL;
struct part p;
#ifdef COOLING_GRACKLE
grackle_data.grackle_data_file = cooling->GrackleCloudyTable;
#endif
PyArrayObject *rate = PyArray_NewLikeArray(energy, NPY_ANYORDER, NULL, 1);
for(size_t i = 0; i < N; i++)
{
p.rho = *(float*) PyArray_GETPTR1(rho, i);
float u = *(float*) PyArray_GETPTR1(energy, i);
p.entropy = gas_entropy_from_internal_energy(p.rho, u);
float *tmp = PyArray_GETPTR1(rate, i);
#ifdef COOLING_GRACKLE
*tmp = cooling_rate(pconst, us, cooling, &p, dt);
#else
*tmp = cooling_rate(pconst, us, cooling, &p);
#endif
}
return rate;
} }
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
PyObject* pycooling_init(PyObject* self, PyObject* args); PyObject* pycooling_init(PyObject* self, PyObject* args);
PyObject* pycooling_rate(PyObject* self, PyObject* args); PyArrayObject* pycooling_rate(PyObject* self, PyObject* args);
#endif // __PYSWIFTSIM_COOLING_H__ #endif // __PYSWIFTSIM_COOLING_H__
...@@ -26,7 +26,6 @@ PyObject* pypart_test_struct(PyObject *self, PyObject *args) ...@@ -26,7 +26,6 @@ PyObject* pypart_test_struct(PyObject *self, PyObject *args)
p->rho = 12.; p->rho = 12.;
p->entropy = 13; p->entropy = 13;
p->entropy_dt = 14; p->entropy_dt = 14;
p->last_offset = 15;
hydro_init_part(p, NULL); hydro_init_part(p, NULL);
...@@ -36,3 +35,4 @@ PyObject* pypart_test_struct(PyObject *self, PyObject *args) ...@@ -36,3 +35,4 @@ PyObject* pypart_test_struct(PyObject *self, PyObject *args)
return object; return object;
} }
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include <cooling_struct.h> #include <cooling_struct.h>
#include <Python.h> #include <Python.h>
#include <numpy/arrayobject.h>
const size_t class_size[class_count] = { const size_t class_size[class_count] = {
sizeof(struct unit_system), sizeof(struct unit_system),
...@@ -164,3 +166,27 @@ char* pytools_construct(PyObject* obj, int class) ...@@ -164,3 +166,27 @@ char* pytools_construct(PyObject* obj, int class)
Py_DECREF(data); Py_DECREF(data);
return ret; return ret;
} }
int pytools_check_array(PyArrayObject *obj, int dim, int type)
{
IMPORT_ARRAY();
if (!PyArray_Check(obj))
{
pyerror("Expecting a numpy array");
}
if (PyArray_NDIM(obj) != dim)
{
pyerror("Array should be a %i dimensional object", dim);
}
if (PyArray_TYPE(obj) != type)
{
pyerror("Wrong array type");
}
return SUCCESS;
}
...@@ -4,10 +4,20 @@ ...@@ -4,10 +4,20 @@
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include <Python.h> #include <Python.h>
#include <numpy/arrayobject.h>
#define DIM 3 #define DIM 3
#define STRING_SIZE 200 #define STRING_SIZE 200
/* Check if arrays are imported and if not import them */
#define IMPORT_ARRAY() \
({ \
if (PyArray_API == NULL) \
{ \
import_array(); \
} \
})
/* Set the error message for python (still need to return NULL) */ /* Set the error message for python (still need to return NULL) */
#define pyerror(s, ...) \ #define pyerror(s, ...) \
({ \ ({ \
...@@ -19,6 +29,12 @@ ...@@ -19,6 +29,12 @@
return FAIL; \ return FAIL; \
}) })
#define pydebug(s, ...) \
({ \
PyErr_Print(); \
fprintf(stderr, "\n%s:%s():%i: Test " s "\n", __FILE__, \
__FUNCTION__, __LINE__, ##__VA_ARGS__); \
})
enum class { enum class {
class_unit_system, class_unit_system,
...@@ -45,4 +61,5 @@ PyObject* pytools_import(char* module, char* object_name); ...@@ -45,4 +61,5 @@ PyObject* pytools_import(char* module, char* object_name);
char* pytools_get_type_name(PyObject *obj); char* pytools_get_type_name(PyObject *obj);
int pytools_check_array(PyArrayObject *obj, int dim, int type);
#endif // __PYSWIFTSIM_TOOLS_H__ #endif // __PYSWIFTSIM_TOOLS_H__
...@@ -52,7 +52,7 @@ PyObject* pyunit_system_init(PyObject *self, PyObject *args) ...@@ -52,7 +52,7 @@ PyObject* pyunit_system_init(PyObject *self, PyObject *args)
PyObject *pypconst = pytools_return(&pconst, class_phys_const); PyObject *pypconst = pytools_return(&pconst, class_phys_const);
if (pypconst == NULL) if (pypconst == NULL)
return NULL; return NULL;
return PyTuple_Pack(2, pyus, pypconst); return PyTuple_Pack(2, pyus, pypconst);
} }
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include "parser_wrapper.h" #include "parser_wrapper.h"
#include "cooling_wrapper.h" #include "cooling_wrapper.h"
#include "pyswiftsim_tools.h" #include "pyswiftsim_tools.h"
#include "config_wrapper.h"
#include <Python.h> #include <Python.h>
...@@ -29,6 +30,12 @@ static PyMethodDef wrapper_methods[] = { ...@@ -29,6 +30,12 @@ static PyMethodDef wrapper_methods[] = {
{"coolingInit", pycooling_init, METH_VARARGS, {"coolingInit", pycooling_init, METH_VARARGS,
"Initialize cooling."}, "Initialize cooling."},
{"coolingRate", pycooling_rate, METH_VARARGS,
"Compute the cooling rate."},
{"configGetCooling", config_get_cooling, METH_VARARGS,
"Get the cooling type."},
{NULL, NULL, 0, NULL} /* Sentinel */ {NULL, NULL, 0, NULL} /* Sentinel */
}; };
...@@ -47,8 +54,8 @@ PyMODINIT_FUNC PyInit_wrapper(void) ...@@ -47,8 +54,8 @@ PyMODINIT_FUNC PyInit_wrapper(void)
{ {
PyObject *m; PyObject *m;
Py_Initialize();
import_array(); import_array();
Py_Initialize();
m = PyModule_Create(&wrapper_cmodule); m = PyModule_Create(&wrapper_cmodule);
if (m == NULL) if (m == NULL)
......
# Define the system of units to use internally.
InternalUnitSystem:
UnitMass_in_cgs: 1.989e43 # Grams
UnitLength_in_cgs: 3.085e21 # Centimeters
UnitVelocity_in_cgs: 20725573.785998672 # Centimeters per second
UnitCurrent_in_cgs: 1 # Amperes
UnitTemp_in_cgs: 1 # Kelvin
# Parameters governing the time integration
TimeIntegration:
time_begin: 0. # The starting time of the simulation (in internal units).
time_end: 5e-2 # The end time of the simulation (in internal units).
dt_min: 1e-7 # The minimal time-step size of the simulation (in internal units).
dt_max: 1e-4 # The maximal time-step size of the simulation (in internal units).
# Parameters governing the snapshots
Snapshots:
basename: sedov # Common part of the name of output files
time_first: 0. # Time of the first output (in internal units)
delta_time: 1e-2 # Time difference between consecutive outputs (in internal units)
# Parameters governing the conserved quantities statistics
Statistics:
delta_time: 1e-3 # Time between statistics output
tasks_per_cell: 1000
# Parameters for the hydrodynamics scheme
SPH:
resolution_eta: 1.2348 # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel).
CFL_condition: 0.1 # Courant-Friedrich-Levy condition for time integration.
# Parameters related to the initial conditions
InitialConditions:
file_name: ./sedov.hdf5 # The file to read
h_scaling: 3.33
# Cooling with Grackle 2.0
GrackleCooling:
GrackleCloudyTable: CloudyData_UVB=HM2012.h5 # Name of the Cloudy Table
UVbackground: 1 # Enable or not the UV background
GrackleRedshift: 0 # Redshift to use (-1 means time based redshift)
GrackleHSShieldingDensityThreshold: 1.1708e-26 # self shielding threshold in internal system of units
Gravity:
eta: 0.025 # Constant dimensionless multiplier for time integration.
theta: 0.7 # Opening angle (Multipole acceptance criterion)
epsilon: 0.1 # Softening length (in internal units).
a_smooth: 1.25 # (Optional) Smoothing scale in top-level cell sizes to smooth the long-range forces over (this is the default value).
r_cut_max: 4.5 # (Optional) Cut-off in number of top-level cells beyond which no FMM forces are computed (this is the default value).
r_cut_min: 0.1 # (Optional) Cut-off in number of top-level cells below which no truncation of FMM forces are performed (this is the default value).
...@@ -3,16 +3,134 @@ ...@@ -3,16 +3,134 @@
from pyswiftsim import wrapper from pyswiftsim import wrapper
from pyswiftsim import structure from pyswiftsim import structure
filename = "/home/loikki/swift_test/cooling_sedov/sedov.yml" from copy import deepcopy
import numpy as np
import matplotlib.pyplot as plt
from astropy import units
params = wrapper.parserReadFile(filename) #
# parameters
#
us, pconst = wrapper.unitSystemInit(params) # adiabatic index
gamma = 5. / 3.
# swift params filename
filename = "test/cooling.yml"
# number of points
N_rho = 3000
N_T = 3000
# density in atom / cm3
if N_rho == 1:
rho = np.array([1.])
else:
#rho = np.array([1.])
rho = np.logspace(-6, 4, N_rho)
# temperature in K
T = np.logspace(1, 9, N_T)
#print(us) # time step
#print(pconst) dt = units.Myr * 1e-5
dt = dt.to("s") / units.s
print(type(params), type(us), type(pconst))
# generate grid
rho, T = np.meshgrid(rho, T)
shape = rho.shape
rho = deepcopy(rho.reshape(-1))
T = T.reshape(-1)
#
# swift init
#
# parse swift params
params = wrapper.parserReadFile(filename)
# init units
us, pconst = wrapper.unitSystemInit(params)
# init cooling
cooling = wrapper.coolingInit(params, us, pconst) cooling = wrapper.coolingInit(params, us, pconst)
print(cooling)
#
# Deal with units
#
# change units of rho and T
# rho
rho *= us.UnitLength_in_cgs**3 * pconst.const_proton_mass
# specific energy
energy = pconst.const_boltzmann_k * T / us.UnitTemperature_in_cgs
energy /= (gamma - 1.) * pconst.const_proton_mass
# time step
dt /= us.UnitTime_in_cgs
#
# compute rate
#
# du / dt
rate = wrapper.coolingRate(pconst, us, cooling,
rho.astype(np.float32),
energy.astype(np.float32),
dt)
#
# plot
#
# change units => cgs
energy *= us.UnitLength_in_cgs**2 / us.UnitTime_in_cgs**2
rate *= us.UnitLength_in_cgs**2 / us.UnitTime_in_cgs**3
if N_rho == 1 or N_T == 1:
plt.figure()
n = rho / (pconst.const_proton_mass * us.UnitLength_in_cgs**3)
proton_mass_in_cgs = pconst.const_proton_mass * us.UnitMass_in_cgs
lambda_ = rate * proton_mass_in_cgs / (n)
if N_rho == 1:
plt.loglog(T, np.abs(lambda_))
plt.xlabel("Temperature [K]")
else:
plt.loglog(rho, np.abs(lambda_))
plt.xlabel("Density [atom / cm3]")
plt.ylabel("Rate")
else:
cooling_time = energy / rate
cooling_length = np.sqrt(gamma * (gamma-1.) * energy) * cooling_time
cooling_length = np.log10(np.abs(cooling_length) / units.kpc.to('cm'))
# reshape
rho = rho.reshape(shape)
T = T.reshape(shape)
energy = energy.reshape(shape)
cooling_length = cooling_length.reshape(shape)
_min = -7
_max = 7
N_levels = 100
levels = np.linspace(_min, _max, N_levels)
plt.figure()
plt.contourf(rho, T, cooling_length, levels)
plt.xlabel("Density [atom/cm3]")
plt.ylabel("Temperature [K]")
ax = plt.gca()
ax.set_xscale("log")
ax.set_yscale("log")
cbar = plt.colorbar()
tc = np.arange(_min, _max, 1.5)
cbar.set_ticks(tc)
cbar.set_ticklabels(tc)
plt.show()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment