NimbleSM
NimbleSM is a solid mechanics simulation code for dynamic systems
Loading...
Searching...
No Matches
nimble_element.h
Go to the documentation of this file.
1/*
2//@HEADER
3// ************************************************************************
4//
5// NimbleSM
6// Copyright 2018
7// National Technology & Engineering Solutions of Sandia, LLC (NTESS)
8//
9// Under the terms of Contract DE-NA0003525 with NTESS, the U.S. Government
10// retains certain rights in this software.
11//
12// Redistribution and use in source and binary forms, with or without
13// modification, are permitted provided that the following conditions are
14// met:
15//
16// 1. Redistributions of source code must retain the above copyright
17// notice, this list of conditions and the following disclaimer.
18//
19// 2. Redistributions in binary form must reproduce the above copyright
20// notice, this list of conditions and the following disclaimer in the
21// documentation and/or other materials provided with the distribution.
22//
23// 3. Neither the name of the Corporation nor the names of the
24// contributors may be used to endorse or promote products derived from
25// this software without specific prior written permission.
26//
27// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY EXPRESS OR IMPLIED
28// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
29// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
30// NO EVENT SHALL NTESS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
32// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37//
38// Questions? Contact David Littlewood (djlittl@sandia.gov)
39//
40// ************************************************************************
41//@HEADER
42*/
43
44#ifndef NIMBLE_ELEMENT_H
45#define NIMBLE_ELEMENT_H
46
47#include "nimble_defs.h"
48#include "nimble_macros.h"
49#include "nimble_utils.h"
50
51#include <vector>
52
53namespace nimble {
54
55/// \brief Abstract class for representing an element
57{
58 public:
59 /// \brief Default constructor
61 Element() = default;
62
63 /// \brief Default virtual destructor
65 virtual ~Element() = default;
66
67 /// \brief Virtual function returning the spatial dimension
68 /// \return Spatial dimension
69 virtual int
70 Dim() const = 0;
71
72 /// \brief Virtual function returning the number of nodes in the element
73 /// \return Number of nodes in the element
74 virtual int
75 NumNodesPerElement() const = 0;
76
77 /// \brief Virtual function returning the number of integration points per element
78 /// \return Number of integration points per element
79 virtual int
81
82 /// \brief Virtual function to compute the lumped mass
83 ///
84 /// \param[in] density Material density
85 /// \param[in] node_reference_coords Pointer to array of nodal reference coordinates
86 /// \param[out] lumped_mass Pointer to array of nodal lumped mass value
87 virtual void
88 ComputeLumpedMass(double density, const double* node_reference_coords, double* lumped_mass) const = 0;
89
90#ifdef NIMBLE_HAVE_KOKKOS
91 /// \brief Virtual function to compute the lumped mass
92 ///
93 /// \param[in] density Material density
94 /// \param[in] node_reference_coords Pointer to array of nodal reference coordinates
95 /// \param[out] lumped_mass Pointer to array of nodal lumped mass value
97 virtual void
99 double density,
102#endif
103
104 /// \brief Virtual function to compute the characteristic length
105 ///
106 /// \param[in] node_coords Pointer to array of nodal coordinates
107 /// \return Characteristic length
108 virtual double
109 ComputeCharacteristicLength(const double* node_coords) = 0;
110
111 virtual void
113 const double* node_current_coords,
114 int num_quantities,
115 const double* int_pt_quantities,
116 double& volume,
117 double* volume_averaged_quantity) const = 0;
118
119#ifdef NIMBLE_HAVE_KOKKOS
120
122 virtual void
123 ComputeVolume(
127
129 virtual void
130 ComputeVolumeAverageSymTensor(
134 nimble_kokkos::DeviceSymTensorElemSingleEntryView vol_ave_quantity) const = 0;
135
137 virtual void
138 ComputeVolumeAverageFullTensor(
142 nimble_kokkos::DeviceFullTensorElemSingleEntryView vol_ave_quantity) const = 0;
143#endif
144
145 /// \brief Virtual function to compute the deformation gradients
146 ///
147 /// \param[in] node_reference_coords Pointer to array of reference nodal coordinates
148 /// \param[in] node_current_coords Pointer to array of current nodal coordinates
149 /// \param[out] deformation_gradients Pointer to array of deformation gradients
150 virtual void
152 const double* node_reference_coords,
153 const double* node_current_coords,
154 double* deformation_gradients) const = 0;
155
156#ifdef NIMBLE_HAVE_KOKKOS
157 /// \brief Virtual function to compute the deformation gradients
158 ///
159 /// \param[in] node_reference_coords Kokkos view of reference nodal coordinates
160 /// \param[in] node_displacements Kokkos view of nodal displacements
161 /// \param[out] deformation_gradients Kokkos view of deformation gradients
163 virtual void
167 nimble_kokkos::DeviceFullTensorIntPtSubView deformation_gradients) const = 0;
168#endif
169
170 /// \brief Virtual function to compute the tangent
171 ///
172 /// \param[in] node_current_coords Pointer to array of current nodal coordinates
173 /// \param[in] material_tangent Pointer to array of material tangent
174 /// \param[out] tangent Pointer to array of tangent
175 virtual void
176 ComputeTangent(const double* node_reference_coords, const double* material_tangent, double* tangent) = 0;
177
178 /// \brief Virtual function to compute the nodal forces
179 ///
180 /// \param[in] node_current_coords Pointer to array of current nodal coordinates
181 /// \param[in] int_pt_stresses Pointer to array of stresses at integration points
182 /// \param[out] node_forces Pointer to array of forces
183 virtual void
184 ComputeNodalForces(const double* node_current_coords, const double* int_pt_stresses, double* node_forces) = 0;
185
186#ifdef NIMBLE_HAVE_KOKKOS
187 /// \brief Virtual function to compute the nodal forces
188 ///
189 /// \param[in] node_reference_coords Kokkos view of reference nodal coordinates
190 /// \param[in] node_displacements Kokkos view of nodal displacements
191 /// \param[in] int_pt_stresses Kokkos view of stress at integration points
192 /// \param[out] node_forces Kokkos view of nodal forces
194 virtual void
200#endif
201
202 protected:
203 const int K_S_XX_ = 0;
204 const int K_S_YY_ = 1;
205 const int K_S_ZZ_ = 2;
206 const int K_S_XY_ = 3;
207 const int K_S_YZ_ = 4;
208 const int K_S_ZX_ = 5;
209 const int K_S_YX_ = 3;
210 const int K_S_ZY_ = 4;
211 const int K_S_XZ_ = 5;
212
213 const int K_F_XX_ = 0;
214 const int K_F_YY_ = 1;
215 const int K_F_ZZ_ = 2;
216 const int K_F_XY_ = 3;
217 const int K_F_YZ_ = 4;
218 const int K_F_ZX_ = 5;
219 const int K_F_YX_ = 6;
220 const int K_F_ZY_ = 7;
221 const int K_F_XZ_ = 8;
222};
223
224/// \brief Class for an 8-node hexahedral element
225class HexElement : public Element
226{
227 private:
228 static constexpr int dim_ = 3;
229 static constexpr int num_nodes_ = 8;
230 static constexpr int num_int_pts_ = 8;
231
232 public:
233 /// \brief Default constructor
235 HexElement();
236
237 /// \brief Default destructor
239 ~HexElement() override = default;
240
241 /// \brief Returns the spatial dimension
242 /// \return Spatial dimension (3 for the hexahedral element)
243 int
244 Dim() const override
245 {
246 return dim_;
247 }
248
249 /// \brief Returns the number of nodes per element
250 /// \return Number of nodes per element (8 for the Q1 hexahedral element)
251 int
252 NumNodesPerElement() const override
253 {
254 return num_nodes_;
255 }
256
257 /// \brief Returns the number of integration points per element
258 /// \return Number of integration points per element (8 for the Q1 hexahedral element)
259 int
261 {
262 return num_int_pts_;
263 }
264
265 protected:
266 template <class ViewT>
267 void
269 double density,
270 const ViewT node_reference_coords,
271 double consistent_mass_matrix[][num_nodes_]) const
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 }
310
311 public:
312 /// \brief Compute the lumped mass
313 ///
314 /// \param[in] density Material density
315 /// \param[in] node_reference_coords Pointer to array of nodal reference coordinates
316 /// \param[out] lumped_mass Pointer to array of nodal lumped mass value
317 void
318 ComputeLumpedMass(double density, const double* node_reference_coords, double* lumped_mass) const override;
319
320#ifdef NIMBLE_HAVE_KOKKOS
321 /// \brief Compute the lumped mass when using Kokkos objects
322 ///
323 /// \param[in] density Material density
324 /// \param[in] node_reference_coords Pointer to array of nodal reference coordinates
325 /// \param[out] lumped_mass Pointer to array of nodal lumped mass value
327 void
329 double density,
331 nimble_kokkos::DeviceScalarNodeGatheredSubView lumped_mass) const override;
332#endif
333
334 /// \brief Function to compute the characteristic length
335 ///
336 /// \param[in] node_coords Pointer to array of nodal coordinates
337 /// \return Characteristic length
338 double
339 ComputeCharacteristicLength(const double* node_coords) override;
340
341 protected:
342
343 template <class ConstViewVec, class ConstViewTensor, class ViewTensor>
344 void
346 ConstViewVec node_reference_coords,
347 ConstViewVec node_displacements,
348 ConstViewTensor int_pt_quantities,
349 ViewTensor vol_ave_quantity,
350 int num_quantities,
351 double &volume) const
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 }
393
394 public:
395 void
397 const double* node_current_coords,
398 int num_quantities,
399 const double* int_pt_quantities,
400 double& volume,
401 double* volume_averaged_quantity) const override;
402
403#ifdef NIMBLE_HAVE_KOKKOS
404
406 void
407 ComputeVolume(
410 nimble_kokkos::DeviceScalarElemSingleEntryView elem_volume) const override;
411
413 void
414 ComputeVolumeAverageSymTensor(
418 nimble_kokkos::DeviceSymTensorElemSingleEntryView vol_ave_quantity) const override;
419
421 void
422 ComputeVolumeAverageFullTensor(
426 nimble_kokkos::DeviceFullTensorElemSingleEntryView vol_ave_quantity) const override;
427#endif
428
429 protected:
430 template <class ConstViewT, class TensorViewT>
431 NIMBLE_FUNCTION void
433 ConstViewT node_reference_coords,
434 ConstViewT node_displacements,
435 TensorViewT deformation_gradients) const
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 }
503
504 public:
505
506 /// \brief Function to compute the deformation gradients
507 ///
508 /// \param[in] node_reference_coords Pointer to array of reference nodal coordinates
509 /// \param[in] node_current_coords Pointer to array of current nodal coordinates
510 /// \param[out] deformation_gradients Pointer to array of deformation gradients
511 void
513 const double* node_reference_coords,
514 const double* node_current_coords,
515 double* deformation_gradients) const override;
516
517#ifdef NIMBLE_HAVE_KOKKOS
518 /// \brief Function to compute the deformation gradients
519 ///
520 /// \param[in] node_reference_coords Kokkos view of reference nodal coordinates
521 /// \param[in] node_displacements Kokkos view of current nodal coordinates
522 /// \param[out] deformation_gradients Kokkos view of deformation gradients
524 void
528 nimble_kokkos::DeviceFullTensorIntPtSubView deformation_gradients) const override;
529#endif
530
531 /// \brief Function to compute the tangent
532 ///
533 /// \param[in] node_current_coords Pointer to array of current nodal coordinates
534 /// \param[in] material_tangent Pointer to array of material tangent
535 /// \param[out] tangent Pointer to array of tangent
536 void
537 ComputeTangent(const double* node_current_coords, const double* material_tangent, double* element_tangent) override;
538
539 protected:
540 template <class ConstViewT, class ViewTensorT, class ViewT>
541 void
543 ConstViewT node_reference_coords,
544 ConstViewT node_displacements,
545 ViewTensorT int_pt_stresses,
546 ViewT node_forces) const
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 }
626
627 public:
628
629 /// \brief Virtual function to compute the nodal forces
630 ///
631 /// \param[in] node_current_coords Pointer to array of current nodal coordinates
632 /// \param[in] int_pt_stresses Pointer to array of stresses at integration points
633 /// \param[out] node_forces Pointer to array of forces
634 void
635 ComputeNodalForces(const double* node_current_coords, const double* int_pt_stresses, double* node_forces) override;
636
637#ifdef NIMBLE_HAVE_KOKKOS
638 /// \brief Function to compute the nodal forces
639 ///
640 /// \param[in] node_reference_coords Kokkos view of reference nodal coordinates
641 /// \param[in] node_displacements Kokkos view of nodal displacements
642 /// \param[in] int_pt_stresses Kokkos view of stress at integration points
643 /// \param[out] node_forces Kokkos view of nodal forces
645 void
650 nimble_kokkos::DeviceVectorNodeGatheredSubView node_forces) const override
651 {
652 ComputeNodalForces_impl(node_reference_coords, node_displacements, int_pt_stresses, node_forces);
653 }
654#endif
655
656 protected:
658 void
659 ShapeFunctionValues(const double* natural_coords, double* shape_function_values);
660
662 void
663 ShapeFunctionDerivatives(const double* natural_coords, double* shape_function_derivatives);
664
665 private:
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_]{};
670};
671
672} // namespace nimble
673
674#endif // NIMBLE_ELEMENT_H
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