https://mooseframework.inl.gov
Loading...
Searching...
No Matches
SamplerDRLControlTransfer.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://www.mooseframework.org
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
10#ifdef MOOSE_LIBTORCH_ENABLED
11
13#include "LibtorchDRLControl.h"
14
15#include <numeric>
16
18
21{
24
26 "Copies a DRL actor from a trainer object on the main app to a LibtorchDRLControl object "
27 "on the subapp.");
28
29 params.suppressParameter<MultiAppName>("from_multi_app");
30
31 params.addRequiredParam<UserObjectName>(
32 "trainer_name", "Trainer object that owns the latest controller network.");
33 params.addRequiredParam<std::string>("control_name", "Controller object name.");
34 return params;
35}
36
38 : StochasticToolsTransfer(parameters),
40 _control_name(getParam<std::string>("control_name")),
41 _trainer(getSurrogateTrainerByName<LibtorchDRLControlTrainer>(
42 getParam<UserObjectName>("trainer_name")))
43{
44}
45
46void
50
51void
53{
54 const auto n = getToMultiApp()->numGlobalApps();
55 for (MooseIndex(n) i = 0; i < n; i++)
56 {
57 if (getToMultiApp()->hasLocalApp(i))
58 {
59 // Get the control neural net from the trainer
61
62 LibtorchDRLControl & control_object = getDRLControl(i);
63
64 // Copy and the neural net and execute it to get the initial values
65 control_object.loadControlNeuralNet(trainer_nn);
66 control_object.execute();
67 }
68 }
69}
70
71void
75
76void
80
81void
85
86void
90
91void
93{
94 if (getToMultiApp()->hasLocalApp(_app_index))
95 {
96 // Use a rank-invariant seed based on the configured trainer seed, the current main-app
97 // training step, and the sampler row being executed. This keeps the stochastic rollout path
98 // tied to the actual sample instead of the transient local app slot chosen by batch-reset.
99 const uint64_t sample_seed = static_cast<uint64_t>(_trainer.seed()) +
100 static_cast<uint64_t>(_global_index) +
101 static_cast<uint64_t>(_sampler_ptr->getNumberOfRows()) *
102 static_cast<uint64_t>(_fe_problem.timeStep());
103 // Get the control neural net from the trainer
105
106 LibtorchDRLControl & control_object = getDRLControl(_app_index);
107
108 // Copy and the neural net and execute it to get the initial values
109 control_object.loadControlNeuralNet(trainer_nn);
110 control_object.setPolicySampleSeed(sample_seed);
111 control_object.execute();
112 }
113}
114
116SamplerDRLControlTransfer::getDRLControl(const unsigned int app_index)
117{
118 // Get the control object from the other app
119 FEProblemBase & app_problem = _multi_app->appProblemBase(app_index);
120 auto & control_warehouse = app_problem.getControlWarehouse();
121 std::shared_ptr<Control> control_ptr = control_warehouse.getActiveObject(_control_name);
122 LibtorchDRLControl * control_object = dynamic_cast<LibtorchDRLControl *>(control_ptr.get());
123
124 if (!control_object)
125 paramError("control_name", "The given control is not a LibtorchDRLControl!");
126
127 // The trainer builds one transition and one history lag per timestep_window steps, so any
128 // other window mixes held actions or skips policy evaluations made by the control.
129 const unsigned int timestep_window = _trainer.timestepWindow();
130 const unsigned int num_steps_in_period = control_object->numStepsInPeriod();
131 if (timestep_window != num_steps_in_period)
132 {
133 const auto divisor = std::gcd(timestep_window, num_steps_in_period);
134 const auto numerator = std::to_string(timestep_window / divisor);
135 const auto denominator = num_steps_in_period / divisor;
136 const std::string ratio = denominator == 1
137 ? numerator + " times"
138 : numerator + "/" + std::to_string(denominator) + " of";
139 paramError("control_name",
140 "The trainer '",
141 _trainer.name(),
142 "' has timestep_window = ",
143 timestep_window,
144 ", which is ",
145 ratio,
146 " this control's num_steps_in_period = ",
147 num_steps_in_period,
148 ". They must be equal so that each training transition corresponds to exactly one "
149 "policy evaluation.");
150 }
151
152 if (_trainer.inputTimesteps() != control_object->inputTimesteps())
153 paramError("control_name",
154 "The trainer '",
155 _trainer.name(),
156 "' has input_timesteps = ",
158 ", but this control has input_timesteps = ",
159 control_object->inputTimesteps(),
160 ". They must be equal so that the control stacks the same observation history "
161 "that the actor was trained on.");
162
163 if (_trainer.numberOfObservations() != control_object->numberOfObservations())
164 paramError("control_name",
165 "The trainer '",
166 _trainer.name(),
167 "' reads ",
169 " observation(s), but this control reads ",
170 control_object->numberOfObservations(),
171 ". They must be equal so that the actor receives the observations it was trained "
172 "on.");
173
174 if (_trainer.numberOfControlSignals() != control_object->numberOfControlSignals())
175 paramError("control_name",
176 "The trainer '",
177 _trainer.name(),
178 "' produces ",
180 " control signal(s), but this control sets ",
181 control_object->numberOfControlSignals(),
182 " parameter(s). They must be equal so that each actor output drives exactly one "
183 "controllable parameter.");
184
185 return *control_object;
186}
187
188void
192
193#endif
registerMooseObject("StochasticToolsApp", SamplerDRLControlTransfer)
ExecuteMooseObjectWarehouse< Control > & getControlWarehouse()
virtual int & timeStep() const
void suppressParameter(const std::string &name)
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
Fixed-horizon actor-critic trainer that collects trajectories from MOOSE reporters and runs a PPO upd...
unsigned int numberOfObservations() const
Return the number of observation reporters read at each time level.
const Moose::LibtorchActorNeuralNet & controlNeuralNet() const
Return the current actor network.
unsigned int seed() const
Return the trainer seed used for sampling and shuffling.
unsigned int timestepWindow() const
Return the number of raw reporter entries per training transition.
unsigned int numberOfControlSignals() const
Return the number of control signals produced by the actor.
unsigned int inputTimesteps() const
Return the number of observation time levels stacked into the network inputs.
A time-dependent, neural-network-based controller which is associated with a Proximal Policy Optimiza...
virtual void execute() override
Compute the actions and their corresponding logarithmic probabilities.
unsigned int numStepsInPeriod() const
Return the number of time steps between policy evaluations.
void loadControlNeuralNet(const Moose::LibtorchActorNeuralNet &input_nn)
Copy an actor network into this DRL controller.
void setPolicySampleSeed(uint64_t seed)
Reset the owned policy-sampling generator to a known seed.
unsigned int numberOfObservations() const
Return the number of observations read at each time level.
unsigned int inputTimesteps() const
Return the number of observation time levels stacked into the actor input.
unsigned int numberOfControlSignals() const
const std::string & name() const
void paramError(const std::string &param, Args... args) const
std::shared_ptr< T > getActiveObject(const std::string &name, THREAD_ID tid=0) const
Feed-forward actor network coupled to a Gaussian or Beta action distribution.
const std::shared_ptr< MultiApp > getToMultiApp() const
std::shared_ptr< MultiApp > _multi_app
Transfers a trained DRL controller from a trainer to controls on sampler subapps.
const LibtorchDRLControlTrainer & _trainer
The trainer object which will contains the control neural net.
virtual void execute() override
Execute the transfer in the standard non-batch path.
const std::string _control_name
The name of the control object on the other app where we want to copy our neural net.
static InputParameters validParams()
Return the input parameters supported by this transfer.
virtual void initializeToMultiapp() override
Initialize a batch transfer to the multiapp.
virtual void finalizeFromMultiapp() override
Finalize a batch transfer from the multiapp.
virtual void finalizeToMultiapp() override
Finalize a batch transfer to the multiapp.
LibtorchDRLControl & getDRLControl(unsigned int app_index)
Find the DRL control on a local subapp and check that its control period, observation history length,...
SamplerDRLControlTransfer(const InputParameters &parameters)
Build the transfer that pushes a trained controller into subapps.
virtual void executeToMultiapp() override
Execute a batch transfer to the multiapp.
virtual void executeFromMultiapp() override
Execute a batch transfer from the multiapp.
virtual void initializeFromMultiapp() override
Initialize a batch transfer from the multiapp.
virtual void initialSetup() override
Prepare the transfer for batch-mode execution.
dof_id_type getNumberOfRows() const
The class creates an additional API to allow Transfers to work when running the StochasticTools<FullS...
dof_id_type _global_index
Index for tracking the row index when using batch mode operation.
static InputParameters validParams()
dof_id_type _app_index
Index for the sub-app that the batch-mode multiapp is working on.
Sampler * _sampler_ptr
Pointer to the Sampler object used by the SamplerTransientMultiApp or SamplerFullSolveMultiApp.
Interface for objects that need to use samplers.
static InputParameters validParams()
FEProblemBase & _fe_problem