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

#include <nimble_block.h>

Inheritance diagram for nimble::Block:
nimble::BlockBase

Public Member Functions

 Block ()
 
 ~Block () override=default
 
void Initialize (std::string const &model_material_parameters, MaterialFactory &factory)
 
void InstantiateMaterialModel (MaterialFactory &factory)
 
void InstantiateElement () override
 
void GetDataLabelsAndLengths (std::vector< std::pair< std::string, Length > > &data_labels_and_lengths)
 
void ComputeLumpedMassMatrix (const double *const reference_coordinates, int num_elem, const int *const elem_conn, double *lumped_mass) const
 
void InitializeElementData (int num_elem_in_block, std::vector< int > const &elem_global_ids_in_block, std::vector< std::string > const &elem_data_labels, std::vector< std::string > const &derived_elem_data_labels, std::vector< double > &elem_data_n, std::vector< double > &elem_data_np1, MaterialFactory &material_factory, DataManager &data_manager)
 
void ComputeInternalForce (const double *reference_coordinates, const double *displacement, const double *velocity, double *internal_force, double time_previous, double time_current, int num_elem, const int *elem_conn, const int *elem_global_ids, std::vector< std::string > const &elem_data_labels, std::vector< double > const &elem_data_n, std::vector< double > &elem_data_np1, DataManager &data_manager, bool is_output_step, bool compute_stress_only=false) const
 
void ComputeDerivedElementData (const double *const reference_coordinates, const double *const displacement, int num_elem, const int *const elem_conn, int num_elem_data, std::vector< double > const &elem_data_np1, int num_derived_elem_data, std::vector< std::vector< double > > &derived_elem_data)
 
- Public Member Functions inherited from nimble::BlockBase
 BlockBase ()=default
 
virtual ~BlockBase ()=default
 
double GetDensity () const
 
double GetBulkModulus () const
 
double GetShearModulus () const
 
std::shared_ptr< MaterialGetMaterialPointer () const
 
std::shared_ptr< ElementGetElementPointer () const
 
virtual double ComputeCriticalTimeStep (const nimble::Viewify< 2 > &node_reference_coordinates, const nimble::Viewify< 2 > &node_displacements, int num_elem, const int *elem_conn) const
 
template<typename MatT>
void ComputeTangentStiffnessMatrix (int num_global_unknowns, const double *const reference_coordinates, const double *const displacement, int num_elem, const int *const elem_conn, const int *const global_node_ids, MatT &tangent_stiffness) const
 

Protected Member Functions

void DetermineDataOffsets (std::vector< std::string > const &elem_data_labels, std::vector< std::string > const &derived_elem_data_labels)
 

Protected Attributes

std::vector< int > def_grad_offset_
 
std::vector< int > stress_offset_
 
std::vector< int > state_data_offset_
 
int vol_ave_volume_offset_
 
std::vector< int > vol_ave_offsets_
 
std::map< int, int > vol_ave_index_to_derived_data_index_
 
- Protected Attributes inherited from nimble::BlockBase
std::string model_material_parameters_ = "none"
 
std::shared_ptr< Elementelement_ = nullptr
 
std::shared_ptr< Materialmaterial_ = nullptr
 

Constructor & Destructor Documentation

◆ Block()

nimble::Block::Block ( )
inline
BlockBase()=default
int vol_ave_volume_offset_
Definition nimble_block.h:164

◆ ~Block()

nimble::Block::~Block ( )
overridedefault

Member Function Documentation

◆ ComputeDerivedElementData()

