oomph::VolumeCoupledElement< ELEMENT > Class Template Reference

#include <VCoupledElement.h>

+ Inheritance diagram for oomph::VolumeCoupledElement< ELEMENT >:

Public Member Functions

 VolumeCoupledElement ()
 Constructor: Call constructor of underlying element. More...
 
 ~VolumeCoupledElement ()
 Destructor (empty) More...
 
void fill_in_contribution_to_residuals (Vector< double > &residuals) override
 Add the element's contribution to its residual vector (wrapper) More...
 
void fill_in_contribution_to_jacobian (Vector< double > &residuals, DenseMatrix< double > &jacobian) override
 Add the element's contribution to its residual vector and Jacobian matrix (wrapper) More...
 
void set_nodal_coupling_residual (Vector< Vector< double > > &cResidual)
 
doubleget_nodal_coupling_residual (const unsigned &l, const unsigned &i)
 
void set_nodal_coupling_jacobian (Vector< Vector< double > > &cJacobian)
 
doubleget_nodal_coupling_jacobian (const unsigned &l, const unsigned &ll)
 
void setCouplingStiffness (Vector< Vector< double > > &cStiffness)
 
doublegetCouplingStiffness (const unsigned &m, const unsigned &l)
 
void get_momentum_and_energy (double &mass, Vector< double > &lin_mo, Vector< double > &ang_mo, double &pot_en, double &kin_en)
 

Private Member Functions

void fill_in_generic_contribution_to_residuals_pvd (Vector< double > &residuals, DenseMatrix< double > &jacobian, const unsigned &flag) override
 
void add_internal_coupling_forces_to_residuals (Vector< double > &residuals, DenseMatrix< double > &jacobian, const unsigned &flag)
 Add the point source contribution to the residual vector. More...
 
void output (std::ostream &outfile, const unsigned &n_plot) override
 

Private Attributes

Vector< Vector< double > > nodal_coupling_residual
 Nodal coupling forces. More...
 
Vector< Vector< double > > nodal_coupling_jacobian
 Nodal coupling jacobian. More...
 
Vector< Vector< double > > couplingStiffness
 Coupling stiffness to discrete particles (FIXME: should be moved into DPMVCoupledElement) More...
 

Detailed Description

template<class ELEMENT>
class oomph::VolumeCoupledElement< ELEMENT >

Wrapper class for solid elements to be coupled with discrete solid particles over a partially overlapped volume

Constructor & Destructor Documentation

◆ VolumeCoupledElement()

template<class ELEMENT >
oomph::VolumeCoupledElement< ELEMENT >::VolumeCoupledElement ( )
inline

Constructor: Call constructor of underlying element.

35  {};

◆ ~VolumeCoupledElement()

template<class ELEMENT >
oomph::VolumeCoupledElement< ELEMENT >::~VolumeCoupledElement ( )
inline

Destructor (empty)

39  {};

Member Function Documentation

◆ add_internal_coupling_forces_to_residuals()

template<class ELEMENT >
void oomph::VolumeCoupledElement< ELEMENT >::add_internal_coupling_forces_to_residuals ( Vector< double > &  residuals,
DenseMatrix< double > &  jacobian,
const unsigned flag 
)
inlineprivate

Add the point source contribution to the residual vector.

