https://mooseframework.inl.gov
Loading...
Searching...
No Matches
LibtorchRandomUtils.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
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
12#include "LibtorchRandomUtils.h"
13
14#include <ATen/CPUGeneratorImpl.h>
15#include <ATen/ops/linalg_qr.h>
16#include <ATen/ops/normal.h>
17
18#include "MooseError.h"
19
20namespace Moose
21{
22
23at::Generator
25{
26 return at::detail::createCPUGenerator();
27}
28
29at::Generator
30makeLibtorchCPUGenerator(const uint64_t seed)
31{
32 return at::detail::createCPUGenerator(seed);
33}
34
35void
36orthogonalInitializeTensor(torch::Tensor & tensor,
37 const Real gain,
38 const c10::optional<at::Generator> generator)
39{
40 if (tensor.ndimension() < 2)
41 mooseError("Only tensors with 2 or more dimensions are supported for orthogonal "
42 "initialization.");
43
44 if (!tensor.numel())
45 return;
46
47 torch::NoGradGuard no_grad;
48
49 const auto rows = tensor.size(0);
50 const auto cols = tensor.numel() / rows;
51 auto flattened = torch::empty({rows, cols}, tensor.options());
52 at::normal_out(flattened, 0.0, 1.0, {rows, cols}, generator);
53
54 if (rows < cols)
55 flattened = flattened.transpose(0, 1);
56
57 auto qr = at::linalg_qr(flattened, "reduced");
58 auto q = std::get<0>(qr);
59 const auto phases = torch::diag(std::get<1>(qr), 0).sign();
60 q = q * phases;
61
62 if (rows < cols)
63 q = q.transpose(0, 1);
64
65 tensor.view_as(q).copy_(q);
66 tensor.mul_(gain);
67}
68
69} // namespace Moose
70
71#endif
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
void orthogonalInitializeTensor(torch::Tensor &tensor, Real gain=1.0, c10::optional< at::Generator > generator=c10::nullopt)
Fill a tensor with a (semi) orthogonal matrix using the provided generator.
at::Generator makeLibtorchCPUGenerator()
Create an owned CPU generator using libtorch's default seed behavior.