refineable_axisym_cylindrical_solid_elements.cc
Go to the documentation of this file.
1// LIC// ====================================================================
2// LIC// This file forms part of oomph-lib, the object-oriented,
3// LIC// multi-physics finite-element library, available
4// LIC// at http://www.oomph-lib.org.
5// LIC//
6// LIC// Copyright (C) 2006-2026 Matthias Heil and Andrew Hazel
7// LIC//
8// LIC// This library is free software; you can redistribute it and/or
9// LIC// modify it under the terms of the GNU Lesser General Public
10// LIC// License as published by the Free Software Foundation; either
11// LIC// version 2.1 of the License, or (at your option) any later version.
12// LIC//
13// LIC// This library is distributed in the hope that it will be useful,
14// LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16// LIC// Lesser General Public License for more details.
17// LIC//
18// LIC// You should have received a copy of the GNU Lesser General Public
19// LIC// License along with this library; if not, write to the Free Software
20// LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21// LIC// 02110-1301 USA.
22// LIC//
23// LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24// LIC//
25// LIC//====================================================================
26
27// Non-inline member functions and static member data for refineable solid
28// mechanics elements
29
32
33namespace oomph
34{
35 //====================================================================
36 /// Residuals for Refineable AxisymCylindricalPVDWithPressureElements
37 //====================================================================
40 DenseMatrix<double>& jacobian,
41 const unsigned& flag)
42 {
43 // Set the number of Lagrangian coordinates
44 unsigned n_lagrangian = 2;
45 // Find out how many nodes there are
46 unsigned n_node = nnode();
47
48 // Integers to store local equation number and local unknown
49 int local_eqn = 0, local_unknown = 0;
50
51 // Set up memory for the shape functions
54
55 // Timescale ratio (non-dim density)
56 double lambda_sq = this->lambda_sq();
57
58 // Set the value of n_intpt
59 unsigned n_intpt = integral_pt()->nweight();
60
61 // Get the mass damping parameter
62 const double eta_M = eta_mass();
63
64 // Time factor
65 double time_factor = 0.0;
66 if (lambda_sq > 0)
67 {
69 }
70
71 // Loop over the integration points
72 for (unsigned ipt = 0; ipt < n_intpt; ipt++)
73 {
74 // Get the integral weight
75 double w = integral_pt()->weight(ipt);
76 // Call the derivatives of the shape functions
78 // Premultiply the weights and the Jacobian
79 double W = w * J;
80
81 // Calculate the local Lagrangian coordinates, position components
82 // and the derivatives of global position components
83 // wrt lagrangian coordinates, as well as acceleration
86 Vector<double> accel(2, 0.0);
89
90 // Calculate displacements and derivatives
91 for (unsigned l = 0; l < n_node; l++)
92 {
93 // Loop over displacement components (deformed position)
94 for (unsigned i = 0; i < 2; i++)
95 {
96 // Set the value of the lagrangian coordinate
98 // Set the value of the position component
100 // Set accel.
101 accel[i] += dnodal_position_dt(l, 2, i) * psi(l);
102 // Set velocity
104 // Loop over Lagrangian derivative directions
105 for (unsigned j = 0; j < 2; j++)
106 {
107 // Calculate dX[i]/dxi_{j}
109 }
110 }
111 }
112
113 // We are now in a position to calculate the undeformed metric tensor
115 // r row
116 g(0, 0) = 1.0;
117 g(0, 1) = 0.0;
118 g(0, 2) = 0.0;
119 // z row
120 g(1, 0) = 0.0;
121 g(1, 1) = 1.0;
122 g(1, 2) = 0.0;
123 // phi row
124 g(2, 0) = 0.0;
125 g(2, 1) = 0.0;
126 g(2, 2) = interpolated_xi[0] * interpolated_xi[0];
127
128 // Now multiply the weight by the square-root of the undeformed metric
129 // tensor r
130 double detg = g(0, 0) * g(1, 1) * g(2, 2);
131 W *= sqrt(detg);
132
133 // Now calculate the deformed metric tensor
135 // r row
136 G(0, 0) = interpolated_dXdxi(0, 0) * interpolated_dXdxi(0, 0) +
138 G(0, 1) = interpolated_dXdxi(0, 0) * interpolated_dXdxi(0, 1) +
140 G(0, 2) = 0.0;
141 // z row
142 G(1, 0) = G(0, 1);
143 G(1, 1) = interpolated_dXdxi(0, 1) * interpolated_dXdxi(0, 1) +
145 G(1, 2) = 0.0;
146 // phi row
147 G(2, 0) = 0.0;
148 G(2, 1) = 0.0;
149 G(2, 2) = interpolated_X[0] * interpolated_X[0];
150
151 // Now calculate the stress tensor from the constitutive law
152 DenseMatrix<double> sigma(3, 3, 0.0);
153 get_stress(g, G, sigma);
154
155 // If we're calculating the Jacobian, will need derivative of stress
156 // tensor w.r.t. the deformed metric tensor
157 RankFourTensor<double> d_stress_dG(3, 3, 3, 3, 0.0);
158 RankFourTensor<double> dG_dX(n_node, 2, 3, 3, 0.0);
159
160 if (flag == 1)
161 {
162 // Get the "upper triangular"
163 // entries of the derivatives of the stress tensor with
164 // respect to G
165 this->get_d_stress_dG_upper(g, G, sigma, d_stress_dG);
166
167 // Construct upper triangle of dGdX
168 // Loop over nodes
169 for (unsigned m = 0; m < n_node; m++)
170 {
171 // Loops over directions
172 for (unsigned i = 0; i < 2; i++)
173 {
174 for (unsigned a = 0; a < 2; a++)
175 {
176 for (unsigned b = a; b < 2; b++)
177 {
178 dG_dX(m, i, a, b) = interpolated_dXdxi(i, a) * dpsidxi(m, b) +
179 interpolated_dXdxi(i, b) * dpsidxi(m, a);
180 }
181 }
182 }
183
184 // Accounting for axisymmetric coord system
185 dG_dX(m, 0, 2, 2) = 2.0 * interpolated_X[0] * psi(m);
186 }
187 }
188
189 // Get body force at current time
190 Vector<double> b(2, 0.0);
191 this->body_force(interpolated_xi, b);
192
193 // Default setting for non-hanging node
194 unsigned n_master = 1;
195 double hang_weight = 1.0;
196
197 // Loop over the test functions, nodes of the element
198 for (unsigned l = 0; l < n_node; l++)
199 {
200 // Get pointer to local node l
202
203 // Cache hang status
204 bool is_hanging = local_node_pt->is_hanging();
205
206 // If the node is a hanging node
207 if (is_hanging)
208 {
209 n_master = local_node_pt->hanging_pt()->nmaster();
210 }
211 // Otherwise the node is its own master
212 else
213 {
214 n_master = 1;
215 }
216
217 // Storage for local equation numbers at node indexed by
218 // type and direction
220
221 // Loop over the master nodes
222 for (unsigned m = 0; m < n_master; m++)
223 {
224 if (is_hanging)
225 {
226 // Find the equation numbers
228 local_node_pt->hanging_pt()->master_node_pt(m));
229
230 // Find the hanging node weight
231 hang_weight = local_node_pt->hanging_pt()->master_weight(m);
232 }
233 else
234 {
235 // Loop over the displacement components
236 for (unsigned i = 0; i < 2; i++)
237 {
239 }
240
241 // Hang weight is one
242 hang_weight = 1.0;
243 }
244
245 // Loop over displacement components
246 for (unsigned i = 0; i < 2; i++)
247 {
248 // Get the local eqn
250
251 // If not a boundary condition
252 if (local_eqn >= 0)
253 {
254 // Forcing/inertial contributions
256 (lambda_sq * (accel[i] + eta_M * interpolated_dXdt[i]) - b[i]) *
257 psi(l) * W * hang_weight;
258
259 // Stress term
260 for (unsigned a = 0; a < 2; a++)
261 {
262 for (unsigned b = 0; b < 2; b++)
263 {
264 residuals[local_eqn] += sigma(a, b) * dpsidxi(l, b) *
265 interpolated_dXdxi(i, a) * W *
267 }
268 }
269
270 // Additional stress term if it's the r component
271 if (i == 0)
272 {
274 sigma(2, 2) * interpolated_X[0] * psi(l) * W * hang_weight;
275 }
276
277 // Get Jacobian too?
278 if (flag == 1)
279 {
280 // Default setting for non-hanging node
281 unsigned nn_master = 1;
282 double hhang_weight = 1.0;
283
284 // Loop over the nodes of the element again
285 for (unsigned ll = 0; ll < n_node; ll++)
286 {
287 // Get pointer to local node ll
289
290 // Cache hang status
291 bool iis_hanging = llocal_node_pt->is_hanging();
292
293 // If the node is a hanging node
294 if (iis_hanging)
295 {
296 nn_master = llocal_node_pt->hanging_pt()->nmaster();
297 }
298 // Otherwise the node is its own master
299 else
300 {
301 nn_master = 1;
302 }
303
304 // Storage for local unknown numbers at node indexed by
305 // type and direction
307
308 // Loop over the master nodes
309 for (unsigned mm = 0; mm < nn_master; mm++)
310 {
311 if (iis_hanging)
312 {
313 // Find the unknown numbers
315 llocal_node_pt->hanging_pt()->master_node_pt(mm));
316
317 // Find the hanging node weight
319 llocal_node_pt->hanging_pt()->master_weight(mm);
320 }
321 else
322 {
323 // Loop over the displacement components
324 for (unsigned ii = 0; ii < 2; ii++)
325 {
328 }
329
330 // Hang weight is one
331 hhang_weight = 1.0;
332 }
333
334 // Loop over the displacement components again
335 for (unsigned ii = 0; ii < 2; ii++)
336 {
337 // Get the number of the unknown
339
340 /*IF it's not a boundary condition*/
341 if (local_unknown >= 0)
342 {
343 // General stress term
344 //--------------------
345 double sum = 0.0;
346 for (unsigned a = 0; a < 2; a++)
347 {
348 for (unsigned b = a; b < 2; b++)
349 {
350 double factor = dG_dX(l, i, a, b);
351 if (a == b) factor *= 0.5;
352
353 for (unsigned aa = 0; aa < 3; aa++)
354 {
355 // Only upper half of derivatives w.r.t.
356 // symm tensor
357 for (unsigned bb = aa; bb < 3; bb++)
358 {
359 sum += factor * d_stress_dG(a, b, aa, bb) *
360 dG_dX(ll, ii, aa, bb);
361 }
362 }
363 }
364 }
365
366 // Contribution accounting for axisymmetry
367 if (i == 0)
368 {
369 double factor = 0.5 * dG_dX(l, i, 2, 2);
370 for (unsigned aa = 0; aa < 3; aa++)
371 {
372 // Only upper half of derivatives w.r.t.
373 // symm tensor
374 for (unsigned bb = aa; bb < 3; bb++)
375 {
376 sum += factor * d_stress_dG(2, 2, aa, bb) *
377 dG_dX(ll, ii, aa, bb);
378 }
379 }
380 }
381
382 // Multiply by weight and add contribution
383 // (Add directly because this bit is nonsymmetric)
384 jacobian(local_eqn, local_unknown) +=
386
387 // Only upper triangle (no separate test for bc as
388 // local_eqn is already nonnegative). Can be done
389 // for remaining terms as they are symmetric
390 if ((i == ii) && (local_unknown >= local_eqn))
391 {
392 // Initialise contribution
393 double sum = 0.0;
394
395 // Inertia term
396 sum += lambda_sq * time_factor * psi(ll) * psi(l);
397
398 // Stress term
399 for (unsigned a = 0; a < 2; a++)
400 {
401 for (unsigned b = 0; b < 2; b++)
402 {
403 sum +=
404 sigma(a, b) * dpsidxi(ll, a) * dpsidxi(l, b);
405 }
406 }
407
408 // Accounting for axisymmetry
409 if (i == 0)
410 {
411 sum += sigma(2, 2) * psi(l) * psi(ll);
412 }
413
414 // Multiply by weights to form contribution
415 double sym_entry =
417 // Add contribution to jacobian
418 jacobian(local_eqn, local_unknown) += sym_entry;
419 // Add to lower triangular entries
421 {
422 jacobian(local_unknown, local_eqn) += sym_entry;
423 }
424 }
425 } // End of if not boundary condition
426 } // End of second displacement component loop
427 } // End of second master node loop
428 } // End of second node loop
429 } // End of Jacobian
430 } // End of if not a boundary condition
431 } // End of loop over displacement components
432 } // End of loop over master nodes
433 } // End of loop over test functions
434 } // End of loop over integration points
435 }
436
437 //====================================================================
438 /// Residuals for Refineable AxisymCylindricalPVDWithPressureElements
439 //====================================================================
443 DenseMatrix<double>& jacobian,
444 const unsigned& flag)
445 {
446 // Set the number of Lagrangian coordinates
447 unsigned n_lagrangian = 2;
448 // Find out how many nodes there are
449 unsigned n_node = nnode();
450
451 // Integers to store local equation number and local unknown
452 int local_eqn = 0, local_unknown = 0;
453
454 // Find out how many pressure dofs there are
455 const unsigned n_solid_pres = this->nsolid_pres();
456
457 // Find out the index of the solid dof
458 const int solid_p_index = this->solid_p_nodal_index();
459
460 // Local array of booleans that is true if the l-th pressure value is
461 // hanging This is an optimization because it avoids repeated virtual
462 // function calls
464
465 // If the solid pressure is stored at a node
466 if (solid_p_index >= 0)
467 {
468 // Read out whether the solid pressure is hanging
469 for (unsigned l = 0; l < n_solid_pres; ++l)
470 {
473 }
474 }
475 // Otherwise the pressure is not stored at a node and so
476 // it cannot hang
477 else
478 {
479 for (unsigned l = 0; l < n_solid_pres; ++l)
480 {
482 }
483 }
484
485 // Set up memory for the shape functions
488
489 // Set up memory for the pressure shape functions
491
492 // Timescale ratio (non-dim density)
493 double lambda_sq = this->lambda_sq();
494
495 // Set the value of n_intpt
496 unsigned n_intpt = integral_pt()->nweight();
497
498 // Get the mass damping parameter
499 const double eta_M = eta_mass();
500
501 // Time factor
502 double time_factor = 0.0;
503 if (lambda_sq > 0)
504 {
506 }
507
508 // Loop over the integration points
509 for (unsigned ipt = 0; ipt < n_intpt; ipt++)
510 {
511 // Get the integral weight
512 double w = integral_pt()->weight(ipt);
513 // Call the derivatives of the shape functions
515 // Premultiply the weights and the Jacobian
516 double W = w * J;
517
518 // Call the pressure shape functions
520
521 // Calculate the local Lagrangian coordinates, position components
522 // and the derivatives of global position components
523 // wrt lagrangian coordinates, as well as acceleration
526 Vector<double> accel(2, 0.0);
529 double interpolated_solid_p = 0.0;
530
531 // Calculate displacements and derivatives
532 for (unsigned l = 0; l < n_node; l++)
533 {
534 // Loop over displacement components (deformed position)
535 for (unsigned i = 0; i < 2; i++)
536 {
537 // Set the value of the lagrangian coordinate
539 // Set the value of the position component
541 // Set accel.
542 accel[i] += dnodal_position_dt(l, 2, i) * psi(l);
543 // Set velocity
545 // Loop over Lagrangian derivative directions
546 for (unsigned j = 0; j < 2; j++)
547 {
548 // Calculate dX[i]/dxi_{j}
550 }
551 }
552 }
553
554 // Calculate the local internal pressure
555 for (unsigned l = 0; l < n_solid_pres; l++)
556 {
558 }
559
560 // We are now in a position to calculate the undeformed metric tensor
562 // r row
563 g(0, 0) = 1.0;
564 g(0, 1) = 0.0;
565 g(0, 2) = 0.0;
566 // z row
567 g(1, 0) = 0.0;
568 g(1, 1) = 1.0;
569 g(1, 2) = 0.0;
570 // phi row
571 g(2, 0) = 0.0;
572 g(2, 1) = 0.0;
573 g(2, 2) = interpolated_xi[0] * interpolated_xi[0];
574
575 // Now multiply the weight by the square-root of the undeformed metric
576 // tensor r
577 double detg = g(0, 0) * g(1, 1) * g(2, 2);
578 W *= sqrt(detg);
579
580 // Now calculate the deformed metric tensor
582 // r row
583 G(0, 0) = interpolated_dXdxi(0, 0) * interpolated_dXdxi(0, 0) +
585 G(0, 1) = interpolated_dXdxi(0, 0) * interpolated_dXdxi(0, 1) +
587 G(0, 2) = 0.0;
588 // z row
589 G(1, 0) = G(0, 1);
590 G(1, 1) = interpolated_dXdxi(0, 1) * interpolated_dXdxi(0, 1) +
592 G(1, 2) = 0.0;
593 // phi row
594 G(2, 0) = 0.0;
595 G(2, 1) = 0.0;
596 G(2, 2) = interpolated_X[0] * interpolated_X[0];
597
598 // Now calculate the deviatoric stress tensor from the constitutive law
600 double detG = 0.0, gen_dil = 0.0, inv_kappa = 0.0;
601 // If it's incompressible call one form of the constitutive law
602 if (Incompressible)
603 {
605 }
606 // Otherwise call another form
607 else
608 {
610 }
611
612 // Build the stress tensor up from its pressure and deviatoric
613 // components
614 DenseMatrix<double> sigma(3, 3, 0.0);
615 for (unsigned i = 0; i < 3; i++)
616 {
617 for (unsigned j = 0; j < 3; j++)
618 {
619 sigma(i, j) =
620 -1.0 * interpolated_solid_p * Gup(i, j) + sigma_dev(i, j);
621 }
622 }
623
624 // If we're calculating the Jacobian, will need derivative of stress
625 // tensor w.r.t. the deformed metric tensor
626 RankFourTensor<double> d_stress_dG(3, 3, 3, 3, 0.0);
627 RankFourTensor<double> dG_dX(n_node, 2, 3, 3, 0.0);
630
631 if (flag == 1)
632 {
633 // If incompressible, call the incompressible form
634 if (Incompressible)
635 {
638 }
639 else
640 // Otherwise call the near-incompressible form
641 {
642 this->get_d_stress_dG_upper(g,
643 G,
644 sigma,
645 gen_dil,
646 inv_kappa,
650 }
651
652 // Construct upper triangle of dGdX
653 // Loop over nodes
654 for (unsigned m = 0; m < n_node; m++)
655 {
656 // Loops over directions
657 for (unsigned i = 0; i < 2; i++)
658 {
659 for (unsigned a = 0; a < 2; a++)
660 {
661 for (unsigned b = a; b < 2; b++)
662 {
663 dG_dX(m, i, a, b) = interpolated_dXdxi(i, a) * dpsidxi(m, b) +
664 interpolated_dXdxi(i, b) * dpsidxi(m, a);
665 }
666 }
667 }
668
669 // Accounting for axisymmetric coord system
670 dG_dX(m, 0, 2, 2) = 2.0 * interpolated_X[0] * psi(m);
671 }
672 }
673
674 // Get body force at current time
675 Vector<double> b(2, 0.0);
676 this->body_force(interpolated_xi, b);
677
678 // Default setting for non-hanging node
679 unsigned n_master = 1;
680 double hang_weight = 1.0;
681
682 // Loop over the test functions, nodes of the element
683 for (unsigned l = 0; l < n_node; l++)
684 {
685 // Get pointer to local node l
687
688 // Cache hang status
689 bool is_hanging = local_node_pt->is_hanging();
690
691 // If the node is a hanging node
692 if (is_hanging)
693 {
694 n_master = local_node_pt->hanging_pt()->nmaster();
695 }
696 // Otherwise the node is its own master
697 else
698 {
699 n_master = 1;
700 }
701
702 // Storage for local equation numbers at node indexed by
703 // type and direction
705
706 // Loop over the master nodes
707 for (unsigned m = 0; m < n_master; m++)
708 {
709 if (is_hanging)
710 {
711 // Find the equation numbers
713 local_node_pt->hanging_pt()->master_node_pt(m));
714
715 // Find the hanging node weight
716 hang_weight = local_node_pt->hanging_pt()->master_weight(m);
717 }
718 else
719 {
720 // Loop over the displacement components
721 for (unsigned i = 0; i < 2; i++)
722 {
724 }
725
726 // Hang weight is one
727 hang_weight = 1.0;
728 }
729
730 // Loop over displacement components
731 for (unsigned i = 0; i < 2; i++)
732 {
733 // Get the local eqn
735
736 // If not a boundary condition
737 if (local_eqn >= 0)
738 {
739 // Forcing/inertial contributions
741 (lambda_sq * (accel[i] + eta_M * interpolated_dXdt[i]) - b[i]) *
742 psi(l) * W * hang_weight;
743
744 // Stress term
745 for (unsigned a = 0; a < 2; a++)
746 {
747 for (unsigned b = 0; b < 2; b++)
748 {
749 residuals[local_eqn] += sigma(a, b) * dpsidxi(l, b) *
750 interpolated_dXdxi(i, a) * W *
752 }
753 }
754
755 // Additional stress term if it's the r component
756 if (i == 0)
757 {
759 sigma(2, 2) * interpolated_X[0] * psi(l) * W * hang_weight;
760 }
761
762 // Get Jacobian too?
763 if (flag == 1)
764 {
765 // Default setting for non-hanging node
766 unsigned nn_master = 1;
767 double hhang_weight = 1.0;
768
769 // Loop over the nodes of the element again
770 for (unsigned ll = 0; ll < n_node; ll++)
771 {
772 // Get pointer to local node ll
774
775 // Cache hang status
776 bool iis_hanging = llocal_node_pt->is_hanging();
777
778 // If the node is a hanging node
779 if (iis_hanging)
780 {
781 nn_master = llocal_node_pt->hanging_pt()->nmaster();
782 }
783 // Otherwise the node is its own master
784 else
785 {
786 nn_master = 1;
787 }
788
789 // Storage for local unknown numbers at node indexed by
790 // type and direction
792
793 // Loop over the master nodes
794 for (unsigned mm = 0; mm < nn_master; mm++)
795 {
796 if (iis_hanging)
797 {
798 // Find the unknown numbers
800 llocal_node_pt->hanging_pt()->master_node_pt(mm));
801
802 // Find the hanging node weight
804 llocal_node_pt->hanging_pt()->master_weight(mm);
805 }
806 else
807 {
808 // Loop over the displacement components
809 for (unsigned ii = 0; ii < 2; ii++)
810 {
813 }
814
815 // Hang weight is one
816 hhang_weight = 1.0;
817 }
818
819 // Loop over the displacement components again
820 for (unsigned ii = 0; ii < 2; ii++)
821 {
822 // Get the number of the unknown
824
825 /*IF it's not a boundary condition*/
826 if (local_unknown >= 0)
827 {
828 // General stress term
829 //--------------------
830 double sum = 0.0;
831 for (unsigned a = 0; a < 2; a++)
832 {
833 for (unsigned b = a; b < 2; b++)
834 {
835 double factor = dG_dX(l, i, a, b);
836 if (a == b) factor *= 0.5;
837
838 for (unsigned aa = 0; aa < 3; aa++)
839 {
840 // Only upper half of derivatives w.r.t.
841 // symm tensor
842 for (unsigned bb = aa; bb < 3; bb++)
843 {
844 sum += factor * d_stress_dG(a, b, aa, bb) *
845 dG_dX(ll, ii, aa, bb);
846 }
847 }
848 }
849 }
850
851 // Contribution accounting for axisymmetry
852 if (i == 0)
853 {
854 double factor = 0.5 * dG_dX(l, i, 2, 2);
855 for (unsigned aa = 0; aa < 3; aa++)
856 {
857 // Only upper half of derivatives w.r.t.
858 // symm tensor
859 for (unsigned bb = aa; bb < 3; bb++)
860 {
861 sum += factor * d_stress_dG(2, 2, aa, bb) *
862 dG_dX(ll, ii, aa, bb);
863 }
864 }
865 }
866
867 // Multiply by weight and add contribution
868 // (Add directly because this bit is nonsymmetric)
869 jacobian(local_eqn, local_unknown) +=
871
872 // Only upper triangle (no separate test for bc as
873 // local_eqn is already nonnegative). Can be done
874 // for remaining terms as they are symmetric
875 if ((i == ii) && (local_unknown >= local_eqn))
876 {
877 // Initialise contribution
878 double sum = 0.0;
879
880 // Inertia term
881 sum += lambda_sq * time_factor * psi(ll) * psi(l);
882
883 // Stress term
884 for (unsigned a = 0; a < 2; a++)
885 {
886 for (unsigned b = 0; b < 2; b++)
887 {
888 sum +=
889 sigma(a, b) * dpsidxi(ll, a) * dpsidxi(l, b);
890 }
891 }
892
893 // Accounting for axisymmetry
894 if (i == 0)
895 {
896 sum += sigma(2, 2) * psi(l) * psi(ll);
897 }
898
899 // Multiply by weights to form contribution
900 double sym_entry =
902 // Add contribution to jacobian
903 jacobian(local_eqn, local_unknown) += sym_entry;
904 // Add to lower triangular entries
906 {
907 jacobian(local_unknown, local_eqn) += sym_entry;
908 }
909 }
910 } // End of if not boundary condition
911 }
912 }
913 }
914
915 // Can add in the pressure jacobian terms
916 // Loop over the pressure nodes
917 for (unsigned l2 = 0; l2 < n_solid_pres; l2++)
918 {
919 unsigned n_master2 = 1;
920 double hang_weight2 = 1.0;
922
924 if (is_hanging2)
925 {
926 // Get the HangInfo object associated with the
927 // hanging solid pressure
930
931 n_master2 = hang_info2_pt->nmaster();
932 }
933 else
934 {
935 n_master2 = 1;
936 }
937
938 // Loop over all the master nodes
939 for (unsigned m2 = 0; m2 < n_master2; m2++)
940 {
941 if (is_hanging2)
942 {
943 // Get the equation numbers at the master node
945 hang_info2_pt->master_node_pt(m2), solid_p_index);
946
947 // Find the hanging node weight at the node
948 hang_weight2 = hang_info2_pt->master_weight(m2);
949 }
950 else
951 {
953 hang_weight2 = 1.0;
954 }
955
956 // If it's not a boundary condition
957 if (local_unknown >= 0)
958 {
959 // Add the pressure terms to the jacobian
960 for (unsigned a = 0; a < 2; a++)
961 {
962 for (unsigned b = 0; b < 2; b++)
963 {
964 jacobian(local_eqn, local_unknown) -=
965 psisp(l2) * Gup(a, b) * interpolated_dXdxi(i, a) *
966 dpsidxi(l, b) * W * hang_weight * hang_weight2;
967 }
968 }
969
970 // Additional contribution for axisymmetry
971 if (i == 0)
972 {
973 jacobian(local_eqn, local_unknown) -=
974 psisp(l2) * Gup(2, 2) * interpolated_X[0] * psi(l) *
976 }
977 }
978 } // End of loop over master nodes
979 } // End of loop over pressure dofs
980 } // End of Jacobian
981 }
982 } // End of loop over displacement components
983 } // End of loop over master nodes
984 } // End of loop over test functions
985
986 // Now loop over the pressure dofs
987 for (unsigned l = 0; l < n_solid_pres; l++)
988 {
989 bool is_hanging = solid_pressure_dof_is_hanging[l];
990
991 unsigned n_master = 1;
992 double hang_weight = 1.0;
994
995 // If the node is a hanging node
996 if (is_hanging)
997 {
998 // Get a pointer to the HangInfo object associated with the
999 // solid pressure (stored at solid_p_index)
1001
1002 // Number of master nodes
1003 n_master = hang_info_pt->nmaster();
1004 }
1005 // Otherwise the node is its own master
1006 else
1007 {
1008 n_master = 1;
1009 }
1010
1011 // Loop over all the master nodes
1012 // Note that the pressure is stored at the inded solid_p_index
1013 for (unsigned m = 0; m < n_master; m++)
1014 {
1015 if (is_hanging)
1016 {
1017 // Get the equation numbers at the master node
1018 local_eqn =
1019 local_hang_eqn(hang_info_pt->master_node_pt(m), solid_p_index);
1020
1021 // Find the hanging node weight at the node
1022 hang_weight = hang_info_pt->master_weight(m);
1023 }
1024 else
1025 {
1026 local_eqn = this->solid_p_local_eqn(l);
1027 }
1028
1029 // Pinned (unlikely, actually) or real dof?
1030 if (local_eqn >= 0)
1031 {
1032 // For true incompressibility we need to conserve volume
1033 // so the determinant of the deformed metric tensor
1034 // needs to be equal to that of the undeformed one, which
1035 // is equal to the volumetric growth factor
1036 if (this->Incompressible)
1037 {
1038 residuals[local_eqn] +=
1039 (detG / detg - 1.0) * psisp[l] * W * hang_weight;
1040
1041 // Add in the jacobian terms
1042 if (flag == 1)
1043 {
1044 // Default setting for non-hanging node
1045 unsigned nn_master = 1;
1046 double hhang_weight = 1.0;
1047
1048 // Loop over the nodes of the element again
1049 for (unsigned ll = 0; ll < n_node; ll++)
1050 {
1051 // Get pointer to local node ll
1053
1054 // Cache hang status
1055 bool iis_hanging = llocal_node_pt->is_hanging();
1056
1057 // If the node is a hanging node
1058 if (iis_hanging)
1059 {
1060 nn_master = llocal_node_pt->hanging_pt()->nmaster();
1061 }
1062 // Otherwise the node is its own master
1063 else
1064 {
1065 nn_master = 1;
1066 }
1067
1068 // Storage for local unknown numbers at node indexed by
1069 // type and direction
1071
1072 // Loop over the master nodes
1073 for (unsigned mm = 0; mm < nn_master; mm++)
1074 {
1075 if (iis_hanging)
1076 {
1077 // Find the unknown numbers
1079 llocal_node_pt->hanging_pt()->master_node_pt(mm));
1080
1081 // Find the hanging node weight
1082 hhang_weight =
1083 llocal_node_pt->hanging_pt()->master_weight(mm);
1084 }
1085 else
1086 {
1087 // Loop over the displacement components
1088 for (unsigned ii = 0; ii < 2; ii++)
1089 {
1092 }
1093
1094 // Hang weight is one
1095 hhang_weight = 1.0;
1096 }
1097
1098 // Loop over the displacement components again
1099 for (unsigned ii = 0; ii < 2; ii++)
1100 {
1101 // Get the number of the unknown
1103
1104 /*IF it's not a boundary condition*/
1105 if (local_unknown >= 0)
1106 {
1107 // General stress term
1108 double sum = 0.0;
1109 for (unsigned aa = 0; aa < 3; aa++)
1110 {
1111 // Only upper half
1112 for (unsigned bb = aa; bb < 3; bb++)
1113 {
1114 sum += d_detG_dG(aa, bb) * dG_dX(ll, ii, aa, bb) *
1115 psisp(l) / detg;
1116 }
1117 }
1118 jacobian(local_eqn, local_unknown) +=
1120 }
1121 }
1122 }
1123 }
1124 } // End of Jacobian
1125 }
1126 // Nearly incompressible case
1127 else
1128 {
1132
1133 // Add in the jacobian terms
1134 if (flag == 1)
1135 {
1136 // Default setting for non-hanging node
1137 unsigned nn_master = 1;
1138 double hhang_weight = 1.0;
1139
1140 // Loop over the nodes of the element again
1141 for (unsigned ll = 0; ll < n_node; ll++)
1142 {
1143 // Get pointer to local node ll
1145
1146 // Cache hang status
1147 bool iis_hanging = llocal_node_pt->is_hanging();
1148
1149 // If the node is a hanging node
1150 if (iis_hanging)
1151 {
1152 nn_master = llocal_node_pt->hanging_pt()->nmaster();
1153 }
1154 // Otherwise the node is its own master
1155 else
1156 {
1157 nn_master = 1;
1158 }
1159
1160 // Storage for local unknown numbers at node indexed by
1161 // type and direction
1163
1164 // Loop over the master nodes
1165 for (unsigned mm = 0; mm < nn_master; mm++)
1166 {
1167 if (iis_hanging)
1168 {
1169 // Find the unknown numbers
1171 llocal_node_pt->hanging_pt()->master_node_pt(mm));
1172
1173 // Find the hanging node weight
1174 hhang_weight =
1175 llocal_node_pt->hanging_pt()->master_weight(mm);
1176 }
1177 else
1178 {
1179 // Loop over the displacement components
1180 for (unsigned ii = 0; ii < 2; ii++)
1181 {
1184 }
1185
1186 // Hang weight is one
1187 hhang_weight = 1.0;
1188 }
1189
1190 // Loop over the displacement components again
1191 for (unsigned ii = 0; ii < 2; ii++)
1192 {
1193 // Get the number of the unknown
1195
1196 /*IF it's not a boundary condition*/
1197 if (local_unknown >= 0)
1198 {
1199 // General stress term
1200 double sum = 0.0;
1201 for (unsigned aa = 0; aa < 3; aa++)
1202 {
1203 // Only upper half
1204 for (unsigned bb = aa; bb < 3; bb++)
1205 {
1206 sum += d_gen_dil_dG(aa, bb) *
1207 dG_dX(ll, ii, aa, bb) * psisp(l);
1208 }
1209 }
1210 jacobian(local_eqn, local_unknown) +=
1212 }
1213 }
1214 }
1215 }
1216
1217 // Loop over the pressure nodes again
1218 for (unsigned l2 = 0; l2 < n_solid_pres; l2++)
1219 {
1221
1222 unsigned n_master2 = 1;
1223 double hang_weight2 = 1.0;
1225
1226 if (is_hanging2)
1227 {
1228 // Get pointer to hang info object
1229 // Note that the pressure is stored at
1230 // the index solid_p_index
1233
1234 n_master2 = hang_info2_pt->nmaster();
1235 }
1236 else
1237 {
1238 n_master2 = 1;
1239 }
1240
1241 // Loop over all the master nodes
1242 for (unsigned m2 = 0; m2 < n_master2; m2++)
1243 {
1244 if (is_hanging2)
1245 {
1246 // Get the equation numbers at the master node
1248 hang_info2_pt->master_node_pt(m2), solid_p_index);
1249
1250 // Find the hanging node weight at the node
1251 hang_weight2 = hang_info2_pt->master_weight(m2);
1252 }
1253 else
1254 {
1256 hang_weight2 = 1.0;
1257 }
1258
1259 // If it's not a boundary condition
1260 if (local_unknown >= 0)
1261 {
1262 jacobian(local_eqn, local_unknown) +=
1263 inv_kappa * psisp(l2) * psisp(l) * W * hang_weight *
1265 }
1266 } // End of loop over master nodes
1267 } // End of loop over pressure dofs
1268 } // End of Jacobian
1269 }
1270 } // End of if not boundary condition
1271 } // End of loop over master nodes
1272 } // End of loop over pressure dofs
1273 } // End of loop over integration points
1274 }
1275} // namespace oomph
cstr elem_len * i
Definition cfortran.h:603
void get_stress(const DenseMatrix< double > &g, const DenseMatrix< double > &G, DenseMatrix< double > &sigma)
Return the stress tensor, as calculated from the constitutive law.
double eta_mass()
Return the mass damping parameter.
void body_force(const Vector< double > &xi, Vector< double > &b) const
Evaluate body force at Lagrangian coordinate xi at present time (returns zero vector if no body force...
const double & lambda_sq() const
Access function for timescale ratio (nondim density)
void get_d_stress_dG_upper(const DenseMatrix< double > &g, const DenseMatrix< double > &G, const DenseMatrix< double > &sigma, RankFourTensor< double > &d_sigma_dG)
Return the derivatives of the 2nd Piola Kirchhoff stress tensor, as calculated from the constitutive ...
void body_force(const Vector< double > &xi, Vector< double > &b) const
Evaluate body force at Lagrangian coordinate xi at present time (returns zero vector if no body force...
void get_stress(const DenseMatrix< double > &g, const DenseMatrix< double > &G, DenseMatrix< double > &sigma, DenseMatrix< double > &Gup, double &pressure_stress, double &kappa)
Return the stress tensor, as calculated from the constitutive law in the Near-incompresible formulati...
double interpolated_solid_p(const Vector< double > &s) const
Return the interpolated_solid_pressure.
void solid_pshape_at_knot(const unsigned &ipt, Shape &psi) const
Return the stored solid shape functions at the knots.
virtual int solid_p_local_eqn(const unsigned &i) const =0
Access function that returns the local equation number for the n-th solid pressure value.
void get_d_stress_dG_upper(const DenseMatrix< double > &g, const DenseMatrix< double > &G, const DenseMatrix< double > &sigma, const double &gen_dil, const double &inv_kappa, const double &interpolated_solid_p, RankFourTensor< double > &d_sigma_dG, DenseMatrix< double > &d_gen_dil_dG)
Return the derivative of the deviatoric part of the 2nd Piola Kirchhoff stress tensor,...
virtual double solid_p(const unsigned &l) const =0
Return the lth solid pressures.
bool Incompressible
Boolean to determine whether the solid is incompressible or not.
virtual int solid_p_nodal_index() const
Return the index at which the solid pressure is stored.
virtual unsigned nsolid_pres() const =0
Return the number of solid pressure degrees of freedom.
const double & lambda_sq() const
Access function for timescale ratio (nondim density)
A Class for the derivatives of shape functions The class design is essentially the same as Shape,...
Definition shape.h:278
Integral *const & integral_pt() const
Return the pointer to the integration scheme (const version)
Definition elements.h:1967
unsigned nnode() const
Return the number of nodes.
Definition elements.h:2214
double nodal_position(const unsigned &n, const unsigned &i) const
Return the i-th coordinate at local node n. If the node is hanging, the appropriate interpolation is ...
Definition elements.h:2321
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition elements.h:2179
double dnodal_position_dt(const unsigned &n, const unsigned &i) const
Return the i-th component of nodal velocity: dx/dt at local node n.
Definition elements.h:2337
Class that contains data for hanging nodes.
Definition nodes.h:742
virtual unsigned nweight() const =0
Return the number of integration points of the scheme.
virtual double weight(const unsigned &i) const =0
Return weight of i-th integration point.
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
Definition nodes.h:906
TimeStepper *& position_time_stepper_pt()
Return a pointer to the position timestepper.
Definition nodes.h:1022
void fill_in_contribution_to_residuals_axisym_pvd(Vector< double > &residuals, DenseMatrix< double > &jacobian, const unsigned &flag)
Call the residuals including hanging node cases.
virtual Node * solid_pressure_node_pt(const unsigned &l)
Return a pointer to the solid node at which pressure dof l2 is stored.
void fill_in_contribution_to_residuals_axisym_pvd_with_pressure(Vector< double > &residuals, DenseMatrix< double > &jacobian, const unsigned &flag)
Call the residuals including hanging node cases.
int local_hang_eqn(Node *const &node_pt, const unsigned &i)
Access function that returns the local equation number for the hanging node variables (values stored ...
DenseMatrix< int > & local_position_hang_eqn(Node *const &node_pt)
Access the local equation number of of hanging node variables associated with nodal positions....
A Class for shape functions. In simple cases, the shape functions have only one index that can be tho...
Definition shape.h:76
double lagrangian_position(const unsigned &n, const unsigned &i) const
Return i-th Lagrangian coordinate at local node n.
Definition elements.h:3909
int position_local_eqn(const unsigned &n, const unsigned &k, const unsigned &j) const
Access function that returns the local equation number that corresponds to the j-th coordinate of the...
Definition elements.h:4141
virtual double interpolated_xi(const Vector< double > &s, const unsigned &i) const
Return i-th FE-interpolated Lagrangian coordinate xi[i] at local coordinate s.
Definition elements.cc:7135
virtual double dshape_lagrangian_at_knot(const unsigned &ipt, Shape &psi, DShape &dpsidxi) const
Return the geometric shape functions and also first derivatives w.r.t. Lagrangian coordinates at ipt-...
Definition elements.cc:6768
TAdvectionDiffusionReactionElement<NREAGENT,DIM,NNODE_1D> elements are isoparametric triangular DIM-d...
virtual double weight(const unsigned &i, const unsigned &j) const
Access function for j-th weight for the i-th derivative.
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).