44#ifndef NIMBLE_ELEMENT_H
45#define NIMBLE_ELEMENT_H
88 ComputeLumpedMass(
double density,
const double* node_reference_coords,
double* lumped_mass)
const = 0;
90#ifdef NIMBLE_HAVE_KOKKOS
113 const double* node_current_coords,
115 const double* int_pt_quantities,
117 double* volume_averaged_quantity)
const = 0;
119#ifdef NIMBLE_HAVE_KOKKOS
130 ComputeVolumeAverageSymTensor(
138 ComputeVolumeAverageFullTensor(
152 const double* node_reference_coords,
153 const double* node_current_coords,
154 double* deformation_gradients)
const = 0;
156#ifdef NIMBLE_HAVE_KOKKOS
176 ComputeTangent(
const double* node_reference_coords,
const double* material_tangent,
double* tangent) = 0;
184 ComputeNodalForces(
const double* node_current_coords,
const double* int_pt_stresses,
double* node_forces) = 0;
186#ifdef NIMBLE_HAVE_KOKKOS
228 static constexpr int dim_ = 3;
229 static constexpr int num_nodes_ = 8;
230 static constexpr int num_int_pts_ = 8;
266 template <
class ViewT>
270 const ViewT node_reference_coords,
271 double consistent_mass_matrix[][num_nodes_])
const
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++) {
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}};
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;
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];
318 ComputeLumpedMass(
double density,
const double* node_reference_coords,
double* lumped_mass)
const override;
320#ifdef NIMBLE_HAVE_KOKKOS
343 template <
class ConstViewVec,
class ConstViewTensor,
class ViewTensor>
346 ConstViewVec node_reference_coords,
347 ConstViewVec node_displacements,
348 ConstViewTensor int_pt_quantities,
349 ViewTensor vol_ave_quantity,
351 double &volume)
const
353 double cc1, cc2, cc3, sfd1, sfd2, sfd3;
355 double a_inv[][dim_] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
357 std::vector<double> vol_ave(num_quantities, 0);
360 for (
int int_pt = 0; int_pt < num_int_pts_; int_pt++) {
362 double a[][dim_] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
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;
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;
388 for (
int i = 0; i < num_quantities; ++i) {
389 vol_ave[i] /= volume;
390 vol_ave_quantity(i) = vol_ave[i];
397 const double* node_current_coords,
399 const double* int_pt_quantities,
401 double* volume_averaged_quantity)
const override;
403#ifdef NIMBLE_HAVE_KOKKOS
414 ComputeVolumeAverageSymTensor(
422 ComputeVolumeAverageFullTensor(
430 template <
class ConstViewT,
class TensorViewT>
433 ConstViewT node_reference_coords,
434 ConstViewT node_displacements,
435 TensorViewT deformation_gradients)
const
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}};
442 for (
int int_pt = 0; int_pt < 8; int_pt++) {
444 double a[][3] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
447 double b[][3] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
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);
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);
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];
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;
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;
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];
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];
513 const double* node_reference_coords,
514 const double* node_current_coords,
515 double* deformation_gradients)
const override;
517#ifdef NIMBLE_HAVE_KOKKOS
537 ComputeTangent(
const double* node_current_coords,
const double* material_tangent,
double* element_tangent)
override;
540 template <
class ConstViewT,
class ViewTensorT,
class ViewT>
543 ConstViewT node_reference_coords,
544 ConstViewT node_displacements,
545 ViewTensorT int_pt_stresses,
546 ViewT node_forces)
const
548 double cc1, cc2, cc3, sfd1, sfd2, sfd3, dN_dx1, dN_dx2, dN_dx3, f1, f2, f3;
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_] = {
560 constexpr int dim_nodes = dim_ * num_nodes_;
562 for (
int int_pt = 0; int_pt < num_int_pts_; int_pt++) {
564 double a[][dim_] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
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;
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];
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];
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];
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_);
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_);
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_);
608 f1 *= jac_det * int_wts_[int_pt];
609 f2 *= jac_det * int_wts_[int_pt];
610 f3 *= jac_det * int_wts_[int_pt];
614 force[node][0] -= f1;
615 force[node][1] -= f2;
616 force[node][2] -= f3;
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];
635 ComputeNodalForces(
const double* node_current_coords,
const double* int_pt_stresses,
double* node_forces)
override;
637#ifdef NIMBLE_HAVE_KOKKOS
666 double int_pts_[num_int_pts_ * dim_]{};
667 double int_wts_[num_int_pts_]{};
668 double shape_fcn_vals_[num_nodes_ * num_int_pts_]{};
669 double shape_fcn_deriv_[num_nodes_ * num_int_pts_ * dim_]{};
virtual void ComputeLumpedMass(double density, const double *node_reference_coords, double *lumped_mass) const =0
Virtual function to compute the lumped mass.
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_F_XX_
Definition nimble_element.h:213
virtual double ComputeCharacteristicLength(const double *node_coords)=0
Virtual function to compute the characteristic length.
const int K_S_ZY_
Definition nimble_element.h:210
virtual void ComputeNodalForces(const double *node_current_coords, const double *int_pt_stresses, double *node_forces)=0
Virtual function to compute the nodal forces.
const int K_F_XY_
Definition nimble_element.h:216
const int K_F_XZ_
Definition nimble_element.h:221
virtual void ComputeDeformationGradients(const double *node_reference_coords, const double *node_current_coords, double *deformation_gradients) const =0
Virtual function to compute the deformation gradients.
virtual int Dim() const =0
Virtual function returning the spatial dimension.
virtual int NumIntegrationPointsPerElement() const =0
Virtual function returning the number of integration points per element.
virtual void ComputeVolumeAverage(const double *node_current_coords, int num_quantities, const double *int_pt_quantities, double &volume, double *volume_averaged_quantity) const =0
const int K_F_ZY_
Definition nimble_element.h:220
const int K_F_ZX_
Definition nimble_element.h:218
virtual void ComputeTangent(const double *node_reference_coords, const double *material_tangent, double *tangent)=0
Virtual function to compute the tangent.
const int K_S_YX_
Definition nimble_element.h:209
virtual NIMBLE_FUNCTION ~Element()=default
Default virtual destructor.
const int K_F_YZ_
Definition nimble_element.h:217
virtual int NumNodesPerElement() const =0
Virtual function returning the number of nodes in the element.
const int K_F_YY_
Definition nimble_element.h:214
NIMBLE_FUNCTION Element()=default
Default constructor.
const int K_F_ZZ_
Definition nimble_element.h:215
const int K_F_YX_
Definition nimble_element.h:219
const int K_S_ZZ_
Definition nimble_element.h:205
const int K_S_XX_
Definition nimble_element.h:203
double ComputeCharacteristicLength(const double *node_coords) override
Function to compute the characteristic length.
Definition nimble_element.cc:222
NIMBLE_FUNCTION ~HexElement() override=default
Default destructor.
NIMBLE_FUNCTION void ComputeDeformationGradients_impl(ConstViewT node_reference_coords, ConstViewT node_displacements, TensorViewT deformation_gradients) const
Definition nimble_element.h:432
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
void ComputeTangent(const double *node_current_coords, const double *material_tangent, double *element_tangent) override
Function to compute the tangent.
Definition nimble_element.cc:365
void ComputeNodalForces_impl(ConstViewT node_reference_coords, ConstViewT node_displacements, ViewTensorT int_pt_stresses, ViewT node_forces) const
Definition nimble_element.h:542
void ComputeNodalForces(const double *node_current_coords, const double *int_pt_stresses, double *node_forces) override
Virtual function to compute the nodal forces.
Definition nimble_element.cc:458
NIMBLE_FUNCTION void ShapeFunctionDerivatives(const double *natural_coords, double *shape_function_derivatives)
Definition nimble_element.cc:125
void ComputeLumpedMass(double density, const double *node_reference_coords, double *lumped_mass) const override
Compute the lumped mass.
Definition nimble_element.cc:174
void ComputeVolumeAverage(const double *node_current_coords, int num_quantities, const double *int_pt_quantities, double &volume, double *volume_averaged_quantity) const override
Definition nimble_element.cc:263
int Dim() const override
Returns the spatial dimension.
Definition nimble_element.h:244
void ComputeConsistentMass_impl(double density, const ViewT node_reference_coords, double consistent_mass_matrix[][num_nodes_]) const
Definition nimble_element.h:268
int NumIntegrationPointsPerElement() const override
Returns the number of integration points per element.
Definition nimble_element.h:260
void ComputeDeformationGradients(const double *node_reference_coords, const double *node_current_coords, double *deformation_gradients) const override
Function to compute the deformation gradients.
Definition nimble_element.cc:334
NIMBLE_FUNCTION HexElement()
Default constructor.
Definition nimble_element.cc:55
NIMBLE_FUNCTION void ShapeFunctionValues(const double *natural_coords, double *shape_function_values)
Definition nimble_element.cc:100
int NumNodesPerElement() const override
Returns the number of nodes per element.
Definition nimble_element.h:252
Field< FieldType::DeviceScalarElem >::SingleEntryView DeviceScalarElemSingleEntryView
Definition nimble_kokkos_defs.h:601
Field< FieldType::DeviceFullTensorIntPt >::SubView DeviceFullTensorIntPtSubView
Definition nimble_kokkos_defs.h:589
Field< FieldType::DeviceSymTensorElem >::SingleEntryView DeviceSymTensorElemSingleEntryView
Definition nimble_kokkos_defs.h:605
Field< FieldType::DeviceFullTensorElem >::SingleEntryView DeviceFullTensorElemSingleEntryView
Definition nimble_kokkos_defs.h:603
Field< FieldType::DeviceVectorNode >::GatheredSubView DeviceVectorNodeGatheredSubView
Definition nimble_kokkos_defs.h:587
Field< FieldType::DeviceScalarNode >::GatheredSubView DeviceScalarNodeGatheredSubView
Definition nimble_kokkos_defs.h:584
Field< FieldType::DeviceSymTensorIntPt >::SubView DeviceSymTensorIntPtSubView
Definition nimble_kokkos_defs.h:592
Definition kokkos_contact_manager.h:49
#define NIMBLE_FUNCTION
Definition nimble_defs.h:49
NIMBLE_INLINE_FUNCTION double Invert3x3(const double mat[][3], double inv[][3])
Definition nimble_utils.h:1230