Skip to content

Commit a0f5ef2

Browse files
authored
Add finer controls for timestepping (#956)
1 parent 763fa3a commit a0f5ef2

4 files changed

Lines changed: 342 additions & 2 deletions

File tree

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import matplotlib.pyplot as plt
2+
import numpy as np
3+
4+
from amuse.units import units
5+
from amuse.community.mesa.interface import MESA
6+
from amuse import datamodel
7+
8+
stellar_evolution = MESA(version='15140')
9+
10+
masses=[2.0] | units.MSun
11+
stars = datamodel.Particles(len(masses), mass=masses)
12+
13+
stars = stellar_evolution.native_stars.add_particles(stars)
14+
star = stars[0]
15+
16+
star.evolve_one_step()
17+
18+
print(star.time_step)
19+
20+
star.time_step = 1. | units.yr
21+
22+
star.evolve_one_step()
23+
24+
star.save_photo('photo')
25+
star.save_model('model.mod')
26+
27+
28+
star.evolve_one_step()
29+
30+
age = star.age
31+
32+
model_number = star.get_history('model_number')
33+
34+
35+
masses=[1.0] | units.MSun
36+
stars = datamodel.Particles(len(masses), mass=masses,filename=['photo'])
37+
38+
stars = stellar_evolution.photo_stars.add_particles(stars)
39+
star = stars[0]
40+
41+
star.evolve_one_step() # Photos will give exactly the same answer compared to a run without a save/load
42+
43+
print(star.age, star.get_history('model_number'), star.mass)
44+
45+
46+
masses=[1.0] | units.MSun
47+
stars = datamodel.Particles(len(masses), mass=masses,filename=['model.mod'])
48+
49+
stars = stellar_evolution.pre_built_stars.add_particles(stars)
50+
star = stars[0]
51+
52+
star.evolve_one_step() # Models do not give exactly the same answer as a photo
53+
54+
print(star.age, star.get_history('model_number'), star.mass)

src/amuse/community/mesa_r15140/interface.f90

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,6 +1306,78 @@ end function get_gyre
13061306

13071307

13081308

1309+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1310+
! Procedures for manually controlling how a step gets taken
1311+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1312+
1313+
1314+
integer function solve_one_step(AMUSE_ID, first_try, result)
1315+
integer, intent(in) :: AMUSE_ID
1316+
logical, intent(in) :: first_try
1317+
integer, intent(out) :: result
1318+
integer :: ierr
1319+
1320+
ierr = 0
1321+
1322+
call do_solve_one_step(AMUSE_ID, first_try, result, ierr)
1323+
solve_one_step = ierr
1324+
1325+
end function solve_one_step
1326+
1327+
integer function solve_one_step_pre(AMUSE_ID, result)
1328+
integer, intent(in) :: AMUSE_ID
1329+
integer, intent(out) :: result
1330+
integer :: ierr
1331+
1332+
call do_solve_one_step_pre(AMUSE_ID, result, ierr)
1333+
solve_one_step_pre = ierr
1334+
1335+
end function solve_one_step_pre
1336+
1337+
1338+
integer function solve_one_step_post(AMUSE_ID, result)
1339+
integer, intent(in) :: AMUSE_ID
1340+
integer, intent(out) :: result
1341+
integer :: ierr
1342+
1343+
call do_solve_one_step_post(AMUSE_ID, result, ierr)
1344+
solve_one_step_post = ierr
1345+
1346+
end function solve_one_step_post
1347+
1348+
1349+
integer function prepare_retry_step(AMUSE_ID, dt, result)
1350+
! Prepare toretake a timestep with a different dt
1351+
! Does not actualy retry the step
1352+
integer, intent(in) :: AMUSE_ID
1353+
double precision,intent(in) :: dt
1354+
integer, intent(out) :: result
1355+
integer :: ierr
1356+
1357+
1358+
call set_current_dt(AMUSE_ID, dt, ierr) ! Sets dt not dt_next
1359+
if(ierr/=MESA_SUCESS) then
1360+
prepare_retry_step = ierr
1361+
return
1362+
end if
1363+
1364+
result = do_prepare_for_retry(AMUSE_id)
1365+
prepare_retry_step = 0
1366+
1367+
end function prepare_retry_step
1368+
1369+
1370+
integer function prepare_redo_step(AMUSE_ID, result)
1371+
! Retake the same timestep with the same dt. Useful when mdot changes
1372+
! Does not actualy redo the step
1373+
integer, intent(in) :: AMUSE_ID
1374+
integer, intent(out) :: result
1375+
integer :: ierr
1376+
1377+
result = do_prepare_for_redo(AMUSE_id)
1378+
prepare_redo_step = 0
1379+
1380+
end function prepare_redo_step
13091381

13101382

13111383
end module AMUSE_mesa

src/amuse/community/mesa_r15140/interface.py

Lines changed: 113 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -914,7 +914,7 @@ def get_gyre(self, index_of_the_star, mode_l=0,
914914
"""
915915
Get gyre data.
916916
917-
This returns a list of dicts where each element of the list coresponds to one mode
917+
This returns a list of dicts where each element of the list corresponds to one mode
918918
919919
Each dict contains the pg,p,g and complex frequency for the mode as well as
920920
arrays of r/R, xi_r, xi_h, and dwdx for the mode
@@ -963,7 +963,6 @@ def get_mixing_length_ratio(self,index_of_the_star):
963963
"""
964964
Retrieve the current mixing_length_ratio of the star.
965965
"""
966-
967966
return self.get_control(index_of_the_star,'mixing_length_alpha')
968967

969968
def set_mixing_length_ratio(self,index_of_the_star, mixing_length_ratio):
@@ -1126,6 +1125,81 @@ def set_accrete_composition_metals(self, index_of_the_star, **kwargs):
11261125
return r
11271126

11281127

1128+
@legacy_function
1129+
def solve_one_step():
1130+
"""
1131+
Takes one step forward, but does not handle retries or redo's.
1132+
Must call solve_one_step_pre first and solve_one_step_post afterwards
1133+
"""
1134+
function = LegacyFunctionSpecification()
1135+
function.addParameter('index_of_the_star', dtype='int32', direction=function.IN
1136+
, description="The index of the star to get the value of")
1137+
function.addParameter('first_try', dtype='bool', direction=function.IN
1138+
, description="If this is the first attempt at taking this timestep")
1139+
function.addParameter('result', dtype='int32', direction=function.OUT
1140+
, description="What the star should do next (keep going, redo, retry, terminate)")
1141+
function.result_type = 'int32'
1142+
return function
1143+
1144+
1145+
@legacy_function
1146+
def solve_one_step_pre():
1147+
"""
1148+
Prepares to takes one step forward, but does not handle retries or redo's.
1149+
Called before solve_one_step
1150+
"""
1151+
function = LegacyFunctionSpecification()
1152+
function.addParameter('index_of_the_star', dtype='int32', direction=function.IN
1153+
, description="The index of the star to get the value of")
1154+
function.addParameter('result', dtype='int32', direction=function.OUT
1155+
, description="What the star should do next (keep going, redo, retry, terminate)")
1156+
function.result_type = 'int32'
1157+
return function
1158+
1159+
@legacy_function
1160+
def solve_one_step_post():
1161+
"""
1162+
After taking one step forward cleanup the model, but does not handle retries or redo's.
1163+
Called after solve_one_step
1164+
"""
1165+
function = LegacyFunctionSpecification()
1166+
function.addParameter('index_of_the_star', dtype='int32', direction=function.IN
1167+
, description="The index of the star to get the value of")
1168+
function.addParameter('result', dtype='int32', direction=function.OUT
1169+
, description="What the star should do next (keep going, redo, retry, terminate)")
1170+
function.result_type = 'int32'
1171+
return function
1172+
1173+
@legacy_function
1174+
def prepare_retry_step():
1175+
"""
1176+
Prepares to retry a step with a new dt.
1177+
Does not actually take the step
1178+
"""
1179+
function = LegacyFunctionSpecification()
1180+
function.addParameter('index_of_the_star', dtype='int32', direction=function.IN
1181+
, description="The index of the star to get the value of")
1182+
function.addParameter('dt_next', dtype='float64', direction=function.IN
1183+
, description="New timestep to try")
1184+
function.addParameter('result', dtype='int32', direction=function.OUT
1185+
, description="What the star should do next (keep going, redo, retry, terminate)")
1186+
function.result_type = 'int32'
1187+
return function
1188+
1189+
@legacy_function
1190+
def prepare_redo_step():
1191+
"""
1192+
Prepares to redo a step (a step with the same dt but where you have changed other options like the mdot)
1193+
Does not actually take the step
1194+
"""
1195+
function = LegacyFunctionSpecification()
1196+
function.addParameter('index_of_the_star', dtype='int32', direction=function.IN
1197+
, description="The index of the star to get the value of")
1198+
function.addParameter('result', dtype='int32', direction=function.OUT
1199+
, description="What the star should do next (keep going, redo, retry, terminate)")
1200+
function.result_type = 'int32'
1201+
return function
1202+
11291203

11301204
class MESA(StellarEvolution, InternalStellarStructure):
11311205

@@ -1333,6 +1407,13 @@ def define_particle_sets(self, handler):
13331407
handler.add_method(particle_set_name, 'get_blocker_wind_efficiency')
13341408
handler.add_method(particle_set_name, 'set_blocker_wind_efficiency')
13351409

1410+
handler.add_method(particle_set_name, 'solve_one_step')
1411+
handler.add_method(particle_set_name, 'solve_one_step_pre')
1412+
handler.add_method(particle_set_name, 'solve_one_step_post')
1413+
handler.add_method(particle_set_name, 'prepare_retry_step')
1414+
handler.add_method(particle_set_name, 'prepare_redo_step')
1415+
1416+
13361417
def define_state(self, handler):
13371418
StellarEvolution.define_state(self, handler)
13381419
handler.add_method('EDIT', 'new_pre_ms_particle')
@@ -1776,6 +1857,36 @@ def define_methods(self, handler):
17761857
(handler.ERROR_CODE)
17771858
)
17781859

1860+
handler.add_method(
1861+
"solve_one_step",
1862+
(handler.INDEX, handler.NO_UNIT),
1863+
(handler.NO_UNIT,handler.ERROR_CODE)
1864+
)
1865+
1866+
handler.add_method(
1867+
"solve_one_step_pre",
1868+
(handler.INDEX),
1869+
(handler.NO_UNIT,handler.ERROR_CODE)
1870+
)
1871+
1872+
handler.add_method(
1873+
"solve_one_step_post",
1874+
(handler.INDEX),
1875+
(handler.NO_UNIT,handler.ERROR_CODE)
1876+
)
1877+
1878+
handler.add_method(
1879+
"prepare_retry_step",
1880+
(handler.INDEX, units.s),
1881+
(handler.NO_UNIT,handler.ERROR_CODE)
1882+
)
1883+
1884+
handler.add_method(
1885+
"prepare_redo_step",
1886+
(handler.INDEX),
1887+
(handler.NO_UNIT,handler.ERROR_CODE)
1888+
)
1889+
17791890
def initialize_module_with_default_parameters(self):
17801891
self.parameters.set_defaults()
17811892
self.initialize_code()

0 commit comments

Comments
 (0)