A PID controller for ODE adaptive step size control.
| 307 | |
| 308 | |
| 309 | class PIDStepSizeController: |
| 310 | """A PID controller for ODE adaptive step size control.""" |
| 311 | def __init__(self, h, pcoeff, icoeff, dcoeff, order=1, accept_safety=0.81, eps=1e-8): |
| 312 | self.h = h |
| 313 | self.b1 = (pcoeff + icoeff + dcoeff) / order |
| 314 | self.b2 = -(pcoeff + 2 * dcoeff) / order |
| 315 | self.b3 = dcoeff / order |
| 316 | self.accept_safety = accept_safety |
| 317 | self.eps = eps |
| 318 | self.errs = [] |
| 319 | |
| 320 | def limiter(self, x): |
| 321 | return 1 + math.atan(x - 1) |
| 322 | |
| 323 | def propose_step(self, error): |
| 324 | inv_error = 1 / (float(error) + self.eps) |
| 325 | if not self.errs: |
| 326 | self.errs = [inv_error, inv_error, inv_error] |
| 327 | self.errs[0] = inv_error |
| 328 | factor = self.errs[0] ** self.b1 * self.errs[1] ** self.b2 * self.errs[2] ** self.b3 |
| 329 | factor = self.limiter(factor) |
| 330 | accept = factor >= self.accept_safety |
| 331 | if accept: |
| 332 | self.errs[2] = self.errs[1] |
| 333 | self.errs[1] = self.errs[0] |
| 334 | self.h *= factor |
| 335 | return accept |
| 336 | |
| 337 | |
| 338 | class DPMSolver(nn.Module): |