Specifying times¶
When calling ODEIntegrator
, there are three general ways of specifying the integration times.
1. Absolute times¶
The first way is to specify the actual times values instead of
specifying the initial time, final time, and time spacing separately.
This first way is the simplest approach and is sufficient if the initial and final times
do not change during optimization.
As shown below, we provide the times
argument when calling ODEIntegrator
.
import numpy as np
import matplotlib.pyplot as plt
from openmdao.api import Problem
from ozone.api import ODEIntegrator
from ozone.tests.ode_function_library.getting_started_ode_func \
import GettingStartedODEFunction
ode_function = GettingStartedODEFunction()
formulation = 'solver-based'
method_name = 'RK4'
initial_conditions = {'y': 1.}
# Only times is passed in.
times = np.linspace(0., 3., 101)
integrator = ODEIntegrator(ode_function, formulation, method_name,
times=times, initial_conditions=initial_conditions)
prob = Problem(model=integrator)
prob.setup(check=False)
prob.run_model()
plt.plot(prob['times'], prob['state:y'][:, 0])
plt.xlabel('t')
plt.ylabel('y')
plt.show()
2. Normalized times with fixed initial and final times¶
Alternatively, we can specify the initial time, final time, and relative positions of the times as a vector.
In this case, we provide the initial_time
, final_time
, and normalized_times
arguments when calling ODEIntegrator
:
import numpy as np
import matplotlib.pyplot as plt
from openmdao.api import Problem
from ozone.api import ODEIntegrator
from ozone.tests.ode_function_library.getting_started_ode_func \
import GettingStartedODEFunction
ode_function = GettingStartedODEFunction()
formulation = 'solver-based'
method_name = 'RK4'
initial_conditions = {'y': 1.}
# Here, initial_time, final_time, and normalized_times are passed in.
initial_time = 0.
final_time = 3.
normalized_times = np.linspace(0., 1., 101)
integrator = ODEIntegrator(ode_function, formulation, method_name,
initial_time=initial_time, final_time=final_time,
normalized_times=normalized_times, initial_conditions=initial_conditions)
prob = Problem(model=integrator)
prob.setup(check=False)
prob.run_model()
plt.plot(prob['times'], prob['state:y'][:, 0])
plt.xlabel('t')
plt.ylabel('y')
plt.show()
3. Normalized times with variable initial and final times¶
If the initial and/or final time changes during optimization, we can connect one or both from an external component that computes the initial and/or final time as an output. Here is an example where both are connected externally.
import numpy as np
import matplotlib.pyplot as plt
from openmdao.api import Problem, IndepVarComp
from ozone.api import ODEIntegrator
from ozone.tests.ode_function_library.getting_started_ode_func \
import GettingStartedODEFunction
ode_function = GettingStartedODEFunction()
formulation = 'solver-based'
method_name = 'RK4'
initial_conditions={'y': 1.}
# Only normalized_times is passed in
normalized_times = np.linspace(0., 1., 101)
integrator = ODEIntegrator(ode_function, formulation, method_name,
normalized_times=normalized_times, initial_conditions=initial_conditions)
# Below, initial_time and final_time are connected from external components.
prob = Problem()
prob.model.add_subsystem('initial_time_comp', IndepVarComp('initial_time', 0.))
prob.model.add_subsystem('final_time_comp', IndepVarComp('final_time', 3.))
prob.model.add_subsystem('integrator_group', integrator)
prob.model.connect('initial_time_comp.initial_time', 'integrator_group.initial_time')
prob.model.connect('final_time_comp.final_time', 'integrator_group.final_time')
prob.setup(check=False)
prob.run_model()
plt.plot(prob['integrator_group.times'], prob['integrator_group.state:y'][:, 0])
plt.xlabel('t')
plt.ylabel('y')
plt.show()