603  {
604  // No further action if no coupling forces
605  if (nodal_coupling_residual.size() == 0) return;
606 
607  // Find out how many nodes there are
608  const unsigned n_node = this->nnode();
609  const unsigned DIM = this->dim();
610 
611  // Find out how many positional dofs there are
612  unsigned n_position_type = this->nnodal_position_type();
613 
614  // Set up memory for the shape/test functions
615  Shape psi(n_node);
616 
617  // Loop over all nodes belonging to the element
618  int local_eqn = 0;
619  // Loop over the nodes of the element
620  for (unsigned l = 0; l < n_node; l++)
621  {
622  // Loop of types of dofs
623  for (unsigned k = 0; k < n_position_type; k++)
624  {
625  // Loop over the force components
626  for (unsigned i = 0; i < DIM; i++)
627  {
628  // Get the local equation
629  local_eqn = this->position_local_eqn(l, k, i);
630  // IF it's not a boundary condition and the interpolated force is nonzero
631  if (local_eqn >= 0)
632  {
633  // add the nodal coupling residual to the global residual vector
634  residuals[local_eqn] += nodal_coupling_residual[l][i];
635  }
636  // Get Jacobian too?
637  if (flag == 1)
638  {
639  // No further action if no coupling forces
640  if (nodal_coupling_jacobian.size() == 0) continue;
641 
642  // Loop over the nodes of the element again
643  for (unsigned ll = 0; ll < n_node; ll++)
644  {
645  // Loop of types of dofs again
646  for (unsigned kk = 0; kk < n_position_type; kk++)
647  {
648  // Loop over the force components again
649  for (unsigned ii = 0; ii < DIM; ii++)
650  {
651  // Get the number of the unknown
652  int local_unknown = this->position_local_eqn(ll, kk, ii);
653  // IF it's not a boundary condition
654  if (( local_unknown >= 0 ) && ( i == ii ) && ( local_unknown >= local_eqn ))
655  {
656  // add the nodal coupling jacobian to the global jacobian matrix
657  jacobian(local_eqn, local_unknown) += nodal_coupling_jacobian[l][ll];
658  if (local_eqn != local_unknown)
659  {
660  jacobian(local_unknown, local_eqn) += nodal_coupling_jacobian[l][ll];
661  }
662  }
663  }
664  }
665  }
666  }
667  }
668  }
669  }
670  }
int i
Definition: BiCGSTAB_step_by_step.cpp:9
Vector< Vector< double > > nodal_coupling_residual
Nodal coupling forces.
Definition: VCoupledElement.h:736
Vector< Vector< double > > nodal_coupling_jacobian
Nodal coupling jacobian.
Definition: VCoupledElement.h:739
char char char int int * k
Definition: level2_impl.h:374
#define DIM
Definition: linearised_navier_stokes_elements.h:44

References DIM, i, k, oomph::VolumeCoupledElement< ELEMENT >::nodal_coupling_jacobian, and oomph::VolumeCoupledElement< ELEMENT >::nodal_coupling_residual.

Referenced by oomph::VolumeCoupledElement< ELEMENT >::fill_in_contribution_to_jacobian(), and oomph::VolumeCoupledElement< ELEMENT >::fill_in_contribution_to_residuals().

◆ fill_in_contribution_to_jacobian()

template<class ELEMENT >
void oomph::VolumeCoupledElement< ELEMENT >::fill_in_contribution_to_jacobian ( Vector< double > &  residuals,
DenseMatrix< double > &  jacobian 
)
inlineoverride

Add the element's contribution to its residual vector and Jacobian matrix (wrapper)

53  {
54  //Call the generic routine with the flag set to 1
55  fill_in_generic_contribution_to_residuals_pvd(residuals, jacobian, 1);
56 
57  // Add nodal coupling force to the residuals
58  add_internal_coupling_forces_to_residuals(residuals, jacobian, 1);
59  }
void add_internal_coupling_forces_to_residuals(Vector< double > &residuals, DenseMatrix< double > &jacobian, const unsigned &flag)
Add the point source contribution to the residual vector.
Definition: VCoupledElement.h:600
void fill_in_generic_contribution_to_residuals_pvd(Vector< double > &residuals, DenseMatrix< double > &jacobian, const unsigned &flag) override
Definition: VCoupledElement.h:217

References oomph::VolumeCoupledElement< ELEMENT >::add_internal_coupling_forces_to_residuals(), and oomph::VolumeCoupledElement< ELEMENT >::fill_in_generic_contribution_to_residuals_pvd().

◆ fill_in_contribution_to_residuals()

template<class ELEMENT >
void oomph::VolumeCoupledElement< ELEMENT >::fill_in_contribution_to_residuals ( Vector< double > &  residuals)
inlineoverride

Add the element's contribution to its residual vector (wrapper)

43  {
44  // Call the generic residuals function with flag set to 0 using a dummy matrix argument
46 
47  // Add nodal coupling force to the residuals
49  }
static DenseMatrix< double > Dummy_matrix
Definition: elements.h:227

References oomph::VolumeCoupledElement< ELEMENT >::add_internal_coupling_forces_to_residuals(), oomph::GeneralisedElement::Dummy_matrix, and oomph::VolumeCoupledElement< ELEMENT >::fill_in_generic_contribution_to_residuals_pvd().