void nimble::Block::ComputeDerivedElementData ( const double *const reference_coordinates,
const double *const displacement,
int num_elem,
const int *const elem_conn,
int num_elem_data,
std::vector< double > const & elem_data_np1,
int num_derived_elem_data,
std::vector< std::vector< double > > & derived_elem_data )
448{
449 // Currently supported derived element data are:
450 // 1) Element volume
451 // 2) Volume-averaged element data
452
453 if (num_derived_elem_data == 0) { return; }
454 if (derived_elem_data.size() != num_derived_elem_data) { derived_elem_data.resize(num_derived_elem_data); }
455 for (auto& vec : derived_elem_data) {
456 if (vec.size() != num_elem) { vec.resize(num_elem); }
457 }
458
459 int dim = element_->Dim();
460 int vector_size = LengthToInt(VECTOR, dim);
461 int num_node_per_elem = element_->NumNodesPerElement();
462 int num_int_pt_per_elem = element_->NumIntegrationPointsPerElement();
463 int num_data_per_int_pt = num_elem_data / num_int_pt_per_elem;
464
465 // Containers that will be passed to an individual element to compute element
466 // volume and volume-averaged quantities
467 double cur_coord[vector_size * num_node_per_elem];
468 unsigned int num_vol_ave_data = vol_ave_offsets_.size() / num_int_pt_per_elem;
469 double int_pt_quantities[num_vol_ave_data * num_int_pt_per_elem];
470 double volume;
471 double vol_ave_quantities[num_vol_ave_data];
472
473 // Loop over each element and compute element volume and volume-averaged
474 // quantities
475 for (int i_elem = 0; i_elem < num_elem; i_elem++) {
476 // Load per element data containers
477 for (int node = 0; node < num_node_per_elem; node++) {
478 int node_id = elem_conn[i_elem * num_node_per_elem + node];
479 for (int i = 0; i < vector_size; i++) {
480 cur_coord[node * vector_size + i] =
481 reference_coordinates[vector_size * node_id + i] + displacement[vector_size * node_id + i];
482 }
483 }
484 for (int i = 0; i < num_vol_ave_data * num_int_pt_per_elem; ++i) {
485 int_pt_quantities[i] = elem_data_np1[i_elem * num_data_per_int_pt * num_int_pt_per_elem + vol_ave_offsets_.at(i)];
486 }
487
488 // Compute element volume and volume-averaged quantities
489 element_->ComputeVolumeAverage(cur_coord, num_vol_ave_data, &int_pt_quantities[0], volume, vol_ave_quantities);
490
491 // Copy the results into the global containers for derived data
492 for (int i = 0; i < num_vol_ave_data; i++) {
493 derived_elem_data.at(vol_ave_index_to_derived_data_index_[i]).at(i_elem) = vol_ave_quantities[i];
494 }
495 if (vol_ave_volume_offset_ != -1) { derived_elem_data.at(vol_ave_volume_offset_).at(i_elem) = volume; }
496 }
497}
std::shared_ptr< Element > element_
Definition nimble_block_base.h:117
std::map< int, int > vol_ave_index_to_derived_data_index_
Definition nimble_block.h:166
std::vector< int > vol_ave_offsets_
Definition nimble_block.h:165
@ VECTOR
Definition nimble_data_utils.h:89
int LengthToInt(Length length, int dim)
Definition nimble_data_utils.cc:57

◆ ComputeInternalForce()

void nimble::Block::ComputeInternalForce ( const double * reference_coordinates,
const double * displacement,
const double * velocity,
double * internal_force,
double time_previous,
double time_current,
int num_elem,
const int * elem_conn,
const int * elem_global_ids,
std::vector< std::string > const & elem_data_labels,
std::vector< double > const & elem_data_n,
std::vector< double > & elem_data_np1,
DataManager & data_manager,
bool is_output_step,
bool compute_stress_only = false ) const
405{
406 double* elem_data_np1_ptr = elem_data_np1.data();
407 int num_element_data = static_cast<int>(elem_data_labels.size());
408
409 ComputeInternalForceFunctor functor(
410 element_,
411 material_,
415 reference_coordinates,
416 displacement,
417 velocity,
418 internal_force,
419 time_previous,
420 time_current,
421 num_elem,
422 elem_conn,
423 elem_global_ids,
424 num_element_data,
425 &elem_data_n[0],
426 elem_data_np1_ptr,
427 data_manager,
428 is_output_step,
429 compute_stress_only);
430
431#ifdef NIMBLE_HAVE_KOKKOS
432 Kokkos::parallel_for(num_elem, functor);
433#else
434 for (int elem = 0; elem < num_elem; elem++) { functor(elem); } // for (int elem = 0; elem < num_elem; elem++)
435#endif
436}
std::shared_ptr< Material > material_
Definition nimble_block_base.h:118
std::vector< int > def_grad_offset_
Definition nimble_block.h:161
std::vector< int > stress_offset_
Definition nimble_block.h:162
std::vector< int > state_data_offset_
Definition nimble_block.h:163

◆ ComputeLumpedMassMatrix()

