Project
Loading...
Searching...
No Matches
AlignmentDOF.h
Go to the documentation of this file.
1// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12#ifndef O2_ITS3_ALIGNMENT_DOF_H
13#define O2_ITS3_ALIGNMENT_DOF_H
14
15#include <algorithm>
16#include <cstdint>
17#include <format>
18#include <stdexcept>
19#include <string>
20#include <vector>
21
22#include <Eigen/Dense>
23
25
27 int sensorID{-1};
28 int layerID{-1};
29 double measX{0.};
30 double measAlpha{0.};
31 double measZ{0.};
32 double trkY{0.};
33 double trkZ{0.};
34 double snp{0.};
35 double tgl{0.};
36 double dydx{0.};
37 double dzdx{0.};
38};
39
40// Generic set of DOF
41class DOFSet
42{
43 public:
44 enum class Type : uint8_t {
48 };
49 virtual ~DOFSet() = default;
50 virtual Type type() const = 0;
51 int nDOFs() const { return static_cast<int>(mFree.size()); }
52 virtual std::string dofName(int idx) const = 0;
53 virtual void fillDerivatives(const DerivativeContext& ctx, Eigen::Ref<Eigen::MatrixXd> out) const = 0;
54 bool isFree(int idx) const { return mFree[idx]; }
55 void setFree(int idx, bool f) { mFree[idx] = f; }
56 void setAllFree(bool f) { std::fill(mFree.begin(), mFree.end(), f); }
57 int nFreeDOFs() const
58 {
59 int n = 0;
60 for (bool f : mFree) {
61 n += f;
62 }
63 return n;
64 }
65
66 protected:
68 std::vector<bool> mFree;
69};
70
71// Rigid body set
72class RigidBodyDOFSet final : public DOFSet
73{
74 public:
75 // indices for rigid body parameters in LOC frame
76 enum RigidBodyDOF : uint8_t {
77 TX = 0,
84 };
85 static constexpr const char* RigidBodyDOFNames[RigidBodyDOF::NDOF] = {"TX", "TY", "TZ", "RX", "RY", "RZ"};
86
88 // mask: bitmask of free DOFs (bit i = DOF i is free)
89 explicit RigidBodyDOFSet(uint8_t mask) : DOFSet(NDOF)
90 {
91 for (int i = 0; i < NDOF; ++i) {
92 mFree[i] = (mask >> i) & 1;
93 }
94 }
95 Type type() const override { return Type::RigidBody; }
96 std::string dofName(int idx) const override { return RigidBodyDOFNames[idx]; }
97 void fillDerivatives(const DerivativeContext& ctx, Eigen::Ref<Eigen::MatrixXd> out) const override;
98 uint8_t mask() const
99 {
100 uint8_t m = 0;
101 for (int i = 0; i < NDOF; ++i) {
102 m |= (uint8_t(mFree[i]) << i);
103 }
104 return m;
105 }
106};
107
108// Legendre DOFs
109// Describing radial misplacement
110class LegendreDOFSet final : public DOFSet
111{
112 public:
113 explicit LegendreDOFSet(int order) : DOFSet((order + 1) * (order + 2) / 2), mOrder(order) {}
114 Type type() const override { return Type::Legendre; }
115 int order() const { return mOrder; }
116 std::string dofName(int idx) const override
117 {
118 int i = 0;
119 while ((i + 1) * (i + 2) / 2 <= idx) {
120 ++i;
121 }
122 int j = idx - (i * (i + 1) / 2);
123 return std::format("L({},{})", i, j);
124 }
125 void fillDerivatives(const DerivativeContext& ctx, Eigen::Ref<Eigen::MatrixXd> out) const override;
126
127 private:
128 int mOrder;
129};
130
131// Deformation DOFs for an open cylindrical half-shell.
132//
133// Inextensional part. Vanishing linear membrane strains admit the general solution (u in the local (r, phi, z)
134// directions) u_z = f(phi) u_phi = -(z/r) f'(phi) + g(phi) u_r = (z/r) f''(phi) - g'(phi) with two arbitrary
135// one-dimensional functions f, g. Because the shell is open in phi these are expanded in Legendre polynomials of the
136// normalised azimuth u in [-1, 1]: f(phi) = sum_k f_k P_k(u), g(phi) = sum_k g_k P_k(u).
137//
138// Extensional part (optional). The inextensional u_r is at most linear in z, so radial deformations with curvature
139// along z lie outside it. They are added as strictly radial modes u_r += sum_{k,l} h_{k,l} P_k(u) P_l(v), l >= 1, with
140// v the normalised axial coordinate. l = 0 is excluded because a z-independent radial field is already spanned by the g
141// family.
142//
143// Flat index layout: [f_0, g_0, f_1, g_1, ..., f_K, g_K, h_{0,1} ... h_{0,Lz}, h_{1,1} ... h_{Kphi,Lz}]
144//
145// NOTE on degeneracies: f_0 is a rigid translation along the cylinder axis and g_0 a rigid rotation about it, i.e. they
146// duplicate rigid-body DOFs of the same volume.
147class InextensionalDOFSet final : public DOFSet
148{
149 public:
150 explicit InextensionalDOFSet(int maxOrder, int extOrderPhi = -1, int extOrderZ = 0)
152 mMaxOrder(maxOrder),
153 mExtOrderPhi(extOrderZ > 0 ? extOrderPhi : -1),
154 mExtOrderZ(extOrderPhi >= 0 ? extOrderZ : 0)
155 {
156 if (maxOrder < 1) {
157 // only k = 0 is left, which is equivalent to a rigid body motion
158 throw std::invalid_argument("InextensionalDOFSet requires maxOrder >= 1");
159 }
160 // f_0 / g_0 are rigid: fixed unless explicitly freed
161 setFree(fIdx(0), false);
162 setFree(gIdx(0), false);
163 }
164
165 static int nDOFsFor(int maxOrder, int extOrderPhi, int extOrderZ)
166 {
167 int n = 2 * (maxOrder + 1);
168 if (extOrderPhi >= 0 && extOrderZ > 0) {
169 n += (extOrderPhi + 1) * extOrderZ;
170 }
171 return n;
172 }
173
174 Type type() const override { return Type::Inextensional; }
175 int maxOrder() const { return mMaxOrder; }
176 int extOrderPhi() const { return mExtOrderPhi; }
177 int extOrderZ() const { return mExtOrderZ; }
178 bool hasExtensional() const { return mExtOrderPhi >= 0 && mExtOrderZ > 0; }
179
180 // number of inextensional DOFs (before the radial h modes)
181 int nInextensional() const { return 2 * (mMaxOrder + 1); }
182
183 // flat indices
184 static int fIdx(int k) { return 2 * k; }
185 static int gIdx(int k) { return (2 * k) + 1; }
186 int hIdx(int k, int l) const { return nInextensional() + (k * mExtOrderZ) + (l - 1); }
187
188 std::string dofName(int idx) const override
189 {
190 if (idx < nInextensional()) {
191 return std::format("{}_{}", (idx % 2 == 0) ? "f" : "g", idx / 2);
192 }
193 const int e = idx - nInextensional();
194 return std::format("h_{}_{}", e / mExtOrderZ, (e % mExtOrderZ) + 1);
195 }
196 void fillDerivatives(const DerivativeContext& ctx, Eigen::Ref<Eigen::MatrixXd> out) const override;
197
198 private:
199 int mMaxOrder;
200 int mExtOrderPhi;
201 int mExtOrderZ;
202};
203
204#endif
int32_t i
uint32_t j
Definition RawData.h:0
virtual Type type() const =0
bool isFree(int idx) const
int nFreeDOFs() const
virtual void fillDerivatives(const DerivativeContext &ctx, Eigen::Ref< Eigen::MatrixXd > out) const =0
DOFSet(int n)
void setAllFree(bool f)
void setFree(int idx, bool f)
virtual ~DOFSet()=default
std::vector< bool > mFree
virtual std::string dofName(int idx) const =0
int nDOFs() const
static void checkDOFCount(int nDOFs)
throws if a DOF set is too large to be labelled without aliasing
static int fIdx(int k)
int extOrderPhi() const
static int nDOFsFor(int maxOrder, int extOrderPhi, int extOrderZ)
bool hasExtensional() const
int hIdx(int k, int l) const
Type type() const override
int extOrderZ() const
void fillDerivatives(const DerivativeContext &ctx, Eigen::Ref< Eigen::MatrixXd > out) const override
InextensionalDOFSet(int maxOrder, int extOrderPhi=-1, int extOrderZ=0)
static int gIdx(int k)
int nInextensional() const
std::string dofName(int idx) const override
Type type() const override
LegendreDOFSet(int order)
int order() const
void fillDerivatives(const DerivativeContext &ctx, Eigen::Ref< Eigen::MatrixXd > out) const override
std::string dofName(int idx) const override
std::string dofName(int idx) const override
uint8_t mask() const
RigidBodyDOFSet(uint8_t mask)
void fillDerivatives(const DerivativeContext &ctx, Eigen::Ref< Eigen::MatrixXd > out) const override
static constexpr const char * RigidBodyDOFNames[RigidBodyDOF::NDOF]
Type type() const override
GLdouble n
Definition glcorearb.h:1982
const GLfloat * m
Definition glcorearb.h:4066
GLdouble f
Definition glcorearb.h:310
GLint GLuint mask
Definition glcorearb.h:291