◆ fill_in_generic_contribution_to_residuals_pvd()

template<class ELEMENT >
void oomph::VolumeCoupledElement< ELEMENT >::fill_in_generic_contribution_to_residuals_pvd ( Vector< double > &  residuals,
DenseMatrix< double > &  jacobian,
const unsigned flag 
)
inlineoverrideprivate
220  {
221 
222  // Get problem dimension
223  const unsigned DIM = this->dim();
224 
225  // Simply set up initial condition?
226  if (this->Solid_ic_pt != 0)
227  {
228  this->fill_in_residuals_for_solid_ic(residuals);
229  return;
230  }
231 
232  //Find out how many nodes there are
233  const unsigned n_node = this->nnode();
234 
235  //Find out how many positional dofs there are
236  const unsigned n_position_type = this->nnodal_position_type();
237 
238  //Set up memory for the shape functions
239  Shape psi(n_node, n_position_type);
240  DShape dpsidxi(n_node, n_position_type, DIM);
241 
242  //Set the value of Nintpt -- the number of integration points
243  const unsigned n_intpt = this->integral_pt()->nweight();
244 
245  //Set the vector to hold the local coordinates in the element
246  Vector<double> s(DIM);
247 
248  // Timescale ratio (non-dim density)
249  double lambda_sq = this->lambda_sq();
250 
251  // Time factor
252  double time_factor = 0.0;
253  if (lambda_sq > 0)
254  {
255  time_factor = this->node_pt(0)->position_time_stepper_pt()->weight(2, 0);
256  }
257 
258  //Integer to store the local equation number
259  int local_eqn = 0;
260 
261  //Loop over the integration points
262  for (unsigned ipt = 0; ipt < n_intpt; ipt++)
263  {
264  //Assign the values of s
265  for (unsigned i = 0; i < DIM; ++i)
266  { s[i] = this->integral_pt()->knot(ipt, i); }
267 
268  //Get the integral weight
269  double w = this->integral_pt()->weight(ipt);
270 
271  //Call the derivatives of the shape functions (and get Jacobian)
272  double J = this->dshape_lagrangian_at_knot(ipt, psi, dpsidxi);
273 
274  //Get the coupling weight at the integration point
275  double coupling_w = 0;
276  for (unsigned l = 0; l < n_node; l++)
277  {
278  double nodal_coupling_w = dynamic_cast<CoupledSolidNode*>(this->node_pt(l))->get_coupling_weight();
279  double psi_ = psi(l);
280  coupling_w += psi_ * nodal_coupling_w;
281  }
282 
283  //Calculate interpolated values of the derivative of global position
284  //wrt lagrangian coordinates
285  DenseMatrix<double> interpolated_G(DIM);
286 
287  // Setup memory for accelerations
288  Vector<double> accel(DIM);
289 
290  //Initialise to zero
291  for (unsigned i = 0; i < DIM; i++)
292  {
293  // Initialise acclerations
294  accel[i] = 0.0;
295  for (unsigned j = 0; j < DIM; j++)
296  {
297  interpolated_G(i, j) = 0.0;
298  }
299  }
300 
301  //Storage for Lagrangian coordinates (initialised to zero)
302  Vector<double> interpolated_xi(DIM, 0.0);
303 
304  //Calculate displacements and derivatives and lagrangian coordinates
305  for (unsigned l = 0; l < n_node; l++)
306  {
307  //Loop over positional dofs
308  for (unsigned k = 0; k < n_position_type; k++)
309  {
310  double psi_ = psi(l, k);
311  //Loop over displacement components (deformed position)
312  for (unsigned i = 0; i < DIM; i++)
313  {
314  //Calculate the Lagrangian coordinates and the accelerations
315  interpolated_xi[i] += this->lagrangian_position_gen(l, k, i) * psi_;
316 
317  // Only compute accelerations if inertia is switched on
318  if (( lambda_sq > 0.0 ) && ( this->Unsteady ))
319  {
320  accel[i] += this->dnodal_position_gen_dt(2, l, k, i) * psi_;
321  }
322 
323  //Loop over derivative directions
324  for (unsigned j = 0; j < DIM; j++)
325  {
326  interpolated_G(j, i) +=
327  this->nodal_position_gen(l, k, i) * dpsidxi(l, k, j);
328  }
329  }
330  }
331  }
332 
333  //Get isotropic growth factor
334  double gamma = 1.0;
335  this->get_isotropic_growth(ipt, s, interpolated_xi, gamma);
336 
337 
338  //Get body force at current time
339  Vector<double> b(DIM);
340  this->body_force(interpolated_xi, b);
341 
342  // We use Cartesian coordinates as the reference coordinate
343  // system. In this case the undeformed metric tensor is always
344  // the identity matrix -- stretched by the isotropic growth
345  double diag_entry = pow(gamma, 2.0 / double(DIM));
347  for (unsigned i = 0; i < DIM; i++)
348  {
349  for (unsigned j = 0; j < DIM; j++)
350  {
351  if (i == j)
352  { g(i, j) = diag_entry; }
353  else
354  { g(i, j) = 0.0; }
355  }
356  }
357 
358  //Premultiply the undeformed volume ratio (from the isotropic
359  // growth), the integral weights, the coupling weights, and the Jacobian
360  double W = gamma * w * ( 1.0 - coupling_w ) * J;
361 
362  //Declare and calculate the deformed metric tensor
364 
365  //Assign values of G
366  for (unsigned i = 0; i < DIM; i++)
367  {
368  //Do upper half of matrix
369  for (unsigned j = i; j < DIM; j++)
370  {
371  //Initialise G(i,j) to zero
372  G(i, j) = 0.0;
373  //Now calculate the dot product
374  for (unsigned k = 0; k < DIM; k++)
375  {
376  G(i, j) += interpolated_G(i, k) * interpolated_G(j, k);
377  }
378  }
379  //Matrix is symmetric so just copy lower half
380  for (unsigned j = 0; j < i; j++)
381  {
382  G(i, j) = G(j, i);
383  }
384  }
385 
386  //Now calculate the stress tensor from the constitutive law
388  ELEMENT::get_stress(g, G, sigma);
389 
390  // Add pre-stress
391  for (unsigned i = 0; i < DIM; i++)
392  {
393  for (unsigned j = 0; j < DIM; j++)
394  {
395  sigma(i, j) += this->prestress(i, j, interpolated_xi);
396  }
397  }
398 
399  // Get stress derivative by FD only needed for Jacobian
400  //-----------------------------------------------------
401 
402  // Stress derivative
403  RankFourTensor<double> d_stress_dG(DIM, DIM, DIM, DIM, 0.0);
404  // Derivative of metric tensor w.r.t. to nodal coords
405  RankFiveTensor<double> d_G_dX(n_node, n_position_type, DIM, DIM, DIM, 0.0);
406 
407  // Get Jacobian too?
408  if (flag == 1)
409  {
410  // Derivative of metric tensor w.r.t. to discrete positional dofs
411  // NOTE: Since G is symmetric we only compute the upper triangle
412  // and DO NOT copy the entries across. Subsequent computations
413  // must (and, in fact, do) therefore only operate with upper
414  // triangular entries
415  for (unsigned ll = 0; ll < n_node; ll++)
416  {
417  for (unsigned kk = 0; kk < n_position_type; kk++)
418  {
419  for (unsigned ii = 0; ii < DIM; ii++)
420  {
421  for (unsigned aa = 0; aa < DIM; aa++)
422  {
423  for (unsigned bb = aa; bb < DIM; bb++)
424  {
425  d_G_dX(ll, kk, ii, aa, bb) =
426  interpolated_G(aa, ii) * dpsidxi(ll, kk, bb) +
427  interpolated_G(bb, ii) * dpsidxi(ll, kk, aa);
428  }
429  }
430  }
431  }
432  }
433 
434  //Get the "upper triangular" entries of the derivatives of the stress
435  //tensor with respect to G
436  this->get_d_stress_dG_upper(g, G, sigma, d_stress_dG);
437  }
438 
439  //=====EQUATIONS OF ELASTICITY FROM PRINCIPLE OF VIRTUAL DISPLACEMENTS========
440 
441  //Loop over the test functions, nodes of the element
442  for (unsigned l = 0; l < n_node; l++)
443  {
444  //Loop of types of dofs
445  for (unsigned k = 0; k < n_position_type; k++)
446  {
447  // Offset for faster access
448  const unsigned offset5 = dpsidxi.offset(l, k);
449 
450  //Loop over the displacement components
451  for (unsigned i = 0; i < DIM; i++)
452  {
453  //Get the equation number
454  local_eqn = this->position_local_eqn(l, k, i);
455 
456  /*IF it's not a boundary condition*/
457  if (local_eqn >= 0)
458  {
459  //Initialise contribution to sum
460  double sum = 0.0;
461 
462  // Acceleration and body force
463  sum += ( lambda_sq * accel[i] - b[i] ) * psi(l, k);
464 
465  // Stress term
466  for (unsigned a = 0; a < DIM; a++)
467  {
468  unsigned count = offset5;
469  for (unsigned b = 0; b < DIM; b++)
470  {
471  //Add the stress terms to the residuals
472  sum += sigma(a, b) * interpolated_G(a, i) *
473  dpsidxi.raw_direct_access(count);
474  ++count;
475  }
476  }
477  residuals[local_eqn] += W * sum;
478 
479  // Get Jacobian too?
480  if (flag == 1)
481  {
482  // Offset for faster access in general stress loop
483  const unsigned offset1 = d_G_dX.offset(l, k, i);
484 
485  //Loop over the nodes of the element again
486  for (unsigned ll = 0; ll < n_node; ll++)
487  {
488  //Loop of types of dofs again
489  for (unsigned kk = 0; kk < n_position_type; kk++)
490  {
491  //Loop over the displacement components again
492  for (unsigned ii = 0; ii < DIM; ii++)
493  {
494  //Get the number of the unknown
495  int local_unknown = this->position_local_eqn(ll, kk, ii);
496 
497  /*IF it's not a boundary condition*/
498  if (local_unknown >= 0)
499  {
500  // Offset for faster access in general stress loop
501  const unsigned offset2 = d_G_dX.offset(ll, kk, ii);
502  const unsigned offset4 = dpsidxi.offset(ll, kk);
503 
504  // General stress term
505  //--------------------
506  double sum = 0.0;
507  unsigned count1 = offset1;
508  for (unsigned a = 0; a < DIM; a++)
509  {
510  // Bump up direct access because we're only
511  // accessing upper triangle
512  count1 += a;
513  for (unsigned b = a; b < DIM; b++)
514  {
515  double factor = d_G_dX.raw_direct_access(count1);
516  if (a == b) factor *= 0.5;
517 
518  // Offset for faster access
519  unsigned offset3 = d_stress_dG.offset(a, b);
520  unsigned count2 = offset2;
521  unsigned count3 = offset3;
522 
523  for (unsigned aa = 0; aa < DIM; aa++)
524  {
525  // Bump up direct access because we're only
526  // accessing upper triangle
527  count2 += aa;
528  count3 += aa;
529 
530  // Only upper half of derivatives w.r.t. symm tensor
531  for (unsigned bb = aa; bb < DIM; bb++)
532  {
533  sum += factor *
534  d_stress_dG.raw_direct_access(count3) *
535  d_G_dX.raw_direct_access(count2);
536  ++count2;
537  ++count3;
538  }
539  }
540  ++count1;
541  }
542 
543  }
544 
545  // Multiply by weight and add contribution
546  // (Add directly because this bit is nonsymmetric)
547  jacobian(local_eqn, local_unknown) += sum * W;
548 
549  // Only upper triangle (no separate test for bc as
550  // local_eqn is already nonnegative)
551  if (( i == ii ) && ( local_unknown >= local_eqn ))
552  {
553  //Initialise contribution
554  double sum = 0.0;
555 
556  // Inertia term
557  sum += lambda_sq * time_factor * psi(ll, kk) * psi(l, k);
558 
559  // Stress term
560  unsigned count4 = offset4;
561  for (unsigned a = 0; a < DIM; a++)
562  {
563  //Cache term
564  const double factor =
565  dpsidxi.raw_direct_access(count4);// ll ,kk
566  ++count4;
567 
568  unsigned count5 = offset5;
569  for (unsigned b = 0; b < DIM; b++)
570  {
571  sum += sigma(a, b) * factor *
572  dpsidxi.raw_direct_access(count5); // l ,k
573  ++count5;
574  }
575  }
576  //Add contribution to jacobian
577  jacobian(local_eqn, local_unknown) += sum * W;
578  //Add to lower triangular section
579  if (local_eqn != local_unknown)
580  {
581  jacobian(local_unknown, local_eqn) += sum * W;
582  }
583  }
584 
585  } //End of if not boundary condition
586  }
587  }
588  }
589  }
590 
591  } //End of if not boundary condition
592 
593  } //End of loop over coordinate directions
594  } //End of loop over type of dof
595  } //End of loop over shape functions
596  } //End of loop over integration points
597  }
JacobiRotation< float > G
Definition: Jacobi_makeGivens.cpp:2
JacobiRotation< float > J
Definition: Jacobi_makeJacobi.cpp:3
RowVector3d w
Definition: Matrix_resize_int.cpp:3
Scalar * b
Definition: benchVecAdd.cpp:17
RealScalar s
Definition: level1_cplx_impl.h:130
const Scalar * a
Definition: level2_cplx_impl.h:32
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bfloat16 pow(const bfloat16 &a, const bfloat16 &b)
Definition: BFloat16.h:625
void body_force(const double &time, const Vector< double > &x, Vector< double > &result)
Definition: axisym_linear_elasticity/cylinder/cylinder.cc:96
int sigma
Definition: calibrate.py:179
Mdouble gamma(Mdouble gamma_in)
This is the gamma function returns the true value for the half integer value.
Definition: ExtendedMath.cc:116
@ W
Definition: quadtree.h:63
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2

References a, b, Global_Parameters::body_force(), DIM, G, mathsFunc::gamma(), i, J, j, k, oomph::RankFourTensor< T >::offset(), oomph::DShape::offset(), oomph::RankFiveTensor< T >::offset(), Eigen::bfloat16_impl::pow(), oomph::RankFourTensor< T >::raw_direct_access(), oomph::RankFiveTensor< T >::raw_direct_access(), oomph::DShape::raw_direct_access(), s, calibrate::sigma, w, and oomph::QuadTreeNames::W.

Referenced by oomph::VolumeCoupledElement< ELEMENT >::fill_in_contribution_to_jacobian(), and oomph::VolumeCoupledElement< ELEMENT >::fill_in_contribution_to_residuals().

◆ get_momentum_and_energy()

template<class ELEMENT >
void oomph::VolumeCoupledElement< ELEMENT >::get_momentum_and_energy ( double mass,
Vector< double > &  lin_mo,
Vector< double > &  ang_mo,
double pot_en,
double kin_en 
)
inline
81  {
82  const unsigned DIM = this->dim();
83  // Initialise mass
84  mass = 0;
85  // Initialise momentum
86  lin_mo.initialise(0);
87  ang_mo.initialise(0);
88  // Initialise energy
89  pot_en = 0;
90  kin_en = 0;
91 
92  //Set the value of n_intpt
93  unsigned n_intpt = this->integral_pt()->nweight();
94 
95  //Set the Vector to hold local coordinates
96  Vector<double> s(DIM);
97 
98  //Find out how many nodes there are
99  const unsigned n_node = this->nnode();
100 
101  //Find out how many positional dofs there are
102  const unsigned n_position_type = this->nnodal_position_type();
103 
104  //Set up memory for the shape functions
105  Shape psi(n_node, n_position_type);
106  DShape dpsidxi(n_node, n_position_type, DIM);
107 
108  // Timescale ratio (non-dim density)
109  double lambda_sq = this->lambda_sq();
110 
111  //Loop over the integration points
112  for (unsigned ipt = 0; ipt < n_intpt; ipt++)
113  {
114  //Assign values of s
115  for (unsigned i = 0; i < DIM; i++)
116  { s[i] = this->integral_pt()->knot(ipt, i); }
117 
118  //Get the integral weight
119  double w = this->integral_pt()->weight(ipt);
120 
121  //Call the derivatives of the shape functions and get Jacobian
122  double J = this->dshape_lagrangian_at_knot(ipt, psi, dpsidxi);
123 
124  //Get mass and the coupling weight at the integration point
125  double coupling_w = 0;
126  for (unsigned l = 0; l < n_node; l++)
127  {
128  double nodal_coupling_w = dynamic_cast<CoupledSolidNode*>(this->node_pt(l))->get_coupling_weight();
129  double psi_ = psi(l);
130  coupling_w += psi_ * nodal_coupling_w;
131  }
132 
133  //Storage for Lagrangian coordinates and velocity (initialised to zero)
134  Vector<double> interpolated_xi(DIM, 0.0);
135  Vector<double> veloc(DIM, 0.0);
136 
137  //Calculate lagrangian coordinates
138  for (unsigned l = 0; l < n_node; l++)
139  {
140  //Loop over positional dofs
141  for (unsigned k = 0; k < n_position_type; k++)
142  {
143  //Loop over displacement components (deformed position)
144  for (unsigned i = 0; i < DIM; i++)
145  {
146  //Calculate the Lagrangian coordinates
147  interpolated_xi[i] += this->lagrangian_position_gen(l, k, i) * psi(l, k);
148 
149  //Calculate the velocity components (if unsteady solve)
150  if (this->Unsteady)
151  {
152  veloc[i] += this->dnodal_position_gen_dt(l, k, i) * psi(l, k);
153  }
154  }
155  }
156  }
157 
158  //Get isotropic growth factor
159  double gamma = 1.0;
160  this->get_isotropic_growth(ipt, s, interpolated_xi, gamma);
161 
162  //Premultiply the undeformed volume ratio (from the isotropic
163  // growth), the integral weights, the coupling weights, and the Jacobian
164  double W = gamma * w * ( 1.0 - coupling_w ) * J;
165 
167  DenseMatrix<double> strain(DIM, DIM);
168 
169  //Now calculate the stress tensor from the constitutive law
170  this->get_stress(s, sigma);
171 
172  // Add pre-stress
173  for (unsigned i = 0; i < DIM; i++)
174  {
175  for (unsigned j = 0; j < DIM; j++)
176  {
177  sigma(i, j) += this->prestress(i, j, interpolated_xi);
178  }
179  }
180 
181  //get the strain
182  this->get_strain(s, strain);
183 
184  // Initialise
185  double local_pot_en = 0;
186  double veloc_sq = 0;
187 
188  // Compute integrals
189  for (unsigned i = 0; i < DIM; i++)
190  {
191  for (unsigned j = 0; j < DIM; j++)
192  {
193  local_pot_en += sigma(i, j) * strain(i, j);
194  }
195  veloc_sq += veloc[i] * veloc[i];
196  }
197 
198  // Mass
199  mass += lambda_sq * W;
200  // Linear momentum and angular momentum
201  Vector<double> cross_product(DIM, 0);
202  VectorHelpers::cross(interpolated_xi, veloc, cross_product);
203  for (unsigned i = 0; i < DIM; i++)
204  {
205  lin_mo[i] += lambda_sq * veloc[i] * W;
206  ang_mo[i] += lambda_sq * cross_product[i] * W;
207  }
208  // Potential energy
209  pot_en += 0.5 * local_pot_en * W;
210  // Kinetic energy
211  kin_en += lambda_sq * 0.5 * veloc_sq * W;
212  }
213  }
void initialise(const _Tp &__value)
Iterate over all values and set to the desired value.
Definition: oomph-lib/src/generic/Vector.h:167
void cross(const Vector< double > &A, const Vector< double > &B, Vector< double > &C)
Definition: oomph-lib/src/generic/Vector.h:319