void nimble::Block::ComputeLumpedMassMatrix ( const double *const reference_coordinates,
int num_elem,
const int *const elem_conn,
double * lumped_mass ) const
116{
117 int dim = element_->Dim();
118 int num_node_per_elem = element_->NumNodesPerElement();
119 double density = GetDensity();
120
121 int vector_size = 0;
122 if (dim == 2) {
123 vector_size = 2;
124 } else if (dim == 3) {
125 vector_size = 3;
126 }
127
128 double ref_coord[vector_size * num_node_per_elem];
129 double mass[num_node_per_elem];
130
131 for (int elem = 0; elem < num_elem; elem++) {
132 for (int node = 0; node < num_node_per_elem; node++) {
133 int node_id = elem_conn[elem * num_node_per_elem + node];
134 for (int i = 0; i < vector_size; i++) {
135 ref_coord[node * vector_size + i] = reference_coordinates[vector_size * node_id + i];
136 }
137 }
138
139 element_->ComputeLumpedMass(density, ref_coord, mass);
140
141 for (int node = 0; node < num_node_per_elem; node++) {
142 int node_id = elem_conn[elem * num_node_per_elem + node];
143 lumped_mass[node_id] += mass[node];
144 }
145 }
146}
double GetDensity() const
Definition nimble_block_base.h:68

◆ DetermineDataOffsets()

void nimble::Block::DetermineDataOffsets ( std::vector< std::string > const & elem_data_labels,
std::vector< std::string > const & derived_elem_data_labels )
protected
503{
504 int dim = element_->Dim();
505 int num_int_pt_per_elem = element_->NumIntegrationPointsPerElement();
506 int num_data_per_element = static_cast<int>(elem_data_labels.size());
507 int num_data_per_int_pt = num_data_per_element / num_int_pt_per_elem;
508 int full_tensor_size = LengthToInt(FULL_TENSOR, dim);
509 int sym_tensor_size = LengthToInt(SYMMETRIC_TENSOR, dim);
510
511 // Determine the offset for the derformation gradient in the element data
512 // container
513 def_grad_offset_.clear();
514 for (int i_ipt = 0; i_ipt < num_int_pt_per_elem; i_ipt++) {
515 for (int i_component = 0; i_component < full_tensor_size; i_component++) {
516 std::string def_grad_label = GetComponentLabel("deformation_gradient", FULL_TENSOR, dim, i_component, i_ipt + 1);
517 for (unsigned int i_label = 0; i_label < num_data_per_element; i_label++) {
518 if (elem_data_labels.at(i_label) == def_grad_label) { def_grad_offset_.push_back(i_label); }
519 }
520 }
521 }
522
523 NIMBLE_ASSERT(def_grad_offset_.size() == full_tensor_size * num_int_pt_per_elem,
524 "\nError in Block::ComputeInternalForce(), failed to index def_grad "
525 "into global data.\n");
526
527 // Determine the offset for the stress in the element data container
528 stress_offset_.clear();
529 for (int i_ipt = 0; i_ipt < num_int_pt_per_elem; i_ipt++) {
530 for (int i_component = 0; i_component < sym_tensor_size; i_component++) {
531 std::string stress_label = GetComponentLabel("stress", SYMMETRIC_TENSOR, dim, i_component, i_ipt + 1);
532 for (unsigned int i_label = 0; i_label < num_data_per_element; i_label++) {
533 if (elem_data_labels.at(i_label) == stress_label) { stress_offset_.push_back(i_label); }
534 }
535 }
536 }
537
538 NIMBLE_ASSERT(stress_offset_.size() == sym_tensor_size * num_int_pt_per_elem,
539 "\nError in Block::ComputeInternalForce(), failed to index stress into "
540 "global data.\n");
541
542 // Determine the offset for the state data in the element data container
543 int num_state_data = material_->NumStateVariables();
544 std::vector<std::string> state_data_labels(num_state_data);
545 for (int i = 0; i < num_state_data; ++i) {
547 material_->GetStateVariableLabel(i, label);
548 state_data_labels[i] = label;
549 }
550 state_data_offset_.clear();
551 for (int i_ipt = 0; i_ipt < num_int_pt_per_elem; i_ipt++) {
552 for (int i_state_data = 0; i_state_data < num_state_data; i_state_data++) {
553 std::string raw_label = state_data_labels.at(i_state_data);
554 std::string state_data_label = GetComponentLabel(raw_label, SCALAR, dim, 0, i_ipt + 1);
555 for (unsigned int i_label = 0; i_label < num_data_per_element; i_label++) {
556 if (elem_data_labels.at(i_label) == state_data_label) { state_data_offset_.push_back(i_label); }
557 }
558 }
559 }
560
561 NIMBLE_ASSERT(state_data_offset_.size() == num_state_data * num_int_pt_per_elem,
562 "\nError in Block::ComputeInternalForce(), failed to index state data "
563 "into global data.\n");
564
565 // Determine which requested derived data are volume-averaged data
566 // and set up some bookkeeping
567 std::vector<std::string> vol_ave_labels;
569 for (unsigned int i_derived_data = 0; i_derived_data < derived_elem_data_labels.size(); i_derived_data++) {
570 std::string const& label = derived_elem_data_labels[i_derived_data];
571 if (label == "volume") {
572 vol_ave_volume_offset_ = i_derived_data;
573 } else {
574 vol_ave_index_to_derived_data_index_[vol_ave_labels.size()] = i_derived_data;
575 vol_ave_labels.push_back(label);
576 }
577 }
578 unsigned int num_vol_ave_data = vol_ave_labels.size();
579 vol_ave_offsets_.resize(num_vol_ave_data * num_int_pt_per_elem);
580 // Bookkeeping to allow for loading the per element containers
581 for (unsigned int i_vol_ave_label = 0; i_vol_ave_label < num_vol_ave_data; ++i_vol_ave_label) {
582 std::string const& vol_ave_label = vol_ave_labels[i_vol_ave_label];
583 for (unsigned int i_elem_data_label = 0; i_elem_data_label < num_data_per_int_pt; ++i_elem_data_label) {
584 std::string const& elem_data_label = RemoveIntegrationPointPrefix(elem_data_labels[i_elem_data_label]);
585 if (vol_ave_label == elem_data_label) {
586 for (int i_int_pt = 0; i_int_pt < num_int_pt_per_elem; ++i_int_pt) {
587 vol_ave_offsets_[i_vol_ave_label + i_int_pt * num_vol_ave_data] =
588 i_elem_data_label + i_int_pt * num_data_per_int_pt;
589 }
590 }
591 }
592 }
593}
static const int MAX_MAT_MODEL_STR_LEN
Definition nimble_material.h:65
std::string RemoveIntegrationPointPrefix(std::string label)
Definition nimble_data_utils.cc:99
@ SCALAR
Definition nimble_data_utils.h:88
@ SYMMETRIC_TENSOR
Definition nimble_data_utils.h:90
@ FULL_TENSOR
Definition nimble_data_utils.h:91
std::string GetComponentLabel(std::string label, Length length, int dim, int component_index, int ipt)
Definition nimble_data_utils.cc:210
#define NIMBLE_ASSERT(...)
Definition nimble_macros.h:85

