axisym_displ_based_fvk_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-2022 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// Non-inline functions for axisym FoepplvonKarman elements
27
29
30
31namespace oomph
32{
33 //======================================================================
34 /// Set the data for the number of Variables at each node - 3
35 //======================================================================
36 template<unsigned NNODE_1D>
38
39
40 //======================================================================
41 /// Compute contribution to element residual Vector
42 ///
43 /// Pure version without hanging nodes
44 //======================================================================
46 Vector<double>& residuals)
47 {
48 // Find out how many nodes there are
49 const unsigned n_node = nnode();
50
51 // Set up memory for the shape and test functions
52 Shape psi(n_node), test(n_node);
53 DShape dpsidr(n_node, 1), dtestdr(n_node, 1);
54
55 // Set the value of n_intpt
56 const unsigned n_intpt = integral_pt()->nweight();
57
58 // Indices at which the unknowns are stored
59 const unsigned w_nodal_index = nodal_index_fvk(0);
60 const unsigned laplacian_w_nodal_index = nodal_index_fvk(1);
61 const unsigned u_r_nodal_index = nodal_index_fvk(2);
62
63 // Local copy of parameters
64 const double nu_local = nu();
65 const double eta_local = eta();
66
67 // Integers to store the local equation numbers
68 int local_eqn = 0;
69
70 // Loop over the integration points
71 for (unsigned ipt = 0; ipt < n_intpt; ipt++)
72 {
73 // Get the integral weight
74 double w = integral_pt()->weight(ipt);
75
76 // Call the derivatives of the shape and test functions
78 ipt, psi, dpsidr, test, dtestdr);
79
80 // Allocate and initialise to zero storage for the interpolated values
81 double interpolated_r = 0.0;
82
83 double interpolated_w = 0.0;
84 double interpolated_laplacian_w = 0.0;
85 double interpolated_u_r = 0.0;
86
87 double interpolated_dwdr = 0.0;
88 double interpolated_dlaplacian_wdr = 0.0;
89 double interpolated_du_rdr = 0.0;
90
92
93 // Calculate function values and derivatives:
94 //-----------------------------------------
95 // Loop over nodes
96 for (unsigned l = 0; l < n_node; l++)
97 {
98 // Get the nodal values
99 nodal_value[0] = raw_nodal_value(l, w_nodal_index);
100 nodal_value[1] = raw_nodal_value(l, laplacian_w_nodal_index);
101 nodal_value[2] = raw_nodal_value(l, u_r_nodal_index);
102
103 // Add contributions from current node/shape function
104 interpolated_w += nodal_value[0] * psi(l);
105 interpolated_laplacian_w += nodal_value[1] * psi(l);
106 interpolated_u_r += nodal_value[2] * psi(l);
107
108 interpolated_r += raw_nodal_position(l, 0) * psi(l);
109
110 interpolated_dwdr += nodal_value[0] * dpsidr(l, 0);
111 interpolated_dlaplacian_wdr += nodal_value[1] * dpsidr(l, 0);
112 interpolated_du_rdr += nodal_value[2] * dpsidr(l, 0);
113
114 } // End of loop over the nodes
115
116 // Premultiply the weights and the Jacobian
117 double W = w * interpolated_r * J;
118
119 // Get pressure function
120 //---------------------
121 double pressure = 0.0;
122 get_pressure_fvk(ipt, interpolated_r, pressure);
123
124 // Determine the stresses
125 //-----------------------
126
127 double sigma_r_r = 0.0;
128 double sigma_phi_phi = 0.0;
129
131 {
132 sigma_r_r =
133 1.0 / (1.0 - nu_local * nu_local) *
134 (interpolated_du_rdr + 0.5 * interpolated_dwdr * interpolated_dwdr +
135 nu_local * 1.0 / interpolated_r * interpolated_u_r);
136
137 sigma_phi_phi =
138 1.0 / (1.0 - nu_local * nu_local) *
139 (1.0 / interpolated_r * interpolated_u_r +
140 nu_local * (interpolated_du_rdr +
141 0.5 * interpolated_dwdr * interpolated_dwdr));
142 }
143 else
144 {
145 sigma_r_r = 1.0 / (1.0 - nu_local * nu_local) *
146 (interpolated_du_rdr +
147 nu_local * 1.0 / interpolated_r * interpolated_u_r);
148
149 sigma_phi_phi = 1.0 / (1.0 - nu_local * nu_local) *
150 (1.0 / interpolated_r * interpolated_u_r +
151 nu_local * interpolated_du_rdr);
152 }
153
154
155 // Assemble residuals and Jacobian:
156 //--------------------------------
157 // Loop over the test functions
158 for (unsigned l = 0; l < n_node; l++)
159 {
160 // Get the local equation
161 local_eqn = nodal_local_eqn(l, w_nodal_index);
162
163 // IF it's not a boundary condition
164 if (local_eqn >= 0)
165 {
166 residuals[local_eqn] +=
167 (pressure * test(l) +
168 (dtestdr(l, 0)) * interpolated_dlaplacian_wdr) *
169 W;
171 {
172 residuals[local_eqn] -=
173 eta_local * sigma_r_r * (dtestdr(l, 0)) * interpolated_dwdr * W;
174 }
175 }
176
177 // Get the local equation
178 local_eqn = nodal_local_eqn(l, laplacian_w_nodal_index);
179
180 // IF it's not a boundary condition
181 if (local_eqn >= 0)
182 {
183 residuals[local_eqn] += (test(l) * interpolated_laplacian_w +
184 (dtestdr(l, 0)) * interpolated_dwdr) *
185 W;
186 }
187
188 // Get the local equation
189 local_eqn = nodal_local_eqn(l, u_r_nodal_index);
190
191 // IF it's not a boundary condition
192 if (local_eqn >= 0)
193 {
194 residuals[local_eqn] +=
195 (sigma_r_r * dtestdr(l, 0) +
196 1.0 / interpolated_r * sigma_phi_phi * test(l)) *
197 W;
198 }
199
200 } // End of loop over test functions
201 } // End of loop over integration points
202 }
203
204
205 //======================================================================
206 /// Self-test: Return 0 for OK
207 //======================================================================
209 {
210 bool passed = true;
211
212 // Check lower-level stuff
213 if (FiniteElement::self_test() != 0)
214 {
215 passed = false;
216 }
217
218 // Return verdict
219 if (passed)
220 {
221 return 0;
222 }
223 else
224 {
225 return 1;
226 }
227 }
228
229
230 //======================================================================
231 /// Compute in-plane stresses. Return boolean to indicate success
232 /// (false if attempt to evaluate stresses at zero radius)
233 //======================================================================
235 const Vector<double>& s, double& sigma_r_r, double& sigma_phi_phi) const
236 {
237 // No in plane stresses if linear bending
239 {
240 sigma_r_r = 0.0;
241 sigma_phi_phi = 0.0;
242
243 // Success!
244 return true;
245 }
246 else
247 {
248 // Get shape fcts and derivs
249 unsigned n_dim = this->dim();
250 unsigned n_node = this->nnode();
251 Shape psi(n_node);
252 DShape dpsidr(n_node, n_dim);
253
254 // Check if we're dividing by zero
255 Vector<double> r(1);
256 this->interpolated_x(s, r);
257 if (r[0] == 0.0)
258 {
259 sigma_r_r = 0.0;
260 sigma_phi_phi = 0.0;
261 return false;
262 }
263
264 // Get shape fcts and derivs
265 dshape_eulerian(s, psi, dpsidr);
266
267 // Allocate and initialise to zero storage for the interpolated values
268 double interpolated_r = 0.0;
269 double interpolated_u_r = 0.0;
270
271 double interpolated_dwdr = 0.0;
272 double interpolated_du_rdr = 0.0;
273
274 double nu_local = nu();
275
276
277 // Calculate function values and derivatives:
278 //-----------------------------------------
279 // Loop over nodes
280 for (unsigned l = 0; l < n_node; l++)
281 {
282 // Add contributions from current node/shape function
283 interpolated_r += raw_nodal_position(l, 0) * psi(l);
284 interpolated_u_r +=
285 this->raw_nodal_value(l, nodal_index_fvk(2)) * psi(l);
286 interpolated_dwdr +=
287 this->raw_nodal_value(l, nodal_index_fvk(0)) * dpsidr(l, 0);
288 interpolated_du_rdr +=
289 this->raw_nodal_value(l, nodal_index_fvk(2)) * dpsidr(l, 0);
290 } // End of loop over nodes
291
292 // Compute the stresses:
293 //---------------------
294 sigma_r_r =
295 1.0 / (1.0 - nu_local * nu_local) *
296 (interpolated_du_rdr + 0.5 * interpolated_dwdr * interpolated_dwdr +
297 nu_local * 1.0 / interpolated_r * interpolated_u_r);
298
299 sigma_phi_phi =
300 1.0 / (1.0 - nu_local * nu_local) *
301 (1.0 / interpolated_r * interpolated_u_r +
302 nu_local *
303 (interpolated_du_rdr + 0.5 * interpolated_dwdr * interpolated_dwdr));
304
305 // Success!
306 return true;
307
308 } // End if
309
310 } // End of interpolated_stress function
311
312 //======================================================================
313 /// Output function:
314 /// r, w, sigma_r_r, sigma_phi_phi
315 /// nplot points
316 //======================================================================
317 void AxisymFoepplvonKarmanEquations::output(std::ostream& outfile,
318 const unsigned& nplot)
319 {
320 // Vector of local coordinates
321 Vector<double> s(1);
322
323 // Tecplot header info
324 outfile << "ZONE\n";
325
326 // Loop over plot points
327 unsigned num_plot_points = nplot_points(nplot);
328 for (unsigned iplot = 0; iplot < num_plot_points; iplot++)
329 {
330 // Get local coordinates of plot point
331 get_s_plot(iplot, nplot, s);
332
333 // Get stress
334 double sigma_r_r = 0.0;
335 double sigma_phi_phi = 0.0;
336 bool success = interpolated_stress(s, sigma_r_r, sigma_phi_phi);
337 if (success)
338 {
339 outfile << interpolated_x(s, 0) << " " << interpolated_w_fvk(s) << " "
340 << interpolated_u_fvk(s) << " " << sigma_r_r << " "
341 << sigma_phi_phi << std::endl;
342 }
343 }
344 }
345
346 //======================================================================
347 /// C-style output function:
348 /// r,w
349 /// nplot points
350 //======================================================================
352 const unsigned& nplot)
353 {
354 // Vector of local coordinates
355 Vector<double> s(1);
356
357 // Tecplot header info
358 fprintf(file_pt, "%s", tecplot_zone_string(nplot).c_str());
359
360 // Loop over plot points
361 unsigned num_plot_points = nplot_points(nplot);
362 for (unsigned iplot = 0; iplot < num_plot_points; iplot++)
363 {
364 // Get local coordinates of plot point
365 get_s_plot(iplot, nplot, s);
366
367 fprintf(file_pt, "%g ", interpolated_x(s, 0));
368 fprintf(file_pt, "%g \n", interpolated_w_fvk(s));
369 fprintf(file_pt, "%g \n", interpolated_u_fvk(s));
370 }
371
372 // Write tecplot footer (e.g. FE connectivity lists)
373 write_tecplot_zone_footer(file_pt, nplot);
374 }
375
376
377 //======================================================================
378 /// Output exact solution
379 ///
380 /// Solution is provided via function pointer.
381 /// Plot at a given number of plot points.
382 ///
383 /// r,w_exact
384 //======================================================================
386 std::ostream& outfile,
387 const unsigned& nplot,
389 {
390 // Vector of local coordinates
391 Vector<double> s(1);
392
393 // Vector for coordinates
394 Vector<double> r(1);
395
396 // Tecplot header info
397 outfile << tecplot_zone_string(nplot);
398
399 // Exact solution Vector (here a scalar)
400 // Vector<double> exact_soln(1);
401 Vector<double> exact_soln(1);
402
403 // Loop over plot points
404 unsigned num_plot_points = nplot_points(nplot);
405 for (unsigned iplot = 0; iplot < num_plot_points; iplot++)
406 {
407 // Get local coordinates of plot point
408 get_s_plot(iplot, nplot, s);
409
410 // Get r position as Vector
411 interpolated_x(s, r);
412
413 // Get exact solution at this point
414 (*exact_soln_pt)(r, exact_soln);
415
416 // Output r,w_exact
417 outfile << r[0] << " ";
418 outfile << exact_soln[0] << std::endl;
419 }
420
421 // Write tecplot footer (e.g. FE connectivity lists)
422 write_tecplot_zone_footer(outfile, nplot);
423 }
424
425
426 //======================================================================
427 /// Validate against exact solution
428 ///
429 /// Solution is provided via function pointer.
430 /// Plot error at a given number of plot points.
431 ///
432 //======================================================================
434 std::ostream& outfile,
436 double& error,
437 double& norm)
438 {
439 // Initialise
440 error = 0.0;
441 norm = 0.0;
442
443 // Vector of local coordinates
444 Vector<double> s(1);
445
446 // Vector for coordintes
447 Vector<double> r(1);
448
449 // Find out how many nodes there are in the element
450 unsigned n_node = nnode();
451
452 Shape psi(n_node);
453
454 // Set the value of n_intpt
455 unsigned n_intpt = integral_pt()->nweight();
456
457 // Tecplot
458 outfile << "ZONE" << std::endl;
459
460 // Exact solution Vector (here a scalar)
461 // Vector<double> exact_soln(1);
462 Vector<double> exact_soln(1);
463
464 // Loop over the integration points
465 for (unsigned ipt = 0; ipt < n_intpt; ipt++)
466 {
467 // Assign values of s
468 s[0] = integral_pt()->knot(ipt, 0);
469
470 // Get the integral weight
471 double w = integral_pt()->weight(ipt);
472
473 // Get jacobian of mapping
474 double J = J_eulerian(s);
475
476 // Premultiply the weights and the Jacobian
477 double W = w * J;
478
479 // Get r position as Vector
480 interpolated_x(s, r);
481
482 // Get FE function value
483 double w_fe = interpolated_w_fvk(s);
484
485 // Get exact solution at this point
486 (*exact_soln_pt)(r, exact_soln);
487
488 // Output r,error
489 outfile << r[0] << " ";
490 outfile << exact_soln[0] << " " << exact_soln[0] - w_fe << std::endl;
491
492 // Add to error and norm
493 norm += exact_soln[0] * exact_soln[0] * W;
494 error += (exact_soln[0] - w_fe) * (exact_soln[0] - w_fe) * W;
495 }
496
497 {
498 // Initialise
499 error = 0.0;
500 norm = 0.0;
501
502 // Vector of local coordinates
503 Vector<double> s(1);
504
505 // Vector for coordintes
506 Vector<double> r(1);
507
508 // Find out how many nodes there are in the element
509 unsigned n_node = nnode();
510
511 Shape psi(n_node);
512
513 // Set the value of n_intpt
514 unsigned n_intpt = integral_pt()->nweight();
515
516 // Tecplot
517 outfile << "ZONE" << std::endl;
518
519 // Exact solution Vector (here a scalar)
520 // Vector<double> exact_soln(1);
521 Vector<double> exact_soln(1);
522
523 // Loop over the integration points
524 for (unsigned ipt = 0; ipt < n_intpt; ipt++)
525 {
526 // Assign values of s
527 s[0] = integral_pt()->knot(ipt, 0);
528
529 // Get the integral weight
530 double w = integral_pt()->weight(ipt);
531
532 // Get jacobian of mapping
533 double J = J_eulerian(s);
534
535 // Premultiply the weights and the Jacobian
536 double W = w * J;
537
538 // Get r position as Vector
539 interpolated_x(s, r);
540
541 // Get FE function value
542 double w_fe = interpolated_w_fvk(s);
543
544 // Get exact solution at this point
545 (*exact_soln_pt)(r, exact_soln);
546
547 // Output r error
548 outfile << r[0] << " ";
549 outfile << exact_soln[0] << " " << exact_soln[0] - w_fe << std::endl;
550
551 // Add to error and norm
552 norm += exact_soln[0] * exact_soln[0] * W;
553 error += (exact_soln[0] - w_fe) * (exact_soln[0] - w_fe) * W;
554 }
555 }
556 }
557
558
559 //====================================================================
560 // Force build of templates
561 //====================================================================
562 template class AxisymFoepplvonKarmanElement<2>;
563 template class AxisymFoepplvonKarmanElement<3>;
564 template class AxisymFoepplvonKarmanElement<4>;
565
566} // namespace oomph
static char t char * s
Definition: cfortran.h:568
//////////////////////////////////////////////////////////////////////// ////////////////////////////...
static const unsigned Initial_Nvalue
Static int that holds the number of variables at nodes: always the same.
const double & eta() const
FvK parameter.
void output(std::ostream &outfile)
Output with default number of plot points.
void fill_in_contribution_to_residuals(Vector< double > &residuals)
Fill in the residuals with this element's contribution.
bool interpolated_stress(const Vector< double > &s, double &sigma_r_r, double &sigma_phi_phi) const
Compute in-plane stresses. Return boolean to indicate success (false if attempt to evaluate stresses ...
unsigned self_test()
Self-test: Return 0 for OK.
virtual double dshape_and_dtest_eulerian_at_knot_axisym_fvk(const unsigned &ipt, Shape &psi, DShape &dpsidr, Shape &test, DShape &dtestdr) const =0
Shape/test functions and derivs w.r.t. to global coords at integration point ipt; return Jacobian of ...
virtual unsigned nodal_index_fvk(const unsigned &i=0) const
Return the index at which the i-th unknown value is stored. The default value, i, is appropriate for ...
bool Linear_bending_model
Flag which stores whether we are using a linear, pure bending model instead of the full non-linear Fo...
void output_fct(std::ostream &outfile, const unsigned &n_plot, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt)
Output exact soln: r,w_exact at n_plot plot points.
void compute_error(std::ostream &outfile, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt, double &error, double &norm)
Get error against and norm of exact solution.
double interpolated_u_fvk(const Vector< double > &s) const
Return FE representation of radial displacement.
double interpolated_w_fvk(const Vector< double > &s) const
Return FE representation of transverse displacement.
virtual void get_pressure_fvk(const unsigned &ipt, const double &r, double &pressure) const
Get pressure term at (Eulerian) position r. This function is virtual to allow overloading in multi-ph...
const double & nu() const
Poisson's ratio.
A Class for the derivatives of shape functions The class design is essentially the same as Shape,...
Definition: shape.h:278
virtual double J_eulerian(const Vector< double > &s) const
Return the Jacobian of mapping from local to global coordinates at local position s.
Definition: elements.cc:4103
Integral *const & integral_pt() const
Return the pointer to the integration scheme (const version)
Definition: elements.h:1963
double nodal_value(const unsigned &n, const unsigned &i) const
Return the i-th value stored at local node n. Produces suitably interpolated values for hanging nodes...
Definition: elements.h:2593
virtual std::string tecplot_zone_string(const unsigned &nplot) const
Return string for tecplot zone header (when plotting nplot points in each "coordinate direction")
Definition: elements.h:3161
virtual double interpolated_x(const Vector< double > &s, const unsigned &i) const
Return FE interpolated coordinate x[i] at local coordinate s.
Definition: elements.cc:3962
int nodal_local_eqn(const unsigned &n, const unsigned &i) const
Return the local equation number corresponding to the i-th value at the n-th local node.
Definition: elements.h:1432
unsigned dim() const
Return the spatial dimension of the element, i.e. the number of local coordinates required to paramet...
Definition: elements.h:2611
unsigned nnode() const
Return the number of nodes.
Definition: elements.h:2210
void(* SteadyExactSolutionFctPt)(const Vector< double > &, Vector< double > &)
Function pointer for function that computes vector-valued steady "exact solution" as .
Definition: elements.h:1759
virtual void get_s_plot(const unsigned &i, const unsigned &nplot, Vector< double > &s, const bool &shifted_to_interior=false) const
Get cector of local coordinates of plot point i (when plotting nplot points in each "coordinate direc...
Definition: elements.h:3148
virtual unsigned nplot_points(const unsigned &nplot) const
Return total number of plot points (when plotting nplot points in each "coordinate direction")
Definition: elements.h:3186
double dshape_eulerian(const Vector< double > &s, Shape &psi, DShape &dpsidx) const
Compute the geometric shape functions and also first derivatives w.r.t. global coordinates at local c...
Definition: elements.cc:3298
double raw_nodal_value(const unsigned &n, const unsigned &i) const
Return the i-th value stored at local node n but do NOT take hanging nodes into account.
Definition: elements.h:2576
double raw_nodal_position(const unsigned &n, const unsigned &i) const
Return the i-th coordinate at local node n. Do not use the hanging node representation....
Definition: elements.cc:1686
virtual void write_tecplot_zone_footer(std::ostream &outfile, const unsigned &nplot) const
Add tecplot zone "footer" to output stream (when plotting nplot points in each "coordinate direction"...
Definition: elements.h:3174
virtual unsigned self_test()
Self-test: Check inversion of element & do self-test for GeneralisedElement. Return 0 if OK.
Definition: elements.cc:4440
virtual double knot(const unsigned &i, const unsigned &j) const =0
Return local coordinate s[j] of i-th integration point.
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.
A Class for shape functions. In simple cases, the shape functions have only one index that can be tho...
Definition: shape.h:76
//////////////////////////////////////////////////////////////////// ////////////////////////////////...