References oomph::VectorHelpers::cross(), DIM, mathsFunc::gamma(), i, oomph::Vector< _Tp >::initialise(), J, j, k, s, calibrate::sigma, w, and oomph::QuadTreeNames::W.

◆ get_nodal_coupling_jacobian()

template<class ELEMENT >
double& oomph::VolumeCoupledElement< ELEMENT >::get_nodal_coupling_jacobian ( const unsigned l,
const unsigned ll 
)
inline

◆ get_nodal_coupling_residual()

template<class ELEMENT >
double& oomph::VolumeCoupledElement< ELEMENT >::get_nodal_coupling_residual ( const unsigned l,
const unsigned i 
)
inline

◆ getCouplingStiffness()

template<class ELEMENT >
double& oomph::VolumeCoupledElement< ELEMENT >::getCouplingStiffness ( const unsigned m,
const unsigned l 
)
inline
77  { return couplingStiffness[m][l]; }
Vector< Vector< double > > couplingStiffness
Coupling stiffness to discrete particles (FIXME: should be moved into DPMVCoupledElement)
Definition: VCoupledElement.h:742
int * m
Definition: level2_cplx_impl.h:294

References oomph::VolumeCoupledElement< ELEMENT >::couplingStiffness, and m.

◆ output()

template<class ELEMENT >
void oomph::VolumeCoupledElement< ELEMENT >::output ( std::ostream &  outfile,
const unsigned n_plot 
)
inlineoverrideprivate
673  {
674  const unsigned DIM = this->dim();
675  Vector<double> x(DIM);
676  Vector<double> dxdt(DIM);
677  Vector<double> s(DIM);
678 
679  // Tecplot header info
680  outfile << this->tecplot_zone_string(n_plot);
681 
682  // Loop over plot points
683  unsigned num_plot_points = this->nplot_points(n_plot);
684  for (unsigned iplot = 0; iplot < num_plot_points; iplot++)
685  {
686  // Get local coordinates of plot point
687  this->get_s_plot(iplot, n_plot, s);
688 
689  // Get Eulerian coordinates
690  this->interpolated_x(s, x);
691  SolidFiniteElement* el_pt = dynamic_cast<SolidFiniteElement*>(this);
692  el_pt->interpolated_dxdt(s, 1, dxdt);
693 
694  // Dummy integration point
695  unsigned ipt = 0;
696 
697  // Output the x,y,..
698  for (unsigned i = 0; i < DIM; i++)
699  { outfile << x[i] * Global_Physical_Variables::lenScale << " "; }
700 
701  // Output velocity dnodal_position_gen_dt
702  for (unsigned i = 0; i < DIM; i++)
703  {
705  << " ";
706  }
707 
708  //Find the number of nodes
709  const unsigned n_node = this->nnode();
710  //Find the number of positional types
711  const unsigned n_position_type = this->nnodal_position_type();
712  //Assign storage for the local shape function
713  Shape psi(n_node, n_position_type);
714  //Find the values of shape function
715  this->shape(s, psi);
716  // Initialize coupling weight
717  double w = 0;
718  // Loop over the local nodes
719  for (unsigned l = 0; l < n_node; l++)
720  {
721  double nodal_coupling_w = dynamic_cast<CoupledSolidNode*>(this->node_pt(l))->get_coupling_weight();
722  w += nodal_coupling_w * psi(l);
723  }
724  // Output coupling weight
725  outfile << w << " ";
726 
727  outfile << std::endl;
728  }
729 
730  // Write tecplot footer (e.g. FE connectivity lists)
731  this->write_tecplot_zone_footer(outfile, n_plot);
732  outfile << std::endl;
733  }
double lenScale
Length scale.
Definition: VCoupledElement.h:10
double timeScale
Time scale.
Definition: VCoupledElement.h:13
void shape(const double &s, double *Psi)
Definition: shape.h:564
list x
Definition: plotDoE.py:28

