Skip to content
Snippets Groups Projects
Commit 025da899 authored by David Hendriks's avatar David Hendriks
Browse files

finished custom logging notebook

parent 5013e2ec
No related branches found
No related tags found
No related merge requests found
%% Cell type:markdown id:879b596b-d70c-4f90-b668-563b4ad93ffc tags:
# Notebook custom logging
In this notebook you'll learn how to use the custom logging functionalty
In this notebook you'll learn how to use the custom logging functionality
%% Cell type:code id:77bd09b0-1a94-499d-97db-a1f991c67c12 tags:
%% Cell type:code id:696ecbb9-1efd-48f4-a57e-2cf6dfe416f1 tags:
``` python
import binary_c_python_api
from binarycpython import _binary_c_bindings
from binarycpython.utils.custom_logging_functions import (
autogen_C_logging_code,
binary_c_log_code,
create_and_load_logging_function,
)
from binarycpython.utils.run_system_wrapper import run_system
from binarycpython.utils.grid import Population
```
#################################################
# File containing examples for the custom logging
# I'll put several logging snippets for different purposes in this file
#
%% Cell type:markdown id:d4d721cc-df4f-4ac2-b6f9-62e85ca0c1e5 tags:
#################################################
# no logging set.
pop = Population()
pop.set(
M_1=10,
M_2=10,
separation=0,
orbital_period=4530,
eccentricity=0,
metallicity=0.02,
max_evolution_time=15000,
The custom logging functionality allows us to decide the output of binary_c _without_ modifying the actual sourcecode of binary_c (i.e. editing `src/logging/log_every_timestep` in binary_c). Rather, we can create a logging routine from within python.
Technically, the following steps are taken:
- User creates a logging print statement from within python
- The logging print statement string gets wrapped into a proper c-function by `binary_c_log_code`
- The c-function string gets compiled and loaded into memory by `create_and_load_logging_function`
- The memory adress of the compiled and loaded print function can now be passed to C
- binary_c uses the custom print function
The custom logging functionality can be used when running systems via `run_system()`, via `Population.evolve()` and `Population.evolve_single()`, and directly via the API
Within the logging statement we can access information from the stardata object, as well as use logical statements to determine when to log information. What we cannot do, however, is access functions that are not _publicly available_. For very elaborate printing routines it is still advised to actually hardcode the print statement into binary_c itself.
%% Cell type:markdown id:be137151-bb57-43d7-bab1-0167512ac727 tags:
## Usage
%% Cell type:markdown id:ac4e5f4c-81e6-4980-b852-aca84ca74f4c tags:
There are two methods to create the C-code that will be compiled:
- Automatically generate the print statement and use the wrapper to generate the full function string, by using `autogen_C_logging_code`
- Create your custom print statement and use the wrapper to generate the full function string, by writing out the print statement. Here the logging statement obviously has to be valid C code
%% Cell type:code id:236cf821-09ac-4237-9b8f-6e36d2edf446 tags:
``` python
# generate logging lines. Here you can choose whatever you want to have logged, and with what header
# this generates working print statements
logging_line = autogen_C_logging_code(
{
"MY_STELLAR_DATA": ["model.time", "star[0].mass"],
}
)
out = pop.evolve_single()
print(out)
print(logging_line)
```
#################################################
# Example logging snippet for logging
pop.set(
C_logging_code="""
if(stardata->star[0].stellar_type>=MS)
%% Output
Printf("MY_STELLAR_DATA %g %g\n",((double)stardata->model.time),((double)stardata->star[0].mass));
%% Cell type:code id:feb423d5-5cc3-433c-9801-f8017abbc03a tags:
``` python
# You can also decide to `write` your own logging_line, which allows you to write a more complex logging statement with conditionals.
logging_line = 'Printf("MY_STELLAR_DATA time=%g mass=%g\\n", stardata->model.time, stardata->star[0].mass)'
print(logging_line)
```
%% Output
Printf("MY_STELLAR_DATA time=%g mass=%g\n", stardata->model.time, stardata->star[0].mass)
%% Cell type:code id:2f5defbf-c623-49ed-a238-fba52a563a58 tags:
``` python
# Generate the entire 'script' by wrapping the logging line
custom_logging_code = binary_c_log_code(logging_line)
print(custom_logging_code)
```
%% Output
#pragma push_macro("Max")
#pragma push_macro("Min")
#undef Max
#undef Min
#include "binary_c.h"
// add visibility __attribute__ ((visibility ("default"))) to it
void binary_c_API_function custom_output_function(struct stardata_t * stardata);
void binary_c_API_function custom_output_function(struct stardata_t * stardata)
{
if (stardata->model.time < stardata->model.max_evolution_time)
{
Printf("EXAMPLE_ABOVE_MS %30.12e %g %g %g %g %d %d\\n",
//
stardata->model.time, // 1
// struct stardata_t * stardata = (struct stardata_t *)x;
Printf("MY_STELLAR_DATA time=%g mass=%g\n", stardata->model.time, stardata->star[0].mass);
}
#undef Max
#undef Min
#pragma pop_macro("Min")
#pragma pop_macro("Max")
stardata->star[0].mass, //2
stardata->previous_stardata->star[0].mass, //3
%% Cell type:markdown id:efa7f1e9-247e-4196-a883-bcff05265d02 tags:
stardata->star[0].radius, //4
stardata->previous_stardata->star[0].radius, //5
Combining the above with e.g. run_system() (see notebook_individual_systems for more examples):
stardata->star[0].stellar_type, //6
stardata->previous_stardata->star[0].stellar_type //7
);
};
/* Kill the simulation to save time */
//stardata->model.max_evolution_time = stardata->model.time - stardata->model.dtm;
};
"""
)
out = pop.evolve_single()
print(out)
%% Cell type:code id:dcd74bbc-478b-43e4-b495-8c456e8d1d88 tags:
``` python
# logging statement
logging_line = 'Printf("MY_STELLAR_DATA time=%g mass=%g\\n", stardata->model.time, stardata->star[0].mass)'
# Entire script
custom_logging_code = binary_c_log_code(logging_line)
# Run system
output = run_system(M_1=2, custom_logging_code=custom_logging_code)
# print (abridged) output
print("\n".join(output.splitlines()[:4]))
```
%% Output
MY_STELLAR_DATA time=0 mass=2
MY_STELLAR_DATA time=0 mass=2
MY_STELLAR_DATA time=1e-06 mass=2
MY_STELLAR_DATA time=2e-06 mass=2
%% Cell type:markdown id:1998ee8f-8c0a-462b-b1e0-54f5963902cc tags:
### Using custom logging with the population object
Custom logging can be used for a whole population by setting the print statement (so not the entire logging script) in `C_logging_code`
#################################################
# Example logging snippet for checking whether the system becomes a NS, and stop the evolution if so.
%% Cell type:code id:77bd09b0-1a94-499d-97db-a1f991c67c12 tags:
``` python
# Set up population
pop = Population()
# Set some BSE parameters
pop.set(
M_1=100,
M_2=10,
separation=0,
orbital_period=400530,
eccentricity=0,
metallicity=0.002,
max_evolution_time=15000,
M_1=5
)
# Example logging that prints only if the star is post main-sequence
example_logging_string_post_MS = """
if(stardata->star[0].stellar_type>MS)
{
Printf("EXAMPLE_ABOVE_MS %30.12e %g %g %g %g %d %d\\n",
//
stardata->model.time, // 1
stardata->star[0].mass, //2
stardata->previous_stardata->star[0].mass, //3
stardata->star[0].radius, //4
stardata->previous_stardata->star[0].radius, //5
stardata->star[0].stellar_type, //6
stardata->previous_stardata->star[0].stellar_type //7
);
};
"""
# Set the logging
pop.set(
C_logging_code="""
if(stardata->star[0].stellar_type>=NS)
{
if (stardata->model.time < stardata->model.max_evolution_time)
{
Printf("EXAMPLE_LOG_CO %30.12e %g %g %g %g %d %d\\n",
//
stardata->model.time, // 1
C_logging_code=example_logging_string_post_MS
)
out = pop.evolve_single()
stardata->star[0].mass, //2
stardata->previous_stardata->star[0].mass, //3
# Print (abridged) output
print('\n'.join(out.splitlines()[:4]))
```
stardata->star[0].radius, //4
stardata->previous_stardata->star[0].radius, //5
%% Output
stardata->star[0].stellar_type, //6
stardata->previous_stardata->star[0].stellar_type //7
);
};
/* Kill the simulation to save time */
stardata->model.max_evolution_time = stardata->model.time - stardata->model.dtm;
};
"""
EXAMPLE_ABOVE_MS 1.041660877905e+02 4.99198 4.99198 6.1357 6.1357 2 1
EXAMPLE_ABOVE_MS 1.041662558619e+02 4.99198 4.99198 6.14057 6.1357 2 2
EXAMPLE_ABOVE_MS 1.041662560111e+02 4.99198 4.99198 6.14057 6.14057 2 2
EXAMPLE_ABOVE_MS 1.041662564579e+02 4.99198 4.99198 6.14059 6.14057 2 2
%% Cell type:markdown id:93397ff3-9b71-470d-8bc4-08fe5b1a5dca tags:
### Using custom logging when running directly from the API
When running a system directly with the API we need to manually load the custom logging into memory (via `create_and_load_logging_function`) and pass the memory address to the binary_c binding via `_binary_c_bindings.run_system(argstring, custom_logging_func_memaddr=custom_logging_memaddr)`
%% Cell type:code id:30142286-34ce-433e-82c8-565e2160ff5b tags:
``` python
# generate logging lines
logging_line = autogen_C_logging_code(
{
"MY_STELLAR_DATA": ["model.time", "star[0].mass"],
}
)
out = pop.evolve_single()
# Generate code around logging lines
custom_logging_code = binary_c_log_code(logging_line)
# TODO: add function that shows a
# Generate library and get memaddr
custom_logging_memaddr, shared_lib_filename = create_and_load_logging_function(
custom_logging_code
)
# TODO: add function for compact object mergers
#
m1 = 15.0 # Msun
m2 = 14.0 # Msun
separation = 0 # 0 = ignored, use period
orbital_period = 4530.0 # days
eccentricity = 0.0
metallicity = 0.02
max_evolution_time = 15000
argstring = "binary_c M_1 {0:g} M_2 {1:g} separation {2:g} orbital_period {3:g} eccentricity {4:g} metallicity {5:g} max_evolution_time {6:g}".format(
m1,
m2,
separation,
orbital_period,
eccentricity,
metallicity,
max_evolution_time,
)
output = _binary_c_bindings.run_system(
argstring, custom_logging_func_memaddr=custom_logging_memaddr
)
# TODO: add function
# print (abridged) output
print('\n'.join(output.splitlines()[:4]))
```
%% Cell type:code id:a6150cc1-895c-4e7b-baae-7db81ee81544 tags:
%% Output
``` python
def run_example_binary_with_custom_logging():
"""
Function that will use a automatically generated piece of logging code. Compile it, load it
into memory and run a binary system. See run_system on how several things are done in the background here.
"""
MY_STELLAR_DATA 0 15
MY_STELLAR_DATA 0 15
MY_STELLAR_DATA 1e-06 15
MY_STELLAR_DATA 2e-06 15
import pandas as pd
import numpy as np
%% Cell type:markdown id:39c76b1d-d968-4eef-b5ae-2542ed9557c3 tags:
# generate logging lines. Here you can choose whatever you want to have logged, and with what header
# this generates working print statements
logging_line = autogen_C_logging_code(
{
"MY_STELLAR_DATA": ["model.time", "star[0].mass"],
}
)
# OR
# You can also decide to `write` your own logging_line, which allows you to write a more complex logging statement with conditionals.
logging_line = 'Printf("MY_STELLAR_DATA time=%g mass=%g\\n", stardata->model.time, stardata->star[0].mass)'
# Generate entire shared lib code around logging lines
custom_logging_code = binary_c_log_code(logging_line)
# Run system. all arguments can be given as optional arguments. the custom_logging_code is one of them and will be processed automatically.
output = run_system(
M_1=1,
metallicity=0.002,
M_2=0.1,
separation=0,
orbital_period=100000000000,
custom_logging_code=custom_logging_code,
)
print(output)
# Catch results that start with a given header. (Mind that binary_c has to be configured to print them if your not using a custom logging function)
# DOESNT WORK YET if you have the line autogenerated.
result_example_header = parse_output(output, "MY_STELLAR_DATA")
## Examples of logging strings
Below are some examples of logging strings
%% Cell type:markdown id:2ac4af72-6dab-4cc9-986e-5b5b1fa31b73 tags:
### Compact object
This logging will print the timestep when the star becomes a compact object. After it does, we change the maximum time to be the current time, effectively terminating the evolution
# Cast the data into a dataframe.
df = pd.DataFrame.from_dict(result_example_header, dtype=np.float64)
%% Cell type:code id:6f0edc65-a788-4706-a0c5-2ace030765ec tags:
# Do whatever you like with the dataframe.
print(df)
``` python
example_logging_string_CO = """
if(stardata->star[0].stellar_type>=NS)
{
if (stardata->model.time < stardata->model.max_evolution_time)
{
Printf("EXAMPLE_LOG_CO %30.12e %g %g %g %g %d %d\\n",
//
stardata->model.time, // 1
stardata->star[0].mass, //2
stardata->previous_stardata->star[0].mass, //3
stardata->star[0].radius, //4
stardata->previous_stardata->star[0].radius, //5
stardata->star[0].stellar_type, //6
stardata->previous_stardata->star[0].stellar_type //7
);
};
/* Kill the simulation to save time */
stardata->model.max_evolution_time = stardata->model.time - stardata->model.dtm;
};
"""
# Entire script
custom_logging_code = binary_c_log_code(example_logging_string_CO)
# run_example_binary_with_custom_logging()
# Run system
output = run_system(M_1=10, custom_logging_code=custom_logging_code)
# print (abridged) output
print("\n".join(output.splitlines()[:4]))
```
%% Cell type:code id:30142286-34ce-433e-82c8-565e2160ff5b tags:
%% Output
``` python
def run_example_custom_logging_autogenerated():
"""
This is an example function for the autogeneration of logging codes that binary_c uses.
"""
SINGLE_STAR_LIFETIME 10 27.7358
EXAMPLE_LOG_CO 2.773581245005e+01 1.33524 9.19314 1.72498e-05 730.446 13 5
%% Cell type:markdown id:51c51592-6406-43bd-a879-10ace64aaf28 tags:
# generate logging lines
logging_line = autogen_C_logging_code(
### Logging mass evolution and the supernova
This logging code prints the mass evolution and the moment the star goes supernova
%% Cell type:code id:8f58fdf9-3e76-4c18-a1c5-eed0980d4133 tags:
``` python
example_logging_string_CO = """
Printf("EXAMPLE_MASSLOSS %30.12e %g %g %g %d %g\\n",
//
stardata->model.time, // 1
stardata->star[0].mass, //2
stardata->previous_stardata->star[0].mass, //3
stardata->common.zero_age.mass[0], //4
stardata->star[0].stellar_type, //5
stardata->model.probability //6
);
if(stardata->star[0].SN_type != SN_NONE)
{
if (stardata->model.time < stardata->model.max_evolution_time)
{
if(stardata->pre_events_stardata != NULL)
{
"MY_STELLAR_DATA": ["model.time", "star[0].mass"],
"my_sss2": ["model.time", "star[1].mass"],
}
)
Printf("EXAMPLE_SN %30.12e " // 1
"%g %g %g %d " // 2-5
"%d %d %g %g " // 6-9
"%g %g %g %g\\n", // 10-13
//
stardata->model.time, // 1
# Generate code around logging lines
custom_logging_code = binary_c_log_code(logging_line)
stardata->star[0].mass, //2
stardata->pre_events_stardata->star[0].mass, //3
stardata->common.zero_age.mass[0], //4
stardata->star[0].SN_type, //5
# Generate library and get memaddr
func_memaddr, shared_lib_filename = create_and_load_logging_function(
custom_logging_code
)
#
m1 = 15.0 # Msun
m2 = 14.0 # Msun
separation = 0 # 0 = ignored, use period
orbital_period = 4530.0 # days
eccentricity = 0.0
metallicity = 0.02
max_evolution_time = 15000
argstring = "binary_c M_1 {0:g} M_2 {1:g} separation {2:g} orbital_period {3:g} eccentricity {4:g} metallicity {5:g} max_evolution_time {6:g}".format(
m1,
m2,
separation,
orbital_period,
eccentricity,
metallicity,
max_evolution_time,
)
output = _binary_c_bindings.run_system(
argstring, custom_logging_func_memaddr=func_memaddr
)
print(output)
stardata->star[0].stellar_type, //6
stardata->pre_events_stardata->star[0].stellar_type, //7
stardata->model.probability, //8
stardata->pre_events_stardata->star[0].core_mass[ID_core(stardata->pre_events_stardata->star[0].stellar_type)], // 9
stardata->pre_events_stardata->star[0].core_mass[CORE_CO], // 10
stardata->pre_events_stardata->star[0].core_mass[CORE_He], // 11
stardata->star[0].fallback, // 12
stardata->star[0].fallback_mass // 13
);
}
else
{
Printf("EXAMPLE_SN %30.12e " // 1
"%g %g %g %d " // 2-5
"%d %d %g %g " // 6-9
"%g %g %g %g\\n", // 10-13
//
stardata->model.time, // 1
# run_example_custom_logging_autogenerated()
stardata->star[0].mass, //2
stardata->previous_stardata->star[0].mass, //3
stardata->common.zero_age.mass[0], //4
stardata->star[0].SN_type, //5
stardata->star[0].stellar_type, //6
stardata->previous_stardata->star[0].stellar_type, //7
stardata->model.probability, //8
stardata->previous_stardata->star[0].core_mass[ID_core(stardata->previous_stardata->star[0].stellar_type)], // 9
stardata->previous_stardata->star[0].core_mass[CORE_CO], // 10
stardata->previous_stardata->star[0].core_mass[CORE_He], // 11
stardata->star[0].fallback, // 12
stardata->star[0].fallback_mass // 13
);
}
};
/* Kill the simulation to save time */
stardata->model.max_evolution_time = stardata->model.time - stardata->model.dtm;
};
"""
# Entire script
custom_logging_code = binary_c_log_code(example_logging_string_CO)
# Run system
output = run_system(M_1=20, custom_logging_code=custom_logging_code)
# print (abridged) output
print("\n".join(output.splitlines()[-2:]))
```
%% Output
EXAMPLE_MASSLOSS 9.878236827680e+00 1.61349 8.38063 20 13 1
EXAMPLE_SN 9.878236827680e+00 1.61349 8.38063 20 12 13 5 1 6.74037 4.92267 6.74037 0 0
......
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment