NimbleSM
NimbleSM is a solid mechanics simulation code for dynamic systems
Loading...
Searching...
No Matches
nimble::HexElement Class Reference

Class for an 8-node hexahedral element. More...

#include <nimble_element.h>

Inheritance diagram for nimble::HexElement:
nimble::Element

Public Member Functions

NIMBLE_FUNCTION HexElement ()
 Default constructor.
 
NIMBLE_FUNCTION ~HexElement () override=default
 Default destructor.
 
int Dim () const override
 Returns the spatial dimension.
 
int NumNodesPerElement () const override
 Returns the number of nodes per element.
 
int NumIntegrationPointsPerElement () const override
 Returns the number of integration points per element.
 
void ComputeLumpedMass (double density, const double *node_reference_coords, double *lumped_mass) const override
 Compute the lumped mass.
 
double ComputeCharacteristicLength (const double *node_coords) override
 Function to compute the characteristic length.
 
void ComputeVolumeAverage (const double *node_current_coords, int num_quantities, const double *int_pt_quantities, double &volume, double *volume_averaged_quantity) const override
 
void ComputeDeformationGradients (const double *node_reference_coords, const double *node_current_coords, double *deformation_gradients) const override
 Function to compute the deformation gradients.
 
void ComputeTangent (const double *node_current_coords, const double *material_tangent, double *element_tangent) override
 Function to compute the tangent.
 
void ComputeNodalForces (const double *node_current_coords, const double *int_pt_stresses, double *node_forces) override
 Virtual function to compute the nodal forces.
 
- Public Member Functions inherited from nimble::Element
NIMBLE_FUNCTION Element ()=default
 Default constructor.
 
virtual NIMBLE_FUNCTION ~Element ()=default
 Default virtual destructor.
 

Protected Member Functions

template<class ViewT>
void ComputeConsistentMass_impl (double density, const ViewT node_reference_coords, double consistent_mass_matrix[][num_nodes_]) const
 
template<class ConstViewVec, class ConstViewTensor, class ViewTensor>
void ComputeVolumeAverageQuantities_impl (ConstViewVec node_reference_coords, ConstViewVec node_displacements, ConstViewTensor int_pt_quantities, ViewTensor vol_ave_quantity, int num_quantities, double &volume) const
 
template<class ConstViewT, class TensorViewT>
NIMBLE_FUNCTION void ComputeDeformationGradients_impl (ConstViewT node_reference_coords, ConstViewT node_displacements, TensorViewT deformation_gradients) const
 
template<class ConstViewT, class ViewTensorT, class ViewT>
void ComputeNodalForces_impl (ConstViewT node_reference_coords, ConstViewT node_displacements, ViewTensorT int_pt_stresses, ViewT node_forces) const
 
NIMBLE_FUNCTION void ShapeFunctionValues (const double *natural_coords, double *shape_function_values)
 
NIMBLE_FUNCTION void ShapeFunctionDerivatives (const double *natural_coords, double *shape_function_derivatives)
 

Additional Inherited Members

- Protected Attributes inherited from nimble::Element
const int K_S_XX_ = 0
 
const int K_S_YY_ = 1
 
const int K_S_ZZ_ = 2
 
const int K_S_XY_ = 3
 
const int K_S_YZ_ = 4
 
const int K_S_ZX_ = 5
 
const int K_S_YX_ = 3
 
const int K_S_ZY_ = 4
 
const int K_S_XZ_ = 5
 
const int K_F_XX_ = 0
 
const int K_F_YY_ = 1
 
const int K_F_ZZ_ = 2
 
const int K_F_XY_ = 3
 
const int K_F_YZ_ = 4
 
const int K_F_ZX_ = 5
 
const int K_F_YX_ = 6
 
const int K_F_ZY_ = 7
 
const int K_F_XZ_ = 8
 

Detailed Description

Class for an 8-node hexahedral element.

Constructor & Destructor Documentation

◆ HexElement()

nimble::HexElement::HexElement ( )

Default constructor.

56{
57 // 1/sqrt(3)
58 constexpr double val = 0.577350269189626;
59 // integration point 1
60 int_pts_[0] = -val;
61 int_pts_[1] = -val;
62 int_pts_[2] = -val;
63 // integration point 2
64 int_pts_[3] = val;
65 int_pts_[4] = -val;
66 int_pts_[5] = -val;
67 // integration point 3
68 int_pts_[6] = val;
69 int_pts_[7] = val;
70 int_pts_[8] = -val;
71 // integration point 4
72 int_pts_[9] = -val;
73 int_pts_[10] = val;
74 int_pts_[11] = -val;
75 // integration point 5
76 int_pts_[12] = -val;
77 int_pts_[13] = -val;
78 int_pts_[14] = val;
79 // integration point 6
80 int_pts_[15] = val;
81 int_pts_[16] = -val;
82 int_pts_[17] = val;
83 // integration point 7
84 int_pts_[18] = val;
85 int_pts_[19] = val;
86 int_pts_[20] = val;
87 // integration point 8
88 int_pts_[21] = -val;
89 int_pts_[22] = val;
90 int_pts_[23] = val;
91
92 for (double & int_wt : int_wts_) { int_wt = 1.0; }
93
94 ShapeFunctionValues(int_pts_, shape_fcn_vals_);
95
96 ShapeFunctionDerivatives(int_pts_, shape_fcn_deriv_);
97}
NIMBLE_FUNCTION void ShapeFunctionDerivatives(const double *natural_coords, double *shape_function_derivatives)
Definition nimble_element.cc:125
NIMBLE_FUNCTION void ShapeFunctionValues(const double *natural_coords, double *shape_function_values)
Definition nimble_element.cc:100

◆ ~HexElement()

NIMBLE_FUNCTION nimble::HexElement::~HexElement ( )
overridedefault

Default destructor.

Member Function Documentation

◆ ComputeCharacteristicLength()

double nimble::HexElement::ComputeCharacteristicLength ( const double * node_coords)
overridevirtual

Function to compute the characteristic length.

Parameters
[in]node_coordsPointer to array of nodal coordinates
Returns
Characteristic length

Implements nimble::Element.

223{
224 // TODO Implement a better algorithm for finding the minimum
225 // length across the element.
226
227 double characteristic_length, distance_squared, min_distance_squared, nx, ny, nz, mx, my, mz;
228 double x_min, x_max, y_min, y_max, z_min, z_max;
229
230 x_max = y_max = z_max = 0.0;
231 min_distance_squared = x_min = y_min = z_min = std::numeric_limits<double>::max();
232
233 for (int n = 0; n < num_nodes_; n++) {
234 nx = node_coords[3 * n];
235 ny = node_coords[3 * n + 1];
236 nz = node_coords[3 * n + 2];
237 if (nx < x_min) { x_min = nx; }
238 if (nx > x_max) { x_max = nx; }
239 if (ny < y_min) { y_min = ny; }
240 if (ny > y_max) { y_max = ny; }
241 if (nz < z_min) { z_min = nz; }
242 if (nz > z_max) { z_max = nz; }
243 for (int m = n + 1; m < num_nodes_; m++) {
244 mx = node_coords[3 * m];
245 my = node_coords[3 * m + 1];
246 mz = node_coords[3 * m + 2];
247 distance_squared = (nx - mx) * (nx - mx) + (ny - my) * (ny - my) + (nz - mz) * (nz - mz);
248 if (distance_squared < min_distance_squared) { min_distance_squared = distance_squared; }
249 }
250 }
251 characteristic_length = std::sqrt(min_distance_squared);
252
253 double min_box_length = x_max - x_min;
254 if (y_max - y_min < min_box_length) { min_box_length = y_max - y_min; }
255 if (z_max - z_min < min_box_length) { min_box_length = z_max - z_min; }
256
257 if (min_box_length < characteristic_length) { characteristic_length = min_box_length; }
258
259 return characteristic_length;
260}

◆ ComputeConsistentMass_impl()

template<class ViewT>
void nimble::HexElement::ComputeConsistentMass_impl ( double density,
const ViewT node_reference_coords,
double consistent_mass_matrix[][num_nodes_] ) const
inlineprotected
272 {
273 double jac_det[num_int_pts_];
274 double rc1, rc2, rc3, sfd1, sfd2, sfd3;
275 for (int int_pt = 0; int_pt < num_int_pts_; int_pt++) {
276 // \sum_{i}^{N_{node}} x_{i} \frac{\partial N_{i} (\xi)}{\partial \xi}
277 double a[][dim_] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
278 double a_inv[][dim_] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
279
280 for (int n = 0; n < num_nodes_; n++) {
281 rc1 = node_reference_coords(n, 0);
282 rc2 = node_reference_coords(n, 1);
283 rc3 = node_reference_coords(n, 2);
284 sfd1 = shape_fcn_deriv_[24 * int_pt + dim_ * n];
285 sfd2 = shape_fcn_deriv_[24 * int_pt + dim_ * n + 1];
286 sfd3 = shape_fcn_deriv_[24 * int_pt + dim_ * n + 2];
287 a[0][0] += rc1 * sfd1;
288 a[0][1] += rc1 * sfd2;
289 a[0][2] += rc1 * sfd3;
290 a[1][0] += rc2 * sfd1;
291 a[1][1] += rc2 * sfd2;
292 a[1][2] += rc2 * sfd3;
293 a[2][0] += rc3 * sfd1;
294 a[2][1] += rc3 * sfd2;
295 a[2][2] += rc3 * sfd3;
296 }
297 jac_det[int_pt] = Invert3x3(a, a_inv);
298 }
299
300 for (int i = 0; i < num_nodes_; i++) {
301 for (int j = 0; j < num_nodes_; j++) {
302 consistent_mass_matrix[i][j] = 0.0;
303 for (int int_pt = 0; int_pt < num_int_pts_; int_pt++) {
304 consistent_mass_matrix[i][j] += int_wts_[int_pt] * density * shape_fcn_vals_[int_pt * num_nodes_ + i] *
305 shape_fcn_vals_[int_pt * num_nodes_ + j] * jac_det[int_pt];
306 }
307 }
308 }
309 }
NIMBLE_INLINE_FUNCTION double Invert3x3(const double mat[][3], double inv[][3])
Definition nimble_utils.h:1230

◆ ComputeDeformationGradients()

void nimble::HexElement::ComputeDeformationGradients ( const double * node_reference_coords,
const double * node_current_coords,
double * deformation_gradients ) const
overridevirtual

Function to compute the deformation gradients.

Parameters
[in]node_reference_coordsPointer to array of reference nodal coordinates
[in]node_current_coordsPointer to array of current nodal coordinates
[out]deformation_gradientsPointer to array of deformation gradients

Implements nimble::Element.

338{
339 nimble::Viewify<2, const double> node_reference_coords_v(node_reference_coords, {num_nodes_, dim_}, {dim_, 1});
340
341 std::vector<double> tmp_disp(num_nodes_ * dim_, 0.0);
342 for (size_t ii = 0; ii < tmp_disp.size(); ++ii)
343 tmp_disp[ii] = node_current_coords[ii] - node_reference_coords[ii];
344 nimble::Viewify<2, const double> node_disp(tmp_disp.data(), {num_nodes_, dim_}, {dim_, 1});
345
346 constexpr int dim2 = dim_ * dim_;
347 nimble::Viewify<2> deformation_gradients_v(deformation_gradients, {num_int_pts_, dim2}, {dim2, 1});
348
349 ComputeDeformationGradients_impl(node_reference_coords_v, node_disp,
350 deformation_gradients_v);
351}
NIMBLE_FUNCTION void ComputeDeformationGradients_impl(ConstViewT node_reference_coords, ConstViewT node_displacements, TensorViewT deformation_gradients) const
Definition nimble_element.h:432

◆ ComputeDeformationGradients_impl()

template<class ConstViewT, class TensorViewT>
NIMBLE_FUNCTION void nimble::HexElement::ComputeDeformationGradients_impl ( ConstViewT node_reference_coords,
ConstViewT node_displacements,
TensorViewT deformation_gradients ) const
inlineprotected
436 {
437 double rc1, rc2, rc3, cc1, cc2, cc3, sfd1, sfd2, sfd3;
438 double b_inv[][3] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
439 double def_grad[][3] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
440
441 // Loop over the integration points
442 for (int int_pt = 0; int_pt < 8; int_pt++) {
443 // \sum_{i}^{N_{node}} x_{i} \frac{\partial N_{i} (\xi)}{\partial \xi}
444 double a[][3] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
445
446 // \sum_{i}^{N_{node}} X_{i} \frac{\partial N_{i} (\xi)}{\partial \xi}
447 double b[][3] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
448
449 // Sum over the number of nodes
450 for (int j = 0; j < 8; j++) {
451 rc1 = node_reference_coords(j, 0);
452 rc2 = node_reference_coords(j, 1);
453 rc3 = node_reference_coords(j, 2);
454
455 cc1 = node_reference_coords(j, 0) + node_displacements(j, 0);
456 cc2 = node_reference_coords(j, 1) + node_displacements(j, 1);
457 cc3 = node_reference_coords(j, 2) + node_displacements(j, 2);
458
459 sfd1 = shape_fcn_deriv_[24 * int_pt + 3 * j];
460 sfd2 = shape_fcn_deriv_[24 * int_pt + 3 * j + 1];
461 sfd3 = shape_fcn_deriv_[24 * int_pt + 3 * j + 2];
462
463 a[0][0] += cc1 * sfd1;
464 a[0][1] += cc1 * sfd2;
465 a[0][2] += cc1 * sfd3;
466 a[1][0] += cc2 * sfd1;
467 a[1][1] += cc2 * sfd2;
468 a[1][2] += cc2 * sfd3;
469 a[2][0] += cc3 * sfd1;
470 a[2][1] += cc3 * sfd2;
471 a[2][2] += cc3 * sfd3;
472
473 b[0][0] += rc1 * sfd1;
474 b[0][1] += rc1 * sfd2;
475 b[0][2] += rc1 * sfd3;
476 b[1][0] += rc2 * sfd1;
477 b[1][1] += rc2 * sfd2;
478 b[1][2] += rc2 * sfd3;
479 b[2][0] += rc3 * sfd1;
480 b[2][1] += rc3 * sfd2;
481 b[2][2] += rc3 * sfd3;
482 }
483
484 Invert3x3(b, b_inv);
485
486 for (int j = 0; j < 3; j++) {
487 for (int k = 0; k < 3; k++) {
488 def_grad[j][k] = a[j][0] * b_inv[0][k] + a[j][1] * b_inv[1][k] + a[j][2] * b_inv[2][k];
489 }
490 }
491
492 deformation_gradients(int_pt, K_F_XX_) = def_grad[0][0];
493 deformation_gradients(int_pt, K_F_XY_) = def_grad[0][1];
494 deformation_gradients(int_pt, K_F_XZ_) = def_grad[0][2];
495 deformation_gradients(int_pt, K_F_YX_) = def_grad[1][0];
496 deformation_gradients(int_pt, K_F_YY_) = def_grad[1][1];
497 deformation_gradients(int_pt, K_F_YZ_) = def_grad[1][2];
498 deformation_gradients(int_pt, K_F_ZX_) = def_grad[2][0];
499 deformation_gradients(int_pt, K_F_ZY_) = def_grad[2][1];
500 deformation_gradients(int_pt, K_F_ZZ_) = def_grad[2][2];
501 }
502 }
const int K_F_XX_
Definition nimble_element.h:213
const int K_F_XY_
Definition nimble_element.h:216
const int K_F_XZ_
Definition nimble_element.h:221
const int K_F_ZY_
Definition nimble_element.h:220
const int K_F_ZX_
Definition nimble_element.h:218
const int K_F_YZ_
Definition nimble_element.h:217
const int K_F_YY_
Definition nimble_element.h:214
const int K_F_ZZ_
Definition nimble_element.h:215
const int K_F_YX_
Definition nimble_element.h:219

◆ ComputeLumpedMass()

void nimble::HexElement::ComputeLumpedMass ( double density,
const double * node_reference_coords,
double * lumped_mass ) const
overridevirtual

Compute the lumped mass.

Parameters
[in]densityMaterial density
[in]node_reference_coordsPointer to array of nodal reference coordinates
[out]lumped_massPointer to array of nodal lumped mass value

Implements nimble::Element.

175{
176 double consistent_mass_matrix[][num_nodes_] = {
177 {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
178 {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
179 {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
180 {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
181 {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
182 {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
183 {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
184 {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}};
185
186 nimble::Viewify<2, const double> view_node_reference_coords(node_reference_coords, {num_nodes_, dim_}, {dim_, 1});
187 ComputeConsistentMass_impl(density, view_node_reference_coords, consistent_mass_matrix);
188
189 for (int i = 0; i < num_nodes_; i++) {
190 lumped_mass[i] = 0.0;
191 for (int j = 0; j < num_nodes_; j++) { lumped_mass[i] += consistent_mass_matrix[i][j]; }
192 }
193}
void ComputeConsistentMass_impl(double density, const ViewT node_reference_coords, double consistent_mass_matrix[][num_nodes_]) const
Definition nimble_element.h:268

◆ ComputeNodalForces()

void nimble::HexElement::ComputeNodalForces ( const double * node_current_coords,
const double * int_pt_stresses,
double * node_forces )
overridevirtual

Virtual function to compute the nodal forces.

Parameters
[in]node_current_coordsPointer to array of current nodal coordinates
[in]int_pt_stressesPointer to array of stresses at integration points
[out]node_forcesPointer to array of forces

Implements nimble::Element.

459{
460 nimble::Viewify<2, const double> node_reference_coords(node_current_coords, {num_nodes_, dim_}, {dim_, 1});
461
462 std::vector<double> tmp_disp(num_nodes_ * dim_, 0.0);
463 nimble::Viewify<2, const double> node_disp(tmp_disp.data(), {num_nodes_, dim_}, {dim_, 1});
464
465 constexpr int sym_tensor_size = 6;
466 nimble::Viewify<2, const double> int_stresses_v(int_pt_stresses, {num_int_pts_, sym_tensor_size},
467 {sym_tensor_size, 1});
468
469 nimble::Viewify<2> node_forces_v(node_forces, {num_nodes_, dim_}, {dim_, 1});
470
471 ComputeNodalForces_impl(node_reference_coords, node_disp, int_stresses_v, node_forces_v);
472}
void ComputeNodalForces_impl(ConstViewT node_reference_coords, ConstViewT node_displacements, ViewTensorT int_pt_stresses, ViewT node_forces) const
Definition nimble_element.h:542

◆ ComputeNodalForces_impl()

template<class ConstViewT, class ViewTensorT, class ViewT>
void nimble::HexElement::ComputeNodalForces_impl ( ConstViewT node_reference_coords,
ConstViewT node_displacements,
ViewTensorT int_pt_stresses,
ViewT node_forces ) const
inlineprotected
547 {
548 double cc1, cc2, cc3, sfd1, sfd2, sfd3, dN_dx1, dN_dx2, dN_dx3, f1, f2, f3;
549 double jac_det;
550 double a_inv[][dim_] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
551 double force[][dim_] = {
552 {0.0, 0.0, 0.0},
553 {0.0, 0.0, 0.0},
554 {0.0, 0.0, 0.0},
555 {0.0, 0.0, 0.0},
556 {0.0, 0.0, 0.0},
557 {0.0, 0.0, 0.0},
558 {0.0, 0.0, 0.0},
559 {0.0, 0.0, 0.0}};
560 constexpr int dim_nodes = dim_ * num_nodes_;
561
562 for (int int_pt = 0; int_pt < num_int_pts_; int_pt++) {
563 // \sum_{i}^{N_{node}} x_{i} \frac{\partial N_{i} (\xi)}{\partial \xi}
564 double a[][dim_] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
565
566 for (int n = 0; n < num_nodes_; n++) {
567 cc1 = node_reference_coords(n, 0) + node_displacements(n, 0);
568 cc2 = node_reference_coords(n, 1) + node_displacements(n, 1);
569 cc3 = node_reference_coords(n, 2) + node_displacements(n, 2);
570 sfd1 = shape_fcn_deriv_[dim_nodes * int_pt + dim_ * n];
571 sfd2 = shape_fcn_deriv_[dim_nodes * int_pt + dim_ * n + 1];
572 sfd3 = shape_fcn_deriv_[dim_nodes * int_pt + dim_ * n + 2];
573 a[0][0] += cc1 * sfd1;
574 a[0][1] += cc1 * sfd2;
575 a[0][2] += cc1 * sfd3;
576 a[1][0] += cc2 * sfd1;
577 a[1][1] += cc2 * sfd2;
578 a[1][2] += cc2 * sfd3;
579 a[2][0] += cc3 * sfd1;
580 a[2][1] += cc3 * sfd2;
581 a[2][2] += cc3 * sfd3;
582 }
583
584 jac_det = Invert3x3(a, a_inv);
585
586 for (int node = 0; node < num_nodes_; node++) {
587 dN_dx1 = shape_fcn_deriv_[int_pt * dim_nodes + dim_ * node] * a_inv[0][0] +
588 shape_fcn_deriv_[int_pt * dim_nodes + dim_ * node + 1] * a_inv[1][0] +
589 shape_fcn_deriv_[int_pt * dim_nodes + dim_ * node + 2] * a_inv[2][0];
590
591 dN_dx2 = shape_fcn_deriv_[int_pt * dim_nodes + dim_ * node] * a_inv[0][1] +
592 shape_fcn_deriv_[int_pt * dim_nodes + dim_ * node + 1] * a_inv[1][1] +
593 shape_fcn_deriv_[int_pt * dim_nodes + dim_ * node + 2] * a_inv[2][1];
594
595 dN_dx3 = shape_fcn_deriv_[int_pt * dim_nodes + dim_ * node] * a_inv[0][2] +
596 shape_fcn_deriv_[int_pt * dim_nodes + dim_ * node + 1] * a_inv[1][2] +
597 shape_fcn_deriv_[int_pt * dim_nodes + dim_ * node + 2] * a_inv[2][2];
598
599 f1 = dN_dx1 * int_pt_stresses(int_pt, K_S_XX_) + dN_dx2 * int_pt_stresses(int_pt, K_S_YX_) +
600 dN_dx3 * int_pt_stresses(int_pt, K_S_ZX_);
601
602 f2 = dN_dx1 * int_pt_stresses(int_pt, K_S_XY_) + dN_dx2 * int_pt_stresses(int_pt, K_S_YY_) +
603 dN_dx3 * int_pt_stresses(int_pt, K_S_ZY_);
604
605 f3 = dN_dx1 * int_pt_stresses(int_pt, K_S_XZ_) + dN_dx2 * int_pt_stresses(int_pt, K_S_YZ_) +
606 dN_dx3 * int_pt_stresses(int_pt, K_S_ZZ_);
607
608 f1 *= jac_det * int_wts_[int_pt];
609 f2 *= jac_det * int_wts_[int_pt];
610 f3 *= jac_det * int_wts_[int_pt];
611
612 // profiling showed that calling the -= operator directly on the kokkos
613 // view is expensive
614 force[node][0] -= f1;
615 force[node][1] -= f2;
616 force[node][2] -= f3;
617 }
618 }
619
620 for (int node = 0; node < num_nodes_; node++) {
621 node_forces(node, 0) = force[node][0];
622 node_forces(node, 1) = force[node][1];
623 node_forces(node, 2) = force[node][2];
624 }
625 }
const int K_S_ZX_
Definition nimble_element.h:208
const int K_S_YZ_
Definition nimble_element.h:207
const int K_S_XZ_
Definition nimble_element.h:211
const int K_S_YY_
Definition nimble_element.h:204
const int K_S_XY_
Definition nimble_element.h:206
const int K_S_ZY_
Definition nimble_element.h:210
const int K_S_YX_
Definition nimble_element.h:209
const int K_S_ZZ_
Definition nimble_element.h:205
const int K_S_XX_
Definition nimble_element.h:203

◆ ComputeTangent()

void nimble::HexElement::ComputeTangent ( const double * node_current_coords,
const double * material_tangent,
double * element_tangent )
overridevirtual

Function to compute the tangent.

Parameters
[in]node_current_coordsPointer to array of current nodal coordinates
[in]material_tangentPointer to array of material tangent
[out]tangentPointer to array of tangent

Implements nimble::Element.

366{
367 double jac_det;
368 double cc1, cc2, cc3, sfd1, sfd2, sfd3;
369
370 for (int i = 0; i < 24; i++) {
371 for (int j = 0; j < 24; j++) { element_tangent[i * 24 + j] = 0.0; }
372 }
373
374 // \mathbf{K}_{elem} = \int_{\Omega_{o}} \mathbf{B}^{T}_{0} \mathbf{C}^{SE}
375 // \mathbf{B}_{o} \Omega_{o}
376
377 // dN1/dX 0 0 dN2/dX 0 0 ... dN8/dX 0 0
378 // 0 dN1/dY 0 0 dN2/dY 0 ... 0 dN8/dY 0
379 // 0 0 dN1/dZ 0 0 dN2/dZ ... 0 0
380 // dN8/dZ
381 // B = dN1/dY dN1/dX 0 dN2/dY dN2/dX 0 ... dN8/dY dN8/dX 0
382 // 0 dN1/dZ dN1/dY 0 dN2/dZ dN2/dY ... 0 dN8/dZ
383 // dN8/dY
384 // dN1/dZ 0 dN1/dX dN2/dZ 0 dN2/dX ... dN8/dZ 0
385 // dN8/dX
386
387 double B[6][24];
388 for (auto & B_i : B) {
389 for (double & B_ij : B_i) { B_ij = 0.0; }
390 }
391
392 for (int int_pt = 0; int_pt < num_int_pts_; int_pt++) {
393 // \mathbf{a} = \sum_{i}^{N_{node}} x_{i} \frac{\partial N_{i}
394 // (\xi)}{\partial \xi}
395 double a[][3] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
396 double a_inv[][3] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
397 double temp[6][24];
398 for (auto & t_i : temp) {
399 for (double & t_ij : t_i) { t_ij = 0.0; }
400 }
401
402 for (int n = 0; n < num_nodes_; n++) {
403 cc1 = node_current_coords[3 * n];
404 cc2 = node_current_coords[3 * n + 1];
405 cc3 = node_current_coords[3 * n + 2];
406 sfd1 = shape_fcn_deriv_[24 * int_pt + 3 * n];
407 sfd2 = shape_fcn_deriv_[24 * int_pt + 3 * n + 1];
408 sfd3 = shape_fcn_deriv_[24 * int_pt + 3 * n + 2];
409 a[0][0] += cc1 * sfd1;
410 a[0][1] += cc1 * sfd2;
411 a[0][2] += cc1 * sfd3;
412 a[1][0] += cc2 * sfd1;
413 a[1][1] += cc2 * sfd2;
414 a[1][2] += cc2 * sfd3;
415 a[2][0] += cc3 * sfd1;
416 a[2][1] += cc3 * sfd2;
417 a[2][2] += cc3 * sfd3;
418 }
419 jac_det = Invert3x3(a, a_inv);
420
421 // derivatives of shape function with respect to current coordinate
422 double dN_dcc1, dN_dcc2, dN_dcc3;
423 for (int n = 0; n < num_nodes_; n++) {
424 sfd1 = shape_fcn_deriv_[24 * int_pt + 3 * n];
425 sfd2 = shape_fcn_deriv_[24 * int_pt + 3 * n + 1];
426 sfd3 = shape_fcn_deriv_[24 * int_pt + 3 * n + 2];
427 dN_dcc1 = sfd1 * a_inv[0][0] + sfd2 * a_inv[1][0] + sfd3 * a_inv[2][0];
428 dN_dcc2 = sfd1 * a_inv[0][1] + sfd2 * a_inv[1][1] + sfd3 * a_inv[2][1];
429 dN_dcc3 = sfd1 * a_inv[0][2] + sfd2 * a_inv[1][2] + sfd3 * a_inv[2][2];
430 B[0][3 * n] = dN_dcc1;
431 B[1][3 * n + 1] = dN_dcc2;
432 B[2][3 * n + 2] = dN_dcc3;
433 B[3][3 * n] = dN_dcc2;
434 B[3][3 * n + 1] = dN_dcc1;
435 B[4][3 * n + 1] = dN_dcc3;
436 B[4][3 * n + 2] = dN_dcc2;
437 B[5][3 * n] = dN_dcc3;
438 B[5][3 * n + 2] = dN_dcc1;
439 }
440
441 for (int i = 0; i < 6; i++) {
442 for (int j = 0; j < 24; j++) {
443 for (int k = 0; k < 6; k++) { temp[i][j] += material_tangent[36 * int_pt + 6 * i + k] * B[k][j]; }
444 }
445 }
446
447 for (int i = 0; i < 24; i++) {
448 for (int j = 0; j < 24; j++) {
449 for (int k = 0; k < 6; k++) {
450 element_tangent[i * 24 + j] += B[k][i] * temp[k][j] * int_wts_[int_pt] * jac_det;
451 }
452 }
453 }
454 }
455}

◆ ComputeVolumeAverage()

void nimble::HexElement::ComputeVolumeAverage ( const double * node_current_coords,
int num_quantities,
const double * int_pt_quantities,
double & volume,
double * volume_averaged_quantity ) const
overridevirtual

Implements nimble::Element.

269{
270 nimble::Viewify<2, const double> node_reference_coords(node_current_coords, {num_nodes_, dim_}, {dim_, 1});
271
272 std::vector<double> tmp_disp(num_nodes_ * dim_, 0.0);
273 nimble::Viewify<2, const double> node_disp(tmp_disp.data(), {num_nodes_, dim_}, {dim_, 1});
274
275 nimble::Viewify<2, const double> int_pt_quantities_v(int_pt_quantities, {num_int_pts_, num_quantities},
276 {num_quantities, 1});
277
278 nimble::Viewify<1> vol_ave_quantity(volume_averaged_quantities, num_quantities);
279
280 ComputeVolumeAverageQuantities_impl(node_reference_coords, node_disp, int_pt_quantities_v,
281 vol_ave_quantity, num_quantities, volume);
282}
void ComputeVolumeAverageQuantities_impl(ConstViewVec node_reference_coords, ConstViewVec node_displacements, ConstViewTensor int_pt_quantities, ViewTensor vol_ave_quantity, int num_quantities, double &volume) const
Definition nimble_element.h:345

◆ ComputeVolumeAverageQuantities_impl()

template<class ConstViewVec, class ConstViewTensor, class ViewTensor>
void nimble::HexElement::ComputeVolumeAverageQuantities_impl ( ConstViewVec node_reference_coords,
ConstViewVec node_displacements,
ConstViewTensor int_pt_quantities,
ViewTensor vol_ave_quantity,
int num_quantities,
double & volume ) const
inlineprotected
352 {
353 double cc1, cc2, cc3, sfd1, sfd2, sfd3;
354 double jac_det;
355 double a_inv[][dim_] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
356
357 std::vector<double> vol_ave(num_quantities, 0);
358 volume = 0.0;
359
360 for (int int_pt = 0; int_pt < num_int_pts_; int_pt++) {
361 // \sum_{i}^{N_{node}} x_{i} \frac{\partial N_{i} (\xi)}{\partial \xi}
362 double a[][dim_] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
363
364 for (int n = 0; n < num_nodes_; n++) {
365 cc1 = node_reference_coords(n, 0) + node_displacements(n, 0);
366 cc2 = node_reference_coords(n, 1) + node_displacements(n, 1);
367 cc3 = node_reference_coords(n, 2) + node_displacements(n, 2);
368 sfd1 = shape_fcn_deriv_[24 * int_pt + dim_ * n];
369 sfd2 = shape_fcn_deriv_[24 * int_pt + dim_ * n + 1];
370 sfd3 = shape_fcn_deriv_[24 * int_pt + dim_ * n + 2];
371 a[0][0] += cc1 * sfd1;
372 a[0][1] += cc1 * sfd2;
373 a[0][2] += cc1 * sfd3;
374 a[1][0] += cc2 * sfd1;
375 a[1][1] += cc2 * sfd2;
376 a[1][2] += cc2 * sfd3;
377 a[2][0] += cc3 * sfd1;
378 a[2][1] += cc3 * sfd2;
379 a[2][2] += cc3 * sfd3;
380 }
381 jac_det = Invert3x3(a, a_inv);
382 volume += jac_det;
383 for (int i = 0; i < num_quantities; ++i) {
384 vol_ave[i] += int_pt_quantities(int_pt, i) * int_wts_[int_pt] * jac_det;
385 }
386 }
387
388 for (int i = 0; i < num_quantities; ++i) {
389 vol_ave[i] /= volume;
390 vol_ave_quantity(i) = vol_ave[i];
391 }
392 }

◆ Dim()

int nimble::HexElement::Dim ( ) const
inlineoverridevirtual

Returns the spatial dimension.

Returns
Spatial dimension (3 for the hexahedral element)

Implements nimble::Element.

245 {
246 return dim_;
247 }

◆ NumIntegrationPointsPerElement()

int nimble::HexElement::NumIntegrationPointsPerElement ( ) const
inlineoverridevirtual

Returns the number of integration points per element.

Returns
Number of integration points per element (8 for the Q1 hexahedral element)

Implements nimble::Element.

261 {
262 return num_int_pts_;
263 }

◆ NumNodesPerElement()

int nimble::HexElement::NumNodesPerElement ( ) const
inlineoverridevirtual

Returns the number of nodes per element.

Returns
Number of nodes per element (8 for the Q1 hexahedral element)

Implements nimble::Element.

253 {
254 return num_nodes_;
255 }

◆ ShapeFunctionDerivatives()

void nimble::HexElement::ShapeFunctionDerivatives ( const double * natural_coords,
double * shape_function_derivatives )
protected
126{
127 double r, s, t;
128 constexpr double c = 1.0 / 8.0;
129
130 // Loop over the integration points
131 for (int int_pt = 0; int_pt < num_int_pts_; int_pt++) {
132 // Natural coordinates of this integration point
133 r = natural_coords[dim_ * int_pt];
134 s = natural_coords[dim_ * int_pt + 1];
135 t = natural_coords[dim_ * int_pt + 2];
136
137 // Derivative of each of the eight shape functions w.r.t. the natural
138 // coordinates at this integration point shape function 1
139 shape_function_derivatives[24 * int_pt] = -c * (1.0 - s) * (1.0 - t);
140 shape_function_derivatives[24 * int_pt + 1] = -c * (1.0 - r) * (1.0 - t);
141 shape_function_derivatives[24 * int_pt + 2] = -c * (1.0 - r) * (1.0 - s);
142 // shape function 2
143 shape_function_derivatives[24 * int_pt + 3] = c * (1.0 - s) * (1.0 - t);
144 shape_function_derivatives[24 * int_pt + 4] = -c * (1.0 + r) * (1.0 - t);
145 shape_function_derivatives[24 * int_pt + 5] = -c * (1.0 + r) * (1.0 - s);
146 // shape function 3
147 shape_function_derivatives[24 * int_pt + 6] = c * (1.0 + s) * (1.0 - t);
148 shape_function_derivatives[24 * int_pt + 7] = c * (1.0 + r) * (1.0 - t);
149 shape_function_derivatives[24 * int_pt + 8] = -c * (1.0 + r) * (1.0 + s);
150 // shape function 4
151 shape_function_derivatives[24 * int_pt + 9] = -c * (1.0 + s) * (1.0 - t);
152 shape_function_derivatives[24 * int_pt + 10] = c * (1.0 - r) * (1.0 - t);
153 shape_function_derivatives[24 * int_pt + 11] = -c * (1.0 - r) * (1.0 + s);
154 // shape function 5
155 shape_function_derivatives[24 * int_pt + 12] = -c * (1.0 - s) * (1.0 + t);
156 shape_function_derivatives[24 * int_pt + 13] = -c * (1.0 - r) * (1.0 + t);
157 shape_function_derivatives[24 * int_pt + 14] = c * (1.0 - r) * (1.0 - s);
158 // shape function 6
159 shape_function_derivatives[24 * int_pt + 15] = c * (1.0 - s) * (1.0 + t);
160 shape_function_derivatives[24 * int_pt + 16] = -c * (1.0 + r) * (1.0 + t);
161 shape_function_derivatives[24 * int_pt + 17] = c * (1.0 + r) * (1.0 - s);
162 // shape function 7
163 shape_function_derivatives[24 * int_pt + 18] = c * (1.0 + s) * (1.0 + t);
164 shape_function_derivatives[24 * int_pt + 19] = c * (1.0 + r) * (1.0 + t);
165 shape_function_derivatives[24 * int_pt + 20] = c * (1.0 + r) * (1.0 + s);
166 // shape function 8
167 shape_function_derivatives[24 * int_pt + 21] = -c * (1.0 + s) * (1.0 + t);
168 shape_function_derivatives[24 * int_pt + 22] = c * (1.0 - r) * (1.0 + t);
169 shape_function_derivatives[24 * int_pt + 23] = c * (1.0 - r) * (1.0 + s);
170 }
171}

◆ ShapeFunctionValues()

void nimble::HexElement::ShapeFunctionValues ( const double * natural_coords,
double * shape_function_values )
protected
101{
102 double r, s, t;
103 constexpr double c = 1.0 / 8.0;
104
105 // Loop over the integration points
106 for (int i = 0; i < num_int_pts_; i++) {
107 // Natural coordinates of this integration point
108 r = natural_coords[dim_ * i];
109 s = natural_coords[dim_ * i + 1];
110 t = natural_coords[dim_ * i + 2];
111
112 // Value of each of the eight shape functions at this integration point
113 shape_function_values[8 * i] = c * (1.0 - r) * (1.0 - s) * (1.0 - t);
114 shape_function_values[8 * i + 1] = c * (1.0 + r) * (1.0 - s) * (1.0 - t);
115 shape_function_values[8 * i + 2] = c * (1.0 + r) * (1.0 + s) * (1.0 - t);
116 shape_function_values[8 * i + 3] = c * (1.0 - r) * (1.0 + s) * (1.0 - t);
117 shape_function_values[8 * i + 4] = c * (1.0 - r) * (1.0 - s) * (1.0 + t);
118 shape_function_values[8 * i + 5] = c * (1.0 + r) * (1.0 - s) * (1.0 + t);
119 shape_function_values[8 * i + 6] = c * (1.0 + r) * (1.0 + s) * (1.0 + t);
120 shape_function_values[8 * i + 7] = c * (1.0 - r) * (1.0 + s) * (1.0 + t);
121 }
122}

The documentation for this class was generated from the following files: