DNDSR 0.2.1
Distributed Numeric Data Structure for CFV
Loading...
Searching...
No Matches
Elements.hpp
Go to the documentation of this file.
1#pragma once
2// Elements.hpp -- Finite element definitions for the Geom module.
3//
4// Architecture
5// ------------
6// Element metadata is split across three layers:
7//
8// ElemEnum.hpp ElemType / ParamSpace enumerations
9// ElementTraits.hpp Per-element compile-time data (nodes, faces, coords,
10// elevation spans, bisection topology, VTK mapping, ...)
11// Elements.hpp (this file) Runtime API consumed by the rest of the
12// codebase: thin wrappers that dispatch to ElementTraits
13// via DispatchElementType(), the Element struct, shape
14// function dispatch, and geometry helpers.
15//
16// Shape functions are auto-generated by tools/gen_shape_functions/ and live
17// in per-element headers under Geom/Elements/<ElemName>.hpp. Each header
18// provides a full specialization of ShapeFuncImpl<ElemType> with static
19// Diff0..Diff3 methods. ShapeFunc_DiNj() resolves the runtime ElemType to
20// the correct specialization via DispatchElementType().
21//
22// Remaining runtime-only logic
23// ----------------------------
24// GetO2ElemBisectVariant() -- chooses the shortest-diagonal bisection variant
25// for Tet10 (3 variants) and Pyramid14 (2 variants) based on physical
26// coordinates. This cannot be made constexpr because it depends on runtime
27// geometry.
28
29#include <type_traits>
30#include <cstdint>
31#include <array>
32#include <tuple>
33#include "DNDS/HardEigen.hpp"
34
35#include "DNDS/Defines.hpp"
36#include "Geometric.hpp"
37#include "BaseFunction.hpp"
38#include "ElemEnum.hpp"
39#include "ElementTraits.hpp"
40
41// Auto-generated per-element shape function headers
56
57namespace DNDS::Geom::Elem
58{
59
60 // ================================================================
61 // Thin wrappers that delegate to ElementTraits via DispatchElementType.
62 // These preserve the old free-function signatures for backward compat.
63 // ================================================================
64
66 {
67 return DispatchElementType(t, [](auto tr) -> ParamSpace
68 { return decltype(tr)::paramSpace; });
69 }
70
72 {
73 return DispatchElementType(t_v, [iFace](auto tr) -> ElemType
74 { return decltype(tr)::GetFaceType(iFace); });
75 }
76
77 /// Get the number of edges for a 3D element. Returns 0 for 1D/2D elements.
79 {
80 return DispatchElementType(t_v, [](auto tr) -> t_index
81 {
82 using T = decltype(tr);
83 if constexpr (T::dim >= 3)
84 return T::numEdges;
85 else
86 return 0; });
87 }
88
89 /// Get the element type of edge iEdge for a 3D element. Returns UnknownElem for 1D/2D.
91 {
92 return DispatchElementType(t_v, [iEdge](auto tr) -> ElemType
93 {
94 using T = decltype(tr);
95 if constexpr (T::dim >= 3)
96 return T::GetEdgeType(iEdge);
97 else
98 return UnknownElem; });
99 }
100
105
107 {
108 return DispatchElementType(t, [](auto tr) -> int
109 { return decltype(tr)::numElevNodes; });
110 }
111
113 {
114 return DispatchElementType(t, [](auto tr) -> ElemType
115 { return decltype(tr)::elevatedType; });
116 }
117
119 {
120 return DispatchElementType(t, [ine](auto tr) -> ElemType
121 {
122 using T = decltype(tr);
123 if constexpr (T::numElevNodes > 0)
124 return T::elevNodeSpanTypes[ine];
125 else
126 return UnknownElem; });
127 }
128
130 {
131 return ParamSpaceO1Elem(ps);
132 }
133
135 {
136 return DispatchElementType(t, [](auto tr) -> t_index
137 {
138 using T = decltype(tr);
139 if constexpr (T::order == 2)
140 return T::numBisect;
141 else
142 return 0; });
143 }
144
146 {
147 return DispatchElementType(t, [i](auto tr) -> ElemType
148 {
149 using T = decltype(tr);
150 if constexpr (T::order == 2)
151 return T::GetBisectElemType(i);
152 else
153 return UnknownElem; });
154 }
155
156 DNDS_DEVICE_CALLABLE static constexpr real _iipow(real x, int y)
157 {
158 if (y == 0)
159 return 1.;
160 if (y == 1)
161 return x;
162 if (y > 1)
163 return x * _iipow(x, y - 1);
164 if (y == -1)
165 return 1. / x;
166 if (y < -1)
167 return 1. / x * _iipow(x, y + 1);
168 return UnInitReal;
169 }
170
171 /// Primary template for per-element shape function implementations.
172 /// Full specializations are auto-generated in Geom/Elements/<Elem>.hpp.
173 template <ElemType>
175
176 /**
177 * @brief Dispatch to per-element shape function code via ShapeFuncImpl<T>.
178 *
179 * Each ShapeFuncImpl specialization provides static Diff0..Diff3 methods.
180 * DispatchElementType (from ElementTraits.hpp) resolves the runtime ElemType
181 * to the correct compile-time specialization.
182 */
183 template <int diffOrder, class TPoint, class TArray>
184 DNDS_DEVICE_CALLABLE void ShapeFunc_DiNj(ElemType t, const TPoint &p, TArray &&v)
185 {
186 static_assert(diffOrder == 0 || diffOrder == 1 || diffOrder == 2 || diffOrder == 3);
187
188 DispatchElementType(t, [&](auto traits)
189 {
190 constexpr ElemType eType = decltype(traits)::elemType;
191 if constexpr (diffOrder == 0)
192 ShapeFuncImpl<eType>::Diff0(p, std::forward<TArray>(v));
193 else if constexpr (diffOrder == 1)
194 ShapeFuncImpl<eType>::Diff1(p, std::forward<TArray>(v));
195 else if constexpr (diffOrder == 2)
196 ShapeFuncImpl<eType>::Diff2(p, std::forward<TArray>(v));
197 else if constexpr (diffOrder == 3)
198 ShapeFuncImpl<eType>::Diff3(p, std::forward<TArray>(v)); });
199 }
200
201 using tNj = Eigen::RowVector<t_real, Eigen::Dynamic>;
202 using tD1Nj = Eigen::Matrix<t_real, 3, Eigen::Dynamic>;
203 using tD01Nj = Eigen::Matrix<t_real, 4, Eigen::Dynamic>;
204 using tDiNj = Eigen::Matrix<t_real, Eigen::Dynamic, Eigen::Dynamic>;
205
206 struct Element
207 {
209
211
212 DNDS_DEVICE_CALLABLE [[nodiscard]] constexpr ParamSpace GetParamSpace() const
213 {
215 }
216
217 DNDS_DEVICE_CALLABLE [[nodiscard]] constexpr t_index GetDim() const
218 {
219 return DispatchElementType(type, [](auto tr) -> t_index
220 { return decltype(tr)::dim; });
221 }
222
223 DNDS_DEVICE_CALLABLE [[nodiscard]] constexpr t_index GetOrder() const
224 {
225 return DispatchElementType(type, [](auto tr) -> t_index
226 { return decltype(tr)::order; });
227 }
228
229 DNDS_DEVICE_CALLABLE [[nodiscard]] constexpr t_index GetNumVertices() const
230 {
231 return DispatchElementType(type, [](auto tr) -> t_index
232 { return decltype(tr)::numVertices; });
233 }
234
235 DNDS_DEVICE_CALLABLE [[nodiscard]] constexpr t_index GetNumNodes() const
236 {
237 return DispatchElementType(type, [](auto tr) -> t_index
238 { return decltype(tr)::numNodes; });
239 }
240
241 DNDS_DEVICE_CALLABLE [[nodiscard]] constexpr t_index GetNumFaces() const
242 {
243 return DispatchElementType(type, [](auto tr) -> t_index
244 { return decltype(tr)::numFaces; });
245 }
246
247 DNDS_DEVICE_CALLABLE [[nodiscard]] constexpr t_index GetNumElev_O1O2() const
248 {
250 }
251
253 {
254 return GetO2ElemBisectNum(type);
255 }
256
257 DNDS_DEVICE_CALLABLE [[nodiscard]] constexpr Element ObtainFace(t_index iFace) const
258 {
259 DNDS_assert(iFace < this->GetNumFaces());
260 return Element{GetFaceType(type, iFace)};
261 }
262
263 /// Number of edges (3D elements only; returns 0 for 1D/2D).
264 DNDS_DEVICE_CALLABLE [[nodiscard]] constexpr t_index GetNumEdges() const
265 {
267 }
268
269 /// Edge sub-element type for edge iEdge (Line2 or Line3).
270 DNDS_DEVICE_CALLABLE [[nodiscard]] constexpr Element ObtainEdge(t_index iEdge) const
271 {
272 DNDS_assert(iEdge < this->GetNumEdges());
273 return Element{Geom::Elem::GetEdgeType(type, iEdge)};
274 }
275
276 /// Extract the global node indices of edge iEdge from a cell's node list.
277 /// @warning Assumes edgeNodesOut has sufficient size.
278 template <class TIn, class TOut>
279 void ExtractEdgeNodes(t_index iEdge, const TIn &nodes, TOut &edgeNodesOut)
280 {
281 DNDS_assert(iEdge < this->GetNumEdges());
282 DispatchElementType(type, [&](auto tr)
283 {
284 using T = decltype(tr);
285 if constexpr (T::dim >= 3)
286 {
287 for (t_index i = 0; i < ObtainEdge(iEdge).GetNumNodes(); i++)
288 edgeNodesOut[i] = nodes[T::edgeNodes[iEdge][i]];
289 } });
290 }
291
292 /**
293 * @warning assuming Out has correct size
294 */
295 template <class TIn, class TOut>
296 void ExtractFaceNodes(t_index iFace, const TIn &nodes, TOut &faceNodesOut)
297 {
298 DNDS_assert(iFace < this->GetNumFaces());
299 DispatchElementType(type, [&](auto tr)
300 {
301 using T = decltype(tr);
302 if constexpr (T::numFaces > 0)
303 {
304 for (t_index i = 0; i < ObtainFace(iFace).GetNumNodes(); i++)
305 faceNodesOut[i] = nodes[T::faceNodes[iFace][i]];
306 } });
307 }
308
309 [[nodiscard]] constexpr Element ObtainElevNodeSpan(t_index iNodeElev) const
310 {
311 DNDS_assert(iNodeElev < this->GetNumElev_O1O2());
313 }
314
315 [[nodiscard]] constexpr Element ObtainElevatedElem() const
316 {
318 }
319
320 [[nodiscard]] constexpr Element ObtainO1Elem() const
321 {
323 }
324
325 [[nodiscard]] Element ObtainO2BisectElem(t_index iSubElem) const
326 {
327 DNDS_assert(iSubElem < this->GetO2NumBisect());
328 return Element{GetO2ElemBisectElem(type, iSubElem)};
329 }
330
331 template <class TIn, class TOut>
332 void ExtractElevNodeSpanNodes(t_index iNodeElev, const TIn &nodes, TOut &spanNodes)
333 {
334 DNDS_assert(iNodeElev < this->GetNumElev_O1O2());
335 DispatchElementType(type, [&](auto tr)
336 {
337 using T = decltype(tr);
338 if constexpr (T::numElevNodes > 0)
339 {
340 auto spanElem = Element{T::elevNodeSpanTypes[iNodeElev]};
341 for (t_index i = 0; i < spanElem.GetNumNodes(); i++)
342 spanNodes[i] = nodes[T::elevSpans[iNodeElev][i]];
343 } });
344 }
345
346 template <class TIn, class TOut>
347 void ExtractO2BisectElemNodes(t_index iSubElem, t_index iVariant, const TIn &nodes, TOut &subNodes)
348 {
349 DNDS_assert(iSubElem < this->GetO2NumBisect());
350 DispatchElementType(type, [&](auto tr)
351 {
352 using T = decltype(tr);
353 if constexpr (T::order == 2)
354 {
355 DNDS_assert(iVariant < T::numBisectVariants);
356 t_index offset = iSubElem + T::numBisect * iVariant;
357 auto subElem = Element{T::GetBisectElemType(iSubElem)};
358 for (t_index i = 0; i < subElem.GetNumNodes(); i++)
359 subNodes[i] = nodes[T::bisectElements[offset][i]];
360 } });
361 }
362
363 /**
364 * @warning Nj resized within
365 */
366 DNDS_DEVICE_CALLABLE void GetNj(const tPoint &pParam, tNj &Nj) const
367 {
368 Nj.setZero(1, this->GetNumNodes());
369 ShapeFunc_DiNj<0>(type, pParam, Nj);
370 }
371
372 /**
373 * @warning D1Nj resized within
374 */
375 DNDS_DEVICE_CALLABLE void GetD1Nj(const tPoint &pParam, tD1Nj &D1Nj) const
376 {
377 D1Nj.setZero(3, this->GetNumNodes());
378 ShapeFunc_DiNj<1>(type, pParam, D1Nj);
379 }
380
381 /**
382 * @warning DiNj resized within
383 */
384 void GetD01Nj(const tPoint &pParam, tD01Nj &D01Nj) const
385 {
386 tNj Nj;
387 tD1Nj D1Nj;
388 this->GetNj(pParam, Nj);
389 this->GetD1Nj(pParam, D1Nj);
390
391 D01Nj.resize(4, this->GetNumNodes());
392 D01Nj(0, EigenAll) = Nj;
393 D01Nj({1, 2, 3}, EigenAll) = D1Nj;
394 }
395 /**
396 * @warning DiNj resized within
397 */
398 void GetDiNj(const tPoint &pParam, tDiNj &DiNj, int maxOrder) const
399 {
400 if (this->GetDim() == 2)
401 {
402 int nDiffCur = Base::ndiffSizC2D.at(maxOrder);
403 DiNj.setZero(nDiffCur, this->GetNumNodes());
404 for (; maxOrder >= 0; maxOrder--)
405 {
406 if (maxOrder == 3)
407 ShapeFunc_DiNj<3>(
408 type, pParam,
409 DiNj(
410 Eigen::seq(Base::ndiffSizC2D.at(2), Base::ndiffSizC2D.at(3) - 1),
411 EigenAll));
412 if (maxOrder == 2)
413 ShapeFunc_DiNj<2>(
414 type, pParam,
415 DiNj(
416 Eigen::seq(Base::ndiffSizC2D.at(1), Base::ndiffSizC2D.at(2) - 1),
417 EigenAll));
418 if (maxOrder == 1)
419 ShapeFunc_DiNj<1>(
420 type, pParam,
421 DiNj(
422 Eigen::seq(Base::ndiffSizC2D.at(0), Base::ndiffSizC2D.at(1) - 1),
423 EigenAll));
424 if (maxOrder == 0)
425 ShapeFunc_DiNj<0>(
426 type, pParam,
427 DiNj(
428 0,
429 EigenAll));
430 }
431 }
432 else if (this->GetDim() == 3)
433 {
434 int nDiffCur = Base::ndiffSizC.at(maxOrder);
435 DiNj.setZero(nDiffCur, this->GetNumNodes());
436 for (; maxOrder >= 0; maxOrder--)
437 {
438 if (maxOrder == 3)
439 ShapeFunc_DiNj<3>(
440 type, pParam,
441 DiNj(
442 Eigen::seq(Base::ndiffSizC.at(2), Base::ndiffSizC.at(3) - 1),
443 EigenAll));
444 if (maxOrder == 2)
445 ShapeFunc_DiNj<2>(
446 type, pParam,
447 DiNj(
448 Eigen::seq(Base::ndiffSizC.at(1), Base::ndiffSizC.at(2) - 1),
449 EigenAll));
450 if (maxOrder == 1)
451 ShapeFunc_DiNj<1>(
452 type, pParam,
453 DiNj(
454 Eigen::seq(Base::ndiffSizC.at(0), Base::ndiffSizC.at(1) - 1),
455 EigenAll));
456 if (maxOrder == 0)
457 ShapeFunc_DiNj<0>(
458 type, pParam,
459 DiNj(
460 0,
461 EigenAll));
462 }
463 }
464 else if (this->GetDim() == 1)
465 {
466 int nDiffCur = maxOrder + 1;
467 DiNj.setZero(nDiffCur, this->GetNumNodes());
468 for (; maxOrder >= 0; maxOrder--)
469 {
470 if (maxOrder == 3)
471 ShapeFunc_DiNj<3>(
472 type, pParam,
473 DiNj(
474 3,
475 EigenAll));
476 if (maxOrder == 2)
477 ShapeFunc_DiNj<2>(
478 type, pParam,
479 DiNj(
480 2,
481 EigenAll));
482 if (maxOrder == 1)
483 ShapeFunc_DiNj<1>(
484 type, pParam,
485 DiNj(
486 1,
487 EigenAll));
488 if (maxOrder == 0)
489 ShapeFunc_DiNj<0>(
490 type, pParam,
491 DiNj(
492 0,
493 EigenAll));
494 }
495 }
496 }
497 };
498
499 Eigen::Matrix<t_real, 3, Eigen::Dynamic> GetStandardCoord(ElemType t);
500}
501
502namespace DNDS::Geom::Elem
503{
505 const std::vector<DNDS::index> &nodes_A,
506 const std::vector<DNDS::index> &nodes_B,
507 Element eA,
508 Element eB)
509 {
510 DNDS_assert(nodes_A.size() >= eA.GetNumNodes());
511 DNDS_assert(nodes_B.size() >= eB.GetNumVertices());
512 std::vector<DNDS::index> nodes_B_Vert{nodes_B.begin(), nodes_B.begin() + eB.GetNumVertices()};
513 std::sort(nodes_B_Vert.begin(), nodes_B_Vert.end());
514 for (int iF = 0; iF < eA.GetNumFaces(); iF++)
515 {
516 auto eF = eA.ObtainFace(iF);
517 std::vector<DNDS::index> fNodes(eF.GetNumNodes());
518 eA.ExtractFaceNodes(iF, nodes_A, fNodes);
519 std::sort(fNodes.begin(), fNodes.begin() + eF.GetNumVertices());
520 if (std::includes(
521 nodes_B_Vert.begin(), nodes_B_Vert.end(),
522 fNodes.begin(), fNodes.begin() + eF.GetNumVertices()))
523 return true;
524 }
525 return false;
526 }
527
529 const std::vector<DNDS::index> &verts_A,
530 const std::vector<DNDS::index> &nodes_B)
531 {
532
533 return false;
534 }
535
536 template <class tCoordsIn>
537 tJacobi ShapeJacobianCoordD01Nj(const tCoordsIn &cs, Eigen::Ref<const tD01Nj> DiNj)
538 {
539 return cs * DiNj({1, 2, 3}, EigenAll).transpose();
540 }
541
542 template <class tCoordsIn>
543 tPoint PPhysicsCoordD01Nj(const tCoordsIn &cs, Eigen::Ref<const tD01Nj> DiNj)
544 {
545 return cs * DiNj(0, EigenAll).transpose();
546 }
547
548 template <int dim>
549 real JacobiDetFace(Eigen::Ref<const tJacobi> J)
550 {
551 static_assert(dim == 2 || dim == 3);
552 if constexpr (dim == 2)
553 return J(EigenAll, 0).stableNorm();
554 else
555 return J(EigenAll, 0).cross(J(EigenAll, 1)).stableNorm();
556 }
557
558 // TODO: add a integration-based counterpart
560 {
561 tPoint c = coords.rowwise().mean();
562 tSmallCoords coordsC = coords.colwise() - c;
563 tPoint ve0 = coordsC(EigenAll, 1) - coordsC(EigenAll, 0);
564 tJacobi inertia = coordsC * coordsC.transpose();
565 real cond01 = HardEigen::Eigen3x3RealSymEigenDecompositionGetCond01(inertia); // ratio of 2 largest eigenvalues
566 if (cond01 < 1 + 1e-6)
567 inertia += ve0 * ve0.transpose() * 1e-4; // first edge gets priority
569 coordsC = decRet.transpose() * coordsC;
570 tPoint ret = coordsC.rowwise().maxCoeff() - coordsC.rowwise().minCoeff();
571 std::sort(ret.begin(), ret.end(), std::greater_equal<real>());
572 return ret;
573 }
574
576 {
577 DNDS_assert(e.GetOrder() == 2);
578 //! if serendipity ?
579 switch (e.type)
580 {
581 case Tet10:
582 {
583 Eigen::Vector<real, 3> lengths{
584 (coords(EigenAll, 5 - 1) - coords(EigenAll, 10 - 1)).norm(),
585 (coords(EigenAll, 6 - 1) - coords(EigenAll, 8 - 1)).norm(),
586 (coords(EigenAll, 7 - 1) - coords(EigenAll, 9 - 1)).norm(),
587 };
588 Eigen::Index iMin{-1};
589 real minLen = lengths.minCoeff(&iMin);
590 (void)minLen;
591 return t_index(iMin);
592 }
593 break;
594 case Pyramid14:
595 {
596 Eigen::Vector<real, 2> lengths{
597 (coords(EigenAll, 10 - 1) - coords(EigenAll, 12 - 1)).norm(),
598 (coords(EigenAll, 11 - 1) - coords(EigenAll, 13 - 1)).norm(),
599 };
600 Eigen::Index iMin{-1};
601 real minLen = lengths.minCoeff(&iMin);
602 (void)minLen;
603 return t_index(iMin);
604 }
605 break;
606 default:
607 return 0;
608 }
609 }
610
611 template <class TIn>
612 std::pair<int, std::vector<index>> ToVTKVertsAndData(Element e, const TIn &vin)
613 {
614 return DispatchElementType(e.type, [&](auto tr) -> std::pair<int, std::vector<index>>
615 {
616 using T = decltype(tr);
617 constexpr int nOut = static_cast<int>(
618 std::tuple_size<decltype(T::vtkNodeOrder)>::value);
619 std::vector<index> v(nOut);
620 for (int i = 0; i < nOut; i++)
621 v[i] = vin[T::vtkNodeOrder[i]];
622 return {T::vtkCellType, std::move(v)}; });
623 }
624}
Core type aliases, constants, and metaprogramming utilities for the DNDS framework.
#define DNDS_DEVICE_TRIVIAL_COPY_DEFINE(T, T_Self)
Definition Defines.hpp:87
#define DNDS_DEVICE_CALLABLE
Definition Defines.hpp:76
#define DNDS_assert(expr)
Debug-only assertion (compiled out when DNDS_NDEBUG is defined). Prints the expression + file/line + ...
Definition Errors.hpp:112
Robust linear-algebra primitives for small / moderately-sized Eigen matrices that are more numericall...
Eigen::Matrix< t_real, Eigen::Dynamic, Eigen::Dynamic > tDiNj
Definition Elements.hpp:204
Eigen::Matrix< t_real, 3, Eigen::Dynamic > tD1Nj
Definition Elements.hpp:202
tJacobi ShapeJacobianCoordD01Nj(const tCoordsIn &cs, Eigen::Ref< const tD01Nj > DiNj)
Definition Elements.hpp:537
DNDS_DEVICE_CALLABLE constexpr t_index GetNumEdges(ElemType t_v)
Get the number of edges for a 3D element. Returns 0 for 1D/2D elements.
Definition Elements.hpp:78
DNDS_DEVICE_CALLABLE constexpr ParamSpace ElemType_to_ParamSpace(const ElemType t)
Definition Elements.hpp:65
DNDS_DEVICE_CALLABLE constexpr ElemType GetElemO1(ParamSpace ps)
Definition Elements.hpp:129
DNDS_DEVICE_CALLABLE constexpr decltype(auto) DispatchElementType(ElemType t, Func &&func)
Static dispatch over element types at compile time.
DNDS_DEVICE_CALLABLE constexpr int GetElemElevation_O1O2_NumNode(ElemType t)
Definition Elements.hpp:106
DNDS_DEVICE_CALLABLE constexpr t_index GetO2ElemBisectNum(ElemType t)
Definition Elements.hpp:134
DNDS_DEVICE_CALLABLE constexpr ElemType GetO2ElemBisectElem(ElemType t, t_index i)
Definition Elements.hpp:145
DNDS_DEVICE_CALLABLE constexpr ElemType GetElemElevation_O1O2_ElevatedType(ElemType t)
Definition Elements.hpp:112
DNDS_DEVICE_CALLABLE constexpr t_real ParamSpaceVolume(ParamSpace ps)
Get the volume of a parametric space.
Eigen::Matrix< t_real, 4, Eigen::Dynamic > tD01Nj
Definition Elements.hpp:203
bool cellsAreFaceConnected(const std::vector< DNDS::index > &nodes_A, const std::vector< DNDS::index > &nodes_B, Element eA, Element eB)
Definition Elements.hpp:504
std::pair< int, std::vector< index > > ToVTKVertsAndData(Element e, const TIn &vin)
Definition Elements.hpp:612
DNDS_DEVICE_CALLABLE constexpr ElemType GetEdgeType(ElemType t_v, t_index iEdge)
Get the element type of edge iEdge for a 3D element. Returns UnknownElem for 1D/2D.
Definition Elements.hpp:90
DNDS_DEVICE_CALLABLE void ShapeFunc_DiNj(ElemType t, const TPoint &p, TArray &&v)
Dispatch to per-element shape function code via ShapeFuncImpl<T>.
Definition Elements.hpp:184
tPoint GetElemNodeMajorSpan(const tSmallCoords &coords)
Definition Elements.hpp:559
real JacobiDetFace(Eigen::Ref< const tJacobi > J)
Definition Elements.hpp:549
DNDS_DEVICE_CALLABLE constexpr t_real ParamSpaceVol(ParamSpace ps)
Definition Elements.hpp:101
DNDS_DEVICE_CALLABLE constexpr ElemType GetElemElevation_O1O2_NodeSpanType(ElemType t, t_index ine)
Definition Elements.hpp:118
DNDS_DEVICE_CALLABLE constexpr ElemType GetFaceType(ElemType t_v, t_index iFace)
Definition Elements.hpp:71
DNDS_DEVICE_CALLABLE constexpr ElemType ParamSpaceO1Elem(ParamSpace ps)
Get the order-1 (linear) element type for a parametric space.
Eigen::Matrix< t_real, 3, Eigen::Dynamic > GetStandardCoord(ElemType t)
Definition Elements.cpp:6
Eigen::RowVector< t_real, Eigen::Dynamic > tNj
Definition Elements.hpp:201
tPoint PPhysicsCoordD01Nj(const tCoordsIn &cs, Eigen::Ref< const tD01Nj > DiNj)
Definition Elements.hpp:543
t_index GetO2ElemBisectVariant(Element e, const tSmallCoords &coords)
Definition Elements.hpp:575
int32_t t_index
Definition Geometric.hpp:6
Eigen::Matrix3d tJacobi
Definition Geometric.hpp:10
Eigen::Vector3d tPoint
Definition Geometric.hpp:9
Eigen::Matrix< real, 3, Eigen::Dynamic > tSmallCoords
Definition Geometric.hpp:50
double t_real
Definition Geometric.hpp:8
real Eigen3x3RealSymEigenDecompositionGetCond01(const Eigen::Matrix3d &A)
Like Eigen3x3RealSymEigenDecompositionGetCond but returns lambda0 / lambda1 only (ignores the smalles...
Eigen::Matrix3d Eigen3x3RealSymEigenDecompositionNormalized(const Eigen::Matrix3d &A)
Eigen-decomposition with eigenvector columns normalised to unit length.
DNDS_CONSTANT const real UnInitReal
Sentinel "not initialised" real value (NaN). Cheap to detect with std::isnan or IsUnInitReal; survive...
Definition Defines.hpp:179
double real
Canonical floating-point scalar used throughout DNDSR (double precision).
Definition Defines.hpp:110
DNDS_DEVICE_CALLABLE constexpr t_index GetNumEdges() const
Number of edges (3D elements only; returns 0 for 1D/2D).
Definition Elements.hpp:264
constexpr Element ObtainO1Elem() const
Definition Elements.hpp:320
DNDS_DEVICE_CALLABLE constexpr Element ObtainEdge(t_index iEdge) const
Edge sub-element type for edge iEdge (Line2 or Line3).
Definition Elements.hpp:270
void ExtractO2BisectElemNodes(t_index iSubElem, t_index iVariant, const TIn &nodes, TOut &subNodes)
Definition Elements.hpp:347
DNDS_DEVICE_CALLABLE constexpr ParamSpace GetParamSpace() const
Definition Elements.hpp:212
constexpr Element ObtainElevNodeSpan(t_index iNodeElev) const
Definition Elements.hpp:309
void ExtractEdgeNodes(t_index iEdge, const TIn &nodes, TOut &edgeNodesOut)
Definition Elements.hpp:279
DNDS_DEVICE_CALLABLE void GetNj(const tPoint &pParam, tNj &Nj) const
Definition Elements.hpp:366
DNDS_DEVICE_CALLABLE constexpr Element ObtainFace(t_index iFace) const
Definition Elements.hpp:257
DNDS_DEVICE_CALLABLE t_index GetO2NumBisect() const
Definition Elements.hpp:252
constexpr Element ObtainElevatedElem() const
Definition Elements.hpp:315
DNDS_DEVICE_CALLABLE constexpr t_index GetNumElev_O1O2() const
Definition Elements.hpp:247
DNDS_DEVICE_CALLABLE constexpr t_index GetNumVertices() const
Definition Elements.hpp:229
DNDS_DEVICE_CALLABLE constexpr t_index GetNumFaces() const
Definition Elements.hpp:241
DNDS_DEVICE_CALLABLE void GetD1Nj(const tPoint &pParam, tD1Nj &D1Nj) const
Definition Elements.hpp:375
void GetD01Nj(const tPoint &pParam, tD01Nj &D01Nj) const
Definition Elements.hpp:384
void ExtractFaceNodes(t_index iFace, const TIn &nodes, TOut &faceNodesOut)
Definition Elements.hpp:296
void GetDiNj(const tPoint &pParam, tDiNj &DiNj, int maxOrder) const
Definition Elements.hpp:398
Element ObtainO2BisectElem(t_index iSubElem) const
Definition Elements.hpp:325
DNDS_DEVICE_CALLABLE constexpr t_index GetDim() const
Definition Elements.hpp:217
void ExtractElevNodeSpanNodes(t_index iNodeElev, const TIn &nodes, TOut &spanNodes)
Definition Elements.hpp:332
DNDS_DEVICE_CALLABLE constexpr t_index GetOrder() const
Definition Elements.hpp:223
DNDS_DEVICE_CALLABLE constexpr t_index GetNumNodes() const
Definition Elements.hpp:235
Eigen::Matrix< real, 5, 1 > v
tVec x(NCells)
double order
Definition test_ODE.cpp:257
const tPoint const tPoint const tPoint & p