SCoupledElement.h
Go to the documentation of this file.
1 // This file is part of the MercuryDPM project (https://www.mercurydpm.org).
2 // Copyright (c), The MercuryDPM Developers Team. All rights reserved.
3 // License: BSD 3-Clause License; see the LICENSE file in the root directory.
4 
5 #ifndef SCOUPLEDELEMENT_H
6 #define SCOUPLEDELEMENT_H
8 
9 namespace oomph
10 {
11 
12 //=================start_wrapper==================================
15 //================================================================
16 template<class ELEMENT>
17 class SCoupledElement : public ELEMENT
18 {
19 
20 public:
21 
24  {};
25 
28  {};
29 
32  Node* construct_node(const unsigned& n)
33  {
34  // Construct a solid node and assign it to the local node pointer vector.
35  // The dimension and number of values are taken from internal element data
36  // The number of solid pressure dofs are also taken from internal data
37  // The number of timesteps to be stored comes from the problem!
38  this->node_pt(n) = new CoupledSolidNode(
39  this->lagrangian_dimension(),
40  this->nnodal_lagrangian_type(),
41  this->nodal_dimension(),
42  this->nnodal_position_type(),
43  this->required_nvalue(n));
44  // Now return a pointer to the node, so that the mesh can find it
45  return this->node_pt(n);
46  }
47 
52  Node* construct_node(const unsigned& n, TimeStepper* const& time_stepper_pt)
53  {
54  // Construct a solid node and assign it to the local node pointer vector
55  // The dimension and number of values are taken from internal element data
56  // The number of solid pressure dofs are also taken from internal data
57  this->node_pt(n) = new CoupledSolidNode(
58  time_stepper_pt,
59  this->lagrangian_dimension(),
60  this->nnodal_lagrangian_type(),
61  this->nodal_dimension(),
62  this->nnodal_position_type(),
63  this->required_nvalue(n));
64  // Now return a pointer to the node, so that the mesh can find it
65  return this->node_pt(n);
66  }
67 
72  Node* construct_boundary_node(const unsigned& n)
73  {
74  // Construct a solid node and assign it to the local node pointer vector.
75  // The dimension and number of values are taken from internal element data
76  // The number of solid pressure dofs are also taken from internal data
77  // The number of timesteps to be stored comes from the problem!
78  this->node_pt(n) = new BoundaryNode<CoupledSolidNode>(
79  this->lagrangian_dimension(),
80  this->nnodal_lagrangian_type(),
81  this->nodal_dimension(),
82  this->nnodal_position_type(),
83  this->required_nvalue(n));
84  // Now return a pointer to the node, so that the mesh can find it
85  return this->node_pt(n);
86  }
87 
93  Node* construct_boundary_node(const unsigned& n,
94  TimeStepper* const& time_stepper_pt)
95  {
96  // Construct a solid node and assign it to the local node pointer vector
97  // The dimension and number of values are taken from internal element data
98  // The number of solid pressure dofs are also taken from internal data
99  this->node_pt(n) = new BoundaryNode<CoupledSolidNode>(
100  time_stepper_pt,
101  this->lagrangian_dimension(),
102  this->nnodal_lagrangian_type(),
103  this->nodal_dimension(),
104  this->nnodal_position_type(),
105  this->required_nvalue(n));
106  // Now return a pointer to the node, so that the mesh can find it
107  return this->node_pt(n);
108  }
109 
110 
113  {
114  // Call the generic residuals function with flag set to 0 using a dummy matrix argument
115  ELEMENT::fill_in_generic_contribution_to_residuals_pvd(
116  residuals, GeneralisedElement::Dummy_matrix, 0);
117 
118  // Add point source contribution
120  }
121 
124  DenseMatrix<double>& jacobian)
125  {
126  //Call the generic routine with the flag set to 1
127  ELEMENT::fill_in_generic_contribution_to_residuals_pvd(residuals, jacobian, 1);
128 
129  // Add point source contribution
131  }
132 
133  void get_momentum_and_energy(double& mass, Vector<double>& lin_mo, Vector<double>& ang_mo, double& pot_en,
134  double& kin_en)
135  {
136  const unsigned DIM = this->dim();
137  // Initialise mass
138  mass = 0;
139  // Initialise momentum
140  lin_mo.initialise(0);
141  ang_mo.initialise(0);
142  // Initialise energy
143  pot_en = 0;
144  kin_en = 0;
145 
146  //Set the value of n_intpt
147  unsigned n_intpt = this->integral_pt()->nweight();
148 
149  //Set the Vector to hold local coordinates
151 
152  //Find out how many nodes there are
153  const unsigned n_node = this->nnode();
154 
155  //Find out how many positional dofs there are
156  const unsigned n_position_type = this->nnodal_position_type();
157 
158  //Set up memory for the shape functions
159  Shape psi(n_node, n_position_type);
160  DShape dpsidxi(n_node, n_position_type, DIM);
161 
162  // Timescale ratio (non-dim density)
163  double lambda_sq = this->lambda_sq();
164 
165  //Loop over the integration points
166  for (unsigned ipt = 0; ipt < n_intpt; ipt++)
167  {
168  //Assign values of s
169  for (unsigned i = 0; i < DIM; i++)
170  { s[i] = this->integral_pt()->knot(ipt, i); }
171 
172  //Get the integral weight
173  double w = this->integral_pt()->weight(ipt);
174 
175  //Call the derivatives of the shape functions and get Jacobian
176  double J = this->dshape_lagrangian_at_knot(ipt, psi, dpsidxi);
177 
178  //Storage for Lagrangian coordinates and velocity (initialised to zero)
179  Vector<double> interpolated_xi(DIM, 0.0);
180  Vector<double> veloc(DIM, 0.0);
181 
182  //Calculate lagrangian coordinates
183  for (unsigned l = 0; l < n_node; l++)
184  {
185  //Loop over positional dofs
186  for (unsigned k = 0; k < n_position_type; k++)
187  {
188  //Loop over displacement components (deformed position)
189  for (unsigned i = 0; i < DIM; i++)
190  {
191  //Calculate the Lagrangian coordinates
192  interpolated_xi[i] += this->lagrangian_position_gen(l, k, i) * psi(l, k);
193 
194  //Calculate the velocity components (if unsteady solve)
195  if (this->Unsteady)
196  {
197  veloc[i] += this->dnodal_position_gen_dt(l, k, i) * psi(l, k);
198  }
199  }
200  }
201  }
202 
203  //Get isotropic growth factor gamma
204  double gamma = 1.0;
205  this->get_isotropic_growth(ipt, s, interpolated_xi, gamma);
206 
207  //Premultiply the undeformed volume ratio (from the isotropic
208  // growth), the integral weights, the coupling weights, and the Jacobian
209  double W = gamma * w * J;
210 
212  DenseMatrix<double> strain(DIM, DIM);
213 
214  //Now calculate the stress tensor from the constitutive law
215  this->get_stress(s, sigma);
216 
217  // Add pre-stress
218  for (unsigned i = 0; i < DIM; i++)
219  {
220  for (unsigned j = 0; j < DIM; j++)
221  {
222  sigma(i, j) += this->prestress(i, j, interpolated_xi);
223  }
224  }
225 
226  //get the strain
227  this->get_strain(s, strain);
228 
229  // Initialise
230  double local_pot_en = 0;
231  double veloc_sq = 0;
232 
233  // Compute integrals
234  for (unsigned i = 0; i < DIM; i++)
235  {
236  for (unsigned j = 0; j < DIM; j++)
237  {
238  local_pot_en += sigma(i, j) * strain(i, j);
239  }
240  veloc_sq += veloc[i] * veloc[i];
241  }
242 
243  // Mass
244  mass += lambda_sq * W;
245  // Linear momentum and angular momentum
246  Vector<double> cross_product(DIM, 0);
247  VectorHelpers::cross(interpolated_xi, veloc, cross_product);
248  for (unsigned i = 0; i < DIM; i++)
249  {
250  lin_mo[i] += lambda_sq * veloc[i] * W;
251  ang_mo[i] += lambda_sq * cross_product[i] * W;
252  }
253  // Potential energy
254  pot_en += 0.5 * local_pot_en * W;
255  // Kinetic energy
256  kin_en += lambda_sq * 0.5 * veloc_sq * W;
257  }
258  }
259 
260  void set_nodal_coupling_residual(const bool& isCoupled, Vector <Vector<double>>& residual)
261  {
262  if (isCoupled)
263  { nodal_coupling_residual = residual; }
264  else
265  { nodal_coupling_residual.clear(); }
266  }
267 
268  double get_nodal_coupling_residual(const unsigned n, const unsigned d) {
269  if (nodal_coupling_residual.size()>n && nodal_coupling_residual[n].size()>d)
270  return nodal_coupling_residual[n][d];
271  else
272  return 0;
273  }
274 
275 private:
276 
279  {
280  // No further action if no coupling force
281  if (nodal_coupling_residual.size() == 0) return;
282 
283  // Find out how many nodes there are
284  const unsigned n_node = this->nnode();
285  const unsigned DIM = this->dim();
286 
287  //find out how many positional dofs there are
288  unsigned n_position_type = this->nnodal_position_type();
289 
290  // Set up memory for the shape/test functions
291  //Shape psi(n_node);
292 
293  // Loop over all nodes belonging to the element
294  int local_eqn = 0;
295  // Loop over the nodes of the element
296  for (unsigned l = 0; l < n_node; l++)
297  {
298  // Loop of types of dofs
299  for (unsigned k = 0; k < n_position_type; k++)
300  {
301  // Loop over the force components
302  for (unsigned i = 0; i < DIM; i++)
303  {
304  // Get the local equation
305  local_eqn = this->position_local_eqn(l, k, i);
306  // IF it's not a boundary condition and the interpolated force is nonzero
307  if (local_eqn >= 0)
308  {
309  // add the nodal coupling residual to the global residual vector
310  residuals[local_eqn] += nodal_coupling_residual[l][i];
311  }
312  }
313  }
314  }
315  logger(VERBOSE, "Apply nodal_coupling_residual element %", this);
316  }
317 protected:
318  void output(std::ostream& outfile, const unsigned& n_plot)
319  {
320  const unsigned DIM = this->dim();
322  Vector<double> dxdt(DIM);
324 
325  // Tecplot header info
326  outfile << this->tecplot_zone_string(n_plot);
327 
328  // Loop over plot points
329  unsigned num_plot_points = this->nplot_points(n_plot);
330  for (unsigned iplot = 0; iplot < num_plot_points; iplot++)
331  {
332  // Get local coordinates of plot point
333  this->get_s_plot(iplot, n_plot, s);
334 
335  // Get Eulerian coordinates
336  this->interpolated_x(s, x);
337  SolidFiniteElement* el_pt = dynamic_cast<SolidFiniteElement*>(this);
338  el_pt->interpolated_dxdt(s, 1, dxdt);
339 
340  // Dummy integration point
341  unsigned ipt = 0;
342 
343  // Output x,y,z
344  for (unsigned i = 0; i < DIM; i++)
345  {
346  outfile << x[i] << " ";
347  }
348 
349  // Output velocity dnodal_position_gen_dt
350  for (unsigned i = 0; i < DIM; i++)
351  {
352  outfile << dxdt[i] << " ";
353  }
354 
355  outfile << std::endl;
356  }
357 
358  // Write tecplot footer (e.g. FE connectivity lists)
359  this->write_tecplot_zone_footer(outfile, n_plot);
360  outfile << std::endl;
361  }
362 
365 
366 };
367 
368 
369 //===========start_face_geometry==============================================
371 //============================================================================
372 template<class ELEMENT>
373 class FaceGeometry<SCoupledElement<ELEMENT> > :
374  public virtual FaceGeometry<ELEMENT>
375 {
376 public:
377 
380  FaceGeometry() : FaceGeometry<ELEMENT>()
381  {}
382 
383 };
384 
385 }
386 
387 #endif //SCOUPLEDELEMENT_H
int i
Definition: BiCGSTAB_step_by_step.cpp:9
const unsigned n
Definition: CG3DPackingUnitTest.cpp:11
JacobiRotation< float > J
Definition: Jacobi_makeJacobi.cpp:3
LL< Log::VERBOSE > VERBOSE
Verbose information.
Definition: Logger.cc:36
Logger< MERCURYDPM_LOGLEVEL > logger("MercuryKernel")
Definition of different loggers with certain modules. A user can define its own custom logger here.
RowVector3d w
Definition: Matrix_resize_int.cpp:3
Definition: nodes.h:2242
Definition: CoupledSolidNodes.h:20
Definition: shape.h:278
FaceGeometry()
Constructor [this was only required explicitly from gcc 4.5.2 onwards...].
Definition: SCoupledElement.h:380
Definition: elements.h:4998
virtual double interpolated_dxdt(const Vector< double > &s, const unsigned &i, const unsigned &t)
Definition: elements.cc:4596
static DenseMatrix< double > Dummy_matrix
Definition: elements.h:227
Definition: nodes.h:906
Definition: SCoupledElement.h:18
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Add the element's contribution to its residual vector and Jacobian matrix (wrapper)
Definition: SCoupledElement.h:123
void fill_in_contribution_to_residuals(Vector< double > &residuals)
Add the element's contribution to its residual vector (wrapper)
Definition: SCoupledElement.h:112
SCoupledElement()
Constructor: Call constructor of underlying element.
Definition: SCoupledElement.h:23
Node * construct_boundary_node(const unsigned &n, TimeStepper *const &time_stepper_pt)
Definition: SCoupledElement.h:93
Node * construct_boundary_node(const unsigned &n)
Definition: SCoupledElement.h:72
void output(std::ostream &outfile, const unsigned &n_plot)
Definition: SCoupledElement.h:318
Node * construct_node(const unsigned &n)
Definition: SCoupledElement.h:32
Node * construct_node(const unsigned &n, TimeStepper *const &time_stepper_pt)
Definition: SCoupledElement.h:52
void get_momentum_and_energy(double &mass, Vector< double > &lin_mo, Vector< double > &ang_mo, double &pot_en, double &kin_en)
Definition: SCoupledElement.h:133
~SCoupledElement()
Destructor (empty)
Definition: SCoupledElement.h:27
void set_nodal_coupling_residual(const bool &isCoupled, Vector< Vector< double >> &residual)
Definition: SCoupledElement.h:260
void add_external_coupling_forces_to_residuals(Vector< double > &residuals)
Add the point source contribution to the residual vector.
Definition: SCoupledElement.h:278
double get_nodal_coupling_residual(const unsigned n, const unsigned d)
Definition: SCoupledElement.h:268
Vector< Vector< double > > nodal_coupling_residual
Nodal coupling forces.
Definition: SCoupledElement.h:364
Definition: shape.h:76
Definition: elements.h:3561
Definition: timesteppers.h:231
void initialise(const _Tp &__value)
Iterate over all values and set to the desired value.
Definition: oomph-lib/src/generic/Vector.h:167
RealScalar s
Definition: level1_cplx_impl.h:130
char char char int int * k
Definition: level2_impl.h:374
#define DIM
Definition: linearised_navier_stokes_elements.h:44
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
void cross(const Vector< double > &A, const Vector< double > &B, Vector< double > &C)
Definition: oomph-lib/src/generic/Vector.h:319
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
Definition: AnisotropicHookean.h:10
list x
Definition: plotDoE.py:28
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2