◆ GetDataLabelsAndLengths()

void nimble::Block::GetDataLabelsAndLengths ( std::vector< std::pair< std::string, Length > > & data_labels_and_lengths)
86{
87 int num_int_pts = element_->NumIntegrationPointsPerElement();
88 std::vector<std::pair<std::string, Length>> mat_model_data_labels_and_lengths;
89 // kinematic data
90 mat_model_data_labels_and_lengths.push_back(std::pair<std::string, Length>("deformation_gradient", FULL_TENSOR));
91 mat_model_data_labels_and_lengths.push_back(std::pair<std::string, Length>("stress", SYMMETRIC_TENSOR));
92 // material state data
93 int num_data = material_->NumStateVariables();
95 for (int i = 0; i < num_data; ++i) {
96 material_->GetStateVariableLabel(i, label);
97 mat_model_data_labels_and_lengths.push_back(std::pair<std::string, Length>(label, SCALAR));
98 }
99 for (int i_ipt = 0; i_ipt < num_int_pts; i_ipt++) {
100 for (unsigned int i_label = 0; i_label < mat_model_data_labels_and_lengths.size(); i_label++) {
101 std::string material_label = mat_model_data_labels_and_lengths[i_label].first;
102 Length length = mat_model_data_labels_and_lengths[i_label].second;
103 std::string label = AddIntegrationPointPrefix(material_label, i_ipt + 1);
104 std::pair<std::string, Length> label_and_length(label, length);
105 data_labels_and_lengths.push_back(label_and_length);
106 }
107 }
108}
Length
Definition nimble_data_utils.h:66
std::string AddIntegrationPointPrefix(std::string label, int ipt_number)
Definition nimble_data_utils.cc:85

◆ Initialize()

void nimble::Block::Initialize ( std::string const & model_material_parameters,
MaterialFactory & factory )
60{
61 model_material_parameters_ = model_material_parameters;
64}
std::string model_material_parameters_
Definition nimble_block_base.h:116
void InstantiateMaterialModel(MaterialFactory &factory)
Definition nimble_block.cc:67
void InstantiateElement() override
Definition nimble_block.cc:79

◆ InitializeElementData()

void nimble::Block::InitializeElementData ( int num_elem_in_block,
std::vector< int > const & elem_global_ids_in_block,
std::vector< std::string > const & elem_data_labels,
std::vector< std::string > const & derived_elem_data_labels,
std::vector< double > & elem_data_n,
std::vector< double > & elem_data_np1,
MaterialFactory & material_factory,
DataManager & data_manager )
158{
159 int num_int_pts = element_->NumIntegrationPointsPerElement();
160#ifndef NIMBLE_HAVE_KOKKOS
161 for (int i_elem = 0; i_elem < num_elem_in_block; ++i_elem) {
162 int elem_global_id = elem_global_ids_in_block.at(i_elem);
163 }
164#endif
165
166 unsigned int stride = elem_data_labels.size();
167
168 std::map<std::string, double> state_variable_initial_values;
170 for (int i = 0; i < material_->NumStateVariables(); ++i) {
171 material_->GetStateVariableLabel(i, label);
172 double state_variable_initial_value = material_->GetStateVariableInitialValue(i);
173 std::string state_variable_label(label);
174 state_variable_initial_values[state_variable_label] = state_variable_initial_value;
175 }
176
177 for (unsigned int i_variable = 0; i_variable < elem_data_labels.size(); i_variable++) {
178 std::string label = elem_data_labels[i_variable];
179 std::string ipt_label = RemoveIntegrationPointPrefix(label);
180
181 double initial_value = 0.0;
182 auto it = state_variable_initial_values.find(label);
183 if (it != state_variable_initial_values.end()) { initial_value = it->second; }
184
185 for (int i_elem = 0; i_elem < num_elem_in_block; ++i_elem) {
186 // override the material's intial values for the special cases
187 // of global element id and integration point number
188 if (ipt_label == "global_elem_id") {
189 int elem_global_id = elem_global_ids_in_block.at(i_elem);
190 initial_value = elem_global_id;
191 } else if (ipt_label == "ipt_id") {
192 int integration_point_id = static_cast<double>(LabelToIntegrationPointNumber(label));
193 initial_value = integration_point_id;
194 } else if (
195 ipt_label == "deformation_gradient_xx" || ipt_label == "deformation_gradient_yy" ||
196 ipt_label == "deformation_gradient_zz") {
197 initial_value = 1.0;
198 }
199
200 int index = i_elem * stride + i_variable;
201 elem_data_n[index] = initial_value;
202 elem_data_np1[index] = initial_value;
203 }
204 }
205
206 DetermineDataOffsets(elem_data_labels, derived_elem_data_labels);
207}
void DetermineDataOffsets(std::vector< std::string > const &elem_data_labels, std::vector< std::string > const &derived_elem_data_labels)
Definition nimble_block.cc:500
int LabelToIntegrationPointNumber(std::string label)
Definition nimble_data_utils.cc:132

◆ InstantiateElement()

void nimble::Block::InstantiateElement ( )
overridevirtual

Implements nimble::BlockBase.

80{
81 element_ = std::make_shared<HexElement>();
82}

◆ InstantiateMaterialModel()

void nimble::Block::InstantiateMaterialModel ( MaterialFactory & factory)
68{
69 if (model_material_parameters_ != "none") {
70 factory.parse_and_create(model_material_parameters_);
71 material_ = factory.get_material();
72 } else {
73 NIMBLE_ABORT("\nError in Block::InstantiateMaterialModel(), invalid material "
74 "parameters\n");
75 }
76}
#define NIMBLE_ABORT(...)
Definition nimble_macros.h:87

Member Data Documentation

◆ def_grad_offset_

std::vector<int> nimble::Block::def_grad_offset_
protected

◆ state_data_offset_

std::vector<int> nimble::Block::state_data_offset_
protected

◆ stress_offset_

std::vector<int> nimble::Block::stress_offset_
protected

◆ vol_ave_index_to_derived_data_index_

std::map<int, int> nimble::Block::vol_ave_index_to_derived_data_index_
protected

◆ vol_ave_offsets_

std::vector<int> nimble::Block::vol_ave_offsets_
protected

◆ vol_ave_volume_offset_

int nimble::Block::vol_ave_volume_offset_
protected

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