References DIM, i, oomph::FiniteElement::interpolated_dxdt(), Global_Physical_Variables::lenScale, s, oomph::OneDimLagrange::shape(), Global_Physical_Variables::timeScale, w, and plotDoE::x.

◆ set_nodal_coupling_jacobian()

template<class ELEMENT >
void oomph::VolumeCoupledElement< ELEMENT >::set_nodal_coupling_jacobian ( Vector< Vector< double > > &  cJacobian)
inline

◆ set_nodal_coupling_residual()

template<class ELEMENT >
void oomph::VolumeCoupledElement< ELEMENT >::set_nodal_coupling_residual ( Vector< Vector< double > > &  cResidual)
inline

◆ setCouplingStiffness()

template<class ELEMENT >
void oomph::VolumeCoupledElement< ELEMENT >::setCouplingStiffness ( Vector< Vector< double > > &  cStiffness)
inline

Member Data Documentation

◆ couplingStiffness

template<class ELEMENT >
Vector<Vector<double> > oomph::VolumeCoupledElement< ELEMENT >::couplingStiffness
private

Coupling stiffness to discrete particles (FIXME: should be moved into DPMVCoupledElement)

Referenced by oomph::VolumeCoupledElement< ELEMENT >::getCouplingStiffness(), and oomph::VolumeCoupledElement< ELEMENT >::setCouplingStiffness().

◆ nodal_coupling_jacobian

◆ nodal_coupling_residual


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