linear_wave_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-2025 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#include <cmath>
27
28// Non-inline functions for LinearWave elements
30
31
32namespace oomph
33{
34 /// 2D LinearWave elements
35
36
37 //======================================================================
38 // Set the data for the number of Variables at each node
39 //======================================================================
40 template<>
41 const unsigned QLinearWaveElement<1, 4>::Initial_Nvalue[4] = {1, 1, 1, 1};
42 template<>
43 const unsigned QLinearWaveElement<1, 3>::Initial_Nvalue[3] = {1, 1, 1};
44 template<>
45 const unsigned QLinearWaveElement<1, 2>::Initial_Nvalue[2] = {1, 1};
46
47 template<>
49 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
50 template<>
52 1, 1, 1, 1, 1, 1, 1, 1, 1};
53 template<>
54 const unsigned QLinearWaveElement<2, 2>::Initial_Nvalue[4] = {1, 1, 1, 1};
55
56 template<>
58 1, 1, 1, 1, 1, 1, 1, 1};
59 template<>
61 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
62 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
63 template<>
65 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
66 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
67 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
68
69
70 //======================================================================
71 /// Compute element residual Vector and/or element Jacobian matrix
72 ///
73 /// flag=1: compute both
74 /// flag=0: compute only residual Vector
75 ///
76 /// Pure version without hanging nodes
77 //======================================================================
78 template<unsigned DIM>
81 {
82 // Find out how many nodes there are
83 unsigned n_node = nnode();
84
85 // Get continuous time from timestepper of first node
86 double time = node_pt(0)->time_stepper_pt()->time_pt()->time();
87
88 // Find the index at which the linear wave unknown is stored
89 unsigned u_nodal_index = u_index_lin_wave();
90
91 // Set up memory for the shape and test functions
94
95 // Set the value of n_intpt
96 unsigned n_intpt = integral_pt()->nweight();
97
98 // Set the Vector to hold local coordinates
100
101 // Integers to hold the local equation and unknowns
102 int local_eqn = 0, local_unknown = 0;
103
104 // Loop over the integration points
105 for (unsigned ipt = 0; ipt < n_intpt; ipt++)
106 {
107 // Assign values of s
108 for (unsigned i = 0; i < DIM; i++) s[i] = integral_pt()->knot(ipt, i);
109
110 // Get the integral weight
111 double w = integral_pt()->weight(ipt);
112
113 // Call the derivatives of the shape and test functions
114 double J = dshape_and_dtest_eulerian_at_knot_lin_wave(
116
117 // Premultiply the weights and the Jacobian
118 double W = w * J;
119
120 // Allocate memory for local quantities and initialise to zero
121 double interpolated_u = 0.0;
122 double ddudt = 0.0;
124 Vector<double> interpolated_dudx(DIM, 0.0);
125
126 // Calculate function value and derivatives:
127 // Loop over nodes
128 for (unsigned l = 0; l < n_node; l++)
129 {
130 // Get the nodal value
132 interpolated_u += u_value * psi(l);
133 ddudt += d2u_dt2_lin_wave(l) * psi(l);
134 // Loop over directions
135 for (unsigned j = 0; j < DIM; j++)
136 {
138 interpolated_dudx[j] += u_value * dpsidx(l, j);
139 }
140 }
141
142
143 // Get source function
144 //-------------------
145 double source;
146 get_source_lin_wave(time, ipt, interpolated_x, source);
147
148 // Assemble residuals and Jacobian
149 //--------------------------------
150
151 // Loop over the test functions
152 for (unsigned l = 0; l < n_node; l++)
153 {
155 /*IF it's not a boundary condition*/
156 if (local_eqn >= 0)
157 {
158 // Add body force/source term and time derivative
159 residuals[local_eqn] += (ddudt + source) * test(l) * W;
160
161 // Laplace operator
162 for (unsigned k = 0; k < DIM; k++)
163 {
164 residuals[local_eqn] += interpolated_dudx[k] * dtestdx(l, k) * W;
165 }
166
167
168 // Calculate the jacobian
169 //-----------------------
170 if (flag)
171 {
172 // Loop over the velocity shape functions again
173 for (unsigned l2 = 0; l2 < n_node; l2++)
174 {
176 // If at a non-zero degree of freedom add in the entry
177 if (local_unknown >= 0)
178 {
179 // Mass matrix
180 jacobian(local_eqn, local_unknown) +=
181 test(l) * psi(l2) *
182 node_pt(l2)->time_stepper_pt()->weight(2, 0) * W;
183
184 // Laplace operator
185 for (unsigned i = 0; i < DIM; i++)
186 {
187 jacobian(local_eqn, local_unknown) +=
188 dpsidx(l2, i) * dtestdx(l, i) * W;
189 }
190 }
191 }
192 }
193 }
194 }
195
196
197 } // End of loop over integration points
198 }
199
200
201 //======================================================================
202 /// Self-test: Return 0 for OK
203 //======================================================================
204 template<unsigned DIM>
206 {
207 bool passed = true;
208
209 // Check lower-level stuff
210 if (FiniteElement::self_test() != 0)
211 {
212 passed = false;
213 }
214
215 // Return verdict
216 if (passed)
217 {
218 return 0;
219 }
220 else
221 {
222 return 1;
223 }
224 }
225
226
227 //======================================================================
228 /// Output function:
229 ///
230 /// x,y,u or x,y,z,u
231 ///
232 /// nplot points in each coordinate direction
233 //======================================================================
234 template<unsigned DIM>
236 const unsigned& nplot)
237 {
238 // Vector of local coordinates
240
241 // Tecplot header info
243
244 // Loop over plot points
246 for (unsigned iplot = 0; iplot < num_plot_points; iplot++)
247 {
248 // Get local coordinates of plot point
250 for (unsigned i = 0; i < DIM; i++)
251 {
252 outfile << interpolated_x(s, i) << " ";
253 }
254 outfile << interpolated_u_lin_wave(s) << " ";
255 outfile << interpolated_du_dt_lin_wave(s) << " ";
256 outfile << interpolated_d2u_dt2_lin_wave(s) << std::endl;
257 }
258
259 // Write tecplot footer (e.g. FE connectivity lists)
261 }
262
263 //======================================================================
264 /// C-style output function:
265 ///
266 /// x,y,u or x,y,z,u
267 ///
268 /// nplot points in each coordinate direction
269 //======================================================================
270 template<unsigned DIM>
272 {
273 // Vector of local coordinates
275
276 // Tecplot header info
278
279 // Loop over plot points
281 for (unsigned iplot = 0; iplot < num_plot_points; iplot++)
282 {
283 // Get local coordinates of plot point
285
286 for (unsigned i = 0; i < DIM; i++)
287 {
288 // outfile << interpolated_x(s,i) << " ";
289 fprintf(file_pt, "%g ", interpolated_x(s, i));
290 }
291 // outfile << interpolated_u(s) << std::endl;
292 fprintf(file_pt, "%g \n", interpolated_u_lin_wave(s));
293 }
294
295 // Write tecplot footer (e.g. FE connectivity lists)
297 }
298
299
300 //======================================================================
301 /// Output exact solution
302 ///
303 /// Solution is provided via function pointer.
304 /// Plot at a given number of plot points.
305 ///
306 /// x,y,u_exact or x,y,z,u_exact
307 //======================================================================
308 template<unsigned DIM>
310 std::ostream& outfile,
311 const unsigned& nplot,
313 {
314 // Vector of local coordinates
316
317 // Vector for coordintes
319
320 // Tecplot header info
322
323 // Exact solution Vector (value and first and second time derivs)
325
326 // Loop over plot points
328 for (unsigned iplot = 0; iplot < num_plot_points; iplot++)
329 {
330 // Get local coordinates of plot point
332
333 // Get x position as Vector
334 interpolated_x(s, x);
335
336 // Get exact solution at this point
337 (*exact_soln_pt)(x, exact_soln);
338
339 // Output x,y,...,u_exact
340 for (unsigned i = 0; i < DIM; i++)
341 {
342 outfile << x[i] << " ";
343 }
344 outfile << exact_soln[0] << std::endl;
345 }
346
347 // Write tecplot footer (e.g. FE connectivity lists)
349 }
350
351
352 //======================================================================
353 /// Output exact solution at time t
354 ///
355 /// Solution is provided via function pointer.
356 /// Plot at a given number of plot points.
357 ///
358 /// x,y,u_exact or x,y,z,u_exact
359 //======================================================================
360 template<unsigned DIM>
362 std::ostream& outfile,
363 const unsigned& nplot,
364 const double& time,
366 {
367 // Vector of local coordinates
369
370 // Vector for coordintes
372
373 // Tecplot header info
375
376 // Exact solution Vector u, dudt, d2udt2
378
379 // Loop over plot points
381 for (unsigned iplot = 0; iplot < num_plot_points; iplot++)
382 {
383 // Get local coordinates of plot point
385
386 // Get x position as Vector
387 interpolated_x(s, x);
388
389 // Get exact solution at this point
390 (*exact_soln_pt)(time, x, exact_soln);
391
392 // Output x,y,...,u_exact
393 for (unsigned i = 0; i < DIM; i++)
394 {
395 outfile << x[i] << " ";
396 }
397 outfile << exact_soln[0] << " " << exact_soln[1] << " " << exact_soln[2]
398 << " " << std::endl;
399 }
400
401 // Write tecplot footer (e.g. FE connectivity lists)
403 }
404
405
406 //======================================================================
407 /// Validate against exact solution
408 ///
409 /// Solution is provided via function pointer.
410 /// Plot error at a given number of plot points.
411 ///
412 //======================================================================
413 template<unsigned DIM>
415 std::ostream& outfile,
417 double& error,
418 double& norm)
419 {
420 // Initialise
421 error = 0.0;
422 norm = 0.0;
423
424 // Vector of local coordinates
426
427 // Vector for coordintes
429
430
431 // Find out how many nodes there are in the element
432 unsigned n_node = nnode();
433
435
436 // Set the value of n_intpt
437 unsigned n_intpt = integral_pt()->nweight();
438
439 // Tecplot header info
440 outfile << "ZONE" << std::endl;
441
442 // Exact solution Vector (value, and first and second time derivs)
444
445 // Loop over the integration points
446 for (unsigned ipt = 0; ipt < n_intpt; ipt++)
447 {
448 // Assign values of s
449 for (unsigned i = 0; i < DIM; i++)
450 {
451 s[i] = integral_pt()->knot(ipt, i);
452 }
453
454 // Get the integral weight
455 double w = integral_pt()->weight(ipt);
456
457 // Get jacobian of mapping
458 double J = J_eulerian(s);
459
460 // Premultiply the weights and the Jacobian
461 double W = w * J;
462
463 // Get x position as Vector
464 interpolated_x(s, x);
465
466 // Get FE function value
467 double u_fe = interpolated_u_lin_wave(s);
468
469 // Get exact solution at this point
470 (*exact_soln_pt)(x, exact_soln);
471
472 // Output x,y,...,error
473 for (unsigned i = 0; i < DIM; i++)
474 {
475 outfile << x[i] << " ";
476 }
477 outfile << exact_soln[0] << " " << exact_soln[0] - u_fe << std::endl;
478
479 // Add to error and norm
480 norm += exact_soln[0] * exact_soln[0] * W;
481 error += (exact_soln[0] - u_fe) * (exact_soln[0] - u_fe) * W;
482 }
483 }
484
485
486 //======================================================================
487 /// Validate against exact solution at time t.
488 ///
489 /// Solution is provided via function pointer.
490 /// Plot error at a given number of plot points.
491 ///
492 //======================================================================
493 template<unsigned DIM>
495 std::ostream& outfile,
497 const double& time,
498 double& error,
499 double& norm)
500
501 {
502 // Initialise
503 error = 0.0;
504 norm = 0.0;
505
506 // Vector of local coordinates
508
509 // Vector for coordintes
511
512 // Find out how many nodes there are in the element
513 unsigned n_node = nnode();
514
516
517 // Set the value of n_intpt
518 unsigned n_intpt = integral_pt()->nweight();
519
520 // Tecplot header info
521 outfile << "ZONE" << std::endl;
522
523 // Exact solution Vector (value, and first and second time derivs)
525
526 // Loop over the integration points
527 for (unsigned ipt = 0; ipt < n_intpt; ipt++)
528 {
529 // Assign values of s
530 for (unsigned i = 0; i < DIM; i++)
531 {
532 s[i] = integral_pt()->knot(ipt, i);
533 }
534
535 // Get the integral weight
536 double w = integral_pt()->weight(ipt);
537
538 // Get jacobian of mapping
539 double J = J_eulerian(s);
540
541 // Premultiply the weights and the Jacobian
542 double W = w * J;
543
544 // Get x position as Vector
545 interpolated_x(s, x);
546
547 // Get FE function value
548 double u_fe = interpolated_u_lin_wave(s);
549
550 // Get exact solution at this point
551 (*exact_soln_pt)(time, x, exact_soln);
552
553 // Output x,y,...,error
554 for (unsigned i = 0; i < DIM; i++)
555 {
556 outfile << x[i] << " ";
557 }
558 outfile << exact_soln[0] << " " << exact_soln[0] - u_fe << std::endl;
559
560 // Add to error and norm
561 norm += exact_soln[0] * exact_soln[0] * W;
562 error += (exact_soln[0] - u_fe) * (exact_soln[0] - u_fe) * W;
563 }
564 }
565
566
567 //====================================================================
568 // Force build of templates
569 //====================================================================
570 template class QLinearWaveElement<1, 2>;
571 template class QLinearWaveElement<1, 3>;
572 template class QLinearWaveElement<1, 4>;
573
574 template class QLinearWaveElement<2, 2>;
575 template class QLinearWaveElement<2, 3>;
576 template class QLinearWaveElement<2, 4>;
577
578 template class QLinearWaveElement<3, 2>;
579 template class QLinearWaveElement<3, 3>;
580 template class QLinearWaveElement<3, 4>;
581
582
583} // namespace oomph
static char t char * s
Definition cfortran.h:568
cstr elem_len * i
Definition cfortran.h:603
A Class for the derivatives of shape functions The class design is essentially the same as Shape,...
Definition shape.h:278
TimeStepper *& time_stepper_pt()
Return the pointer to the timestepper.
Definition nodes.h:238
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:4133
Integral *const & integral_pt() const
Return the pointer to the integration scheme (const version)
Definition elements.h:1967
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:3165
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:3992
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:1436
unsigned nnode() const
Return the number of nodes.
Definition elements.h:2214
void(* SteadyExactSolutionFctPt)(const Vector< double > &, Vector< double > &)
Function pointer for function that computes vector-valued steady "exact solution" as .
Definition elements.h:1763
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:3152
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:3190
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition elements.h:2179
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:2580
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:1714
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:3178
void(* UnsteadyExactSolutionFctPt)(const double &, const Vector< double > &, Vector< double > &)
Function pointer for function that computes Vector-valued time-dependent function as .
Definition elements.h:1769
virtual unsigned self_test()
Self-test: Check inversion of element & do self-test for GeneralisedElement. Return 0 if OK.
Definition elements.cc:4470
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.
unsigned self_test()
Self-test: Return 0 for OK.
void output_fct(std::ostream &outfile, const unsigned &nplot, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt)
Output exact soln: x,y,u_exact or x,y,z,u_exact at nplot^DIM 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.
void output(std::ostream &outfile)
Output with default number of plot points.
virtual void fill_in_generic_residual_contribution_lin_wave(Vector< double > &residuals, DenseMatrix< double > &jacobian, unsigned flag)
Compute element residual Vector only (if flag=and/or element Jacobian matrix.
QLinearWaveElement elements are linear/quadrilateral/brick-shaped LinearWave elements with isoparamet...
A Class for shape functions. In simple cases, the shape functions have only one index that can be tho...
Definition shape.h:76
TAdvectionDiffusionReactionElement<NREAGENT,DIM,NNODE_1D> elements are isoparametric triangular DIM-d...
TAdvectionDiffusionReactionElement()
Constructor: Call constructors for TElement and AdvectionDiffusionReaction equations.
virtual double weight(const unsigned &i, const unsigned &j) const
Access function for j-th weight for the i-th derivative.
Time *const & time_pt() const
Access function for the pointer to time (const version)
double & time()
Return the current value of the continuous time.
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).