elastic_problems.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
27#include "problem.h"
28#include "fsi.h"
29#include "elastic_problems.h"
30
31
32namespace oomph
33{
34 //////////////////////////////////////////////////////////////////////////
35 //////////////////////////////////////////////////////////////////////////
36 //////////////////////////////////////////////////////////////////////////
37
38
39 //======================================================================
40 /// Setup IC problem by:
41 /// - Pinning all nodal values in the mesh
42 /// - Pinning the internal data of all elements.
43 /// - Freeing/unpinnning all positional data.
44 /// - Flushing the pointers to the elements' external data.
45 /// - Setting the pointer to the IC object for all elements to
46 /// ensure that the correct residuals/Jacobians are computed.
47 //======================================================================
49 {
50 // Find out how many nodes there are
51 unsigned long n_node = mesh_pt()->nnode();
52
53 // Loop over all the nodes
54 for (unsigned n = 0; n < n_node; n++)
55 {
56 // Cast to an elastic node
57 SolidNode* node_pt = dynamic_cast<SolidNode*>(mesh_pt()->node_pt(n));
58
59#ifdef PARANOID
60 if (node_pt == 0)
61 {
62 throw OomphLibError("Wasn't able to cast to SolidNode\n",
65 }
66#endif
67
68 // Get spatial dimension of node
69 unsigned ndim = node_pt->ndim();
70
71 // Find out how many positional dofs there are
73 dynamic_cast<SolidFiniteElement*>(mesh_pt()->element_pt(0));
74
75#ifdef PARANOID
76 if (elem_pt == 0)
77 {
78 throw OomphLibError("Wasn't able to cast to SolidFiniteElement\n",
81 }
82#endif
83
85
86 // Loop over coordinate directions
87 for (unsigned i = 0; i < ndim; i++)
88 {
89 // Loop over type of dof
90 for (unsigned k = 0; k < ntype; k++)
91 {
92 // Unpin them
93 node_pt->unpin_position(k, i);
94 }
95 }
96
97 // Loop over nodal values
98 unsigned nval = node_pt->nvalue();
99 for (unsigned ival = 0; ival < nval; ival++)
100 {
101 // Pin them
102 node_pt->pin(ival);
103 }
104 }
105
106
107 // Loop over the elements
108 unsigned Nelement = mesh_pt()->nelement();
109 for (unsigned i = 0; i < Nelement; i++)
110 {
111 // Cast to proper element type
113 dynamic_cast<SolidFiniteElement*>(mesh_pt()->element_pt(i));
114
115#ifdef PARANOID
116 if (elem_pt == 0)
117 {
118 throw OomphLibError("Wasn't able to cast to SolidFiniteElement\n",
121 }
122#endif
123
124
125 // Set flag for setting initial condition
126 elem_pt->solid_ic_pt() = IC_pt;
127
128 // We've backed up the element's external data: Flush it
130
131 // IF it's an FSI wall element then kill external stuff
132 if (FSIWallElement* fsi_elem_pt = dynamic_cast<FSIWallElement*>(elem_pt))
133 {
134 fsi_elem_pt->exclude_external_load_data();
135 }
136
137 // Find out number of internal data
138 unsigned nint = elem_pt->ninternal_data();
139
140 // Loop over internal data
141 for (unsigned j = 0; j < nint; j++)
142 {
144
145 // Loop over internal values
146 unsigned nval = data_pt->nvalue();
147 for (unsigned ival = 0; ival < nval; ival++)
148 {
149 // Pin internal values
150 data_pt->pin(ival);
151 }
152 }
153
154#ifdef PARANOID
155 // Is there internal solid data
156 if (elem_pt->has_internal_solid_data())
157 {
158 std::string error_message =
159 "Automatic assignment of initial conditions doesn't work yet\n";
160 error_message +=
161 "for elasticity elements with internal solid dofs (pressures)\n";
162
163 throw OomphLibError(
165 }
166#endif
167 // for(unsigned i=0;i<nint_solid;i++)
168 // {
169 // Data* data_pt=elem_pt->internal_solid_data_pt(i);
170
171 // // Loop over values
172 // unsigned nval=data_pt->nvalue();
173 // for (unsigned ival=0;ival<nval;ival++)
174 // {
175 // // Pin internal values
176 // data_pt->pin(ival);
177 // }
178 // }
179 }
180
181 // Setup equation numbers for IC problem
182 oomph_info << "# of dofs for wall initial guess" << assign_eqn_numbers()
183 << std::endl;
184 }
185
186
187 //======================================================================
188 /// Backup pinned status of all data associated with the mesh.
189 /// Also backup the (pointers to the) elements' external data.
190 //======================================================================
192 {
193 // Find out how many nodes there are
194 unsigned long n_node = mesh_pt()->nnode();
195
196 // Flush vector which holds backup of pinned status
197 Backup_pinned.clear();
198
199 // Flush vector which holds vectors with backup of (pointers to) external
200 // data
201 Backup_ext_data.clear();
202
203 // Loop over all the nodes
204 for (unsigned n = 0; n < n_node; n++)
205 {
206 // Cast to an elastic node
207 SolidNode* node_pt = dynamic_cast<SolidNode*>(mesh_pt()->node_pt(n));
208
209#ifdef PARANOID
210 if (node_pt == 0)
211 {
212 throw OomphLibError("Wasn't able to cast to SolidNode\n",
215 }
216#endif
217
218 // Get spatial dimension of node
219 unsigned ndim = node_pt->ndim();
220
221 // Find out how many positional dofs there are
223 dynamic_cast<SolidFiniteElement*>(mesh_pt()->element_pt(0));
224
225#ifdef PARANOID
226 if (elem_pt == 0)
227 {
228 throw OomphLibError("Wasn't able to cast to SolidFiniteElement\n",
231 }
232#endif
233
234 unsigned ntype = elem_pt->nnodal_position_type();
235
236
237 // Loop over coordinate directions
238 for (unsigned i = 0; i < ndim; i++)
239 {
240 // Loop over type of dof
241 for (unsigned k = 0; k < ntype; k++)
242 {
243 // Backup pinned status
244 Backup_pinned.push_back(node_pt->position_is_pinned(k, i));
245 }
246 }
247
248 // Loop over nodal values
249 unsigned nval = node_pt->nvalue();
250 for (unsigned ival = 0; ival < nval; ival++)
251 {
252 // Backup pinned status
253 Backup_pinned.push_back(node_pt->is_pinned(ival));
254 }
255 }
256
257 // Loop over the elements
258 unsigned Nelement = mesh_pt()->nelement();
259 Backup_ext_data.resize(Nelement);
260 for (unsigned i = 0; i < Nelement; i++)
261 {
262 // Cast to proper element type
264 dynamic_cast<SolidFiniteElement*>(mesh_pt()->element_pt(i));
265
266#ifdef PARANOID
267 if (elem_pt == 0)
268 {
269 throw OomphLibError("Wasn't able to cast to SolidFiniteElement\n",
272 }
273#endif
274
275 // Find out number of external data
276 unsigned next = elem_pt->nexternal_data();
277 Backup_ext_data[i].resize(next);
278
279 // Loop over external data
280 for (unsigned j = 0; j < next; j++)
281 {
283
284 // Backup the pointer to external data
286 }
287
288 // Find out number of internal data
289 unsigned nint = elem_pt->ninternal_data();
290
291 // Loop over internal data
292 for (unsigned j = 0; j < nint; j++)
293 {
295
296 // Loop over internal values
297 unsigned nval = data_pt->nvalue();
298 for (unsigned ival = 0; ival < nval; ival++)
299 {
300 // Backup pinned status
301 Backup_pinned.push_back(data_pt->is_pinned(ival));
302 }
303 }
304
305
306#ifdef PARANOID
307 // If there is internal solid data, complain
308 if (elem_pt->has_internal_solid_data())
309 {
310 std::string error_message =
311 "Automatic assignment of initial conditions doesn't work yet\n";
312 error_message +=
313 "for elasticity elements with internal solid dofs (pressures)\n";
314
315 throw OomphLibError(
317 }
318#endif
319 // for(unsigned i=0;i<nint_solid;i++)
320 // {
321 // Data* data_pt=elem_pt->internal_solid_data_pt(i);
322
323 // // Loop over values
324 // unsigned nval=data_pt->nvalue();
325 // for (unsigned ival=0;ival<nval;ival++)
326 // {
327 // // Backup pinned status
328 // Backup_pinned.push_back(data_pt->is_pinned(ival));
329 // }
330 // }
331 }
332
333 // Record number of dofs whose status was pinned
334 // oomph_info << "Number of backed up values " << Backup_pinned.size() <<
335 // std::endl;
336 }
337
338
339 //======================================================================
340 /// Reset pinned status of all data and re-instate the pointers
341 /// to the elements' external data.
342 //======================================================================
344 {
345 // Find out how many nodes there are
346 unsigned long n_node = mesh_pt()->nnode();
347
348 // Initialise counter for backed up dofs
349 unsigned count = 0;
350
351 // Loop over all the nodes
352 for (unsigned n = 0; n < n_node; n++)
353 {
354 // Cast to an elastic node
355 SolidNode* node_pt = dynamic_cast<SolidNode*>(mesh_pt()->node_pt(n));
356
357#ifdef PARANOID
358 if (node_pt == 0)
359 {
360 throw OomphLibError("Wasn't able to cast to SolidNode\n",
363 }
364#endif
365
366 // Get spatial dimension of node
367 unsigned ndim = node_pt->ndim();
368
369 // Find out how many positional dofs there are
371 dynamic_cast<SolidFiniteElement*>(mesh_pt()->element_pt(0));
372
373#ifdef PARANOID
374 if (elem_pt == 0)
375 {
376 throw OomphLibError("Wasn't able to cast to SolidFiniteElement\n",
379 }
380#endif
381
382 unsigned ntype = elem_pt->nnodal_position_type();
383
384 // Loop over coordinate directions
385 for (unsigned i = 0; i < ndim; i++)
386 {
387 // Loop over type of dof
388 for (unsigned k = 0; k < ntype; k++)
389 {
390 // Reset pinned status (positional dofs were all unpinned)
391 if (Backup_pinned[count])
392 {
393 node_pt->pin_position(k, i);
394 }
395 count++;
396 }
397 }
398
399 // Loop over nodal values
400 unsigned nval = node_pt->nvalue();
401 for (unsigned ival = 0; ival < nval; ival++)
402 {
403 // Reset pinned status (nodal values were all pinned)
404 if (Backup_pinned[count])
405 {
406 node_pt->unpin(ival);
407 }
408 }
409 }
410
411
412 // Loop over the elements
413 unsigned Nelement = mesh_pt()->nelement();
414 for (unsigned i = 0; i < Nelement; i++)
415 {
416 // Cast to proper element type
418 dynamic_cast<SolidFiniteElement*>(mesh_pt()->element_pt(i));
419
420#ifdef PARANOID
421 if (elem_pt == 0)
422 {
423 throw OomphLibError("Wasn't able to cast to SolidFiniteElement\n",
426 }
427#endif
428
429 // Switch back to normal Jacobian
430 dynamic_cast<SolidFiniteElement*>(elem_pt)
431 ->disable_solve_for_consistent_newmark_accel();
432
433 // Switch off flag for setting initial condition
434 dynamic_cast<SolidFiniteElement*>(elem_pt)->solid_ic_pt() = 0;
435
436 // IF it's an FSI wall element then turn on external stuff again
437 if (FSIWallElement* fsi_elem_pt = dynamic_cast<FSIWallElement*>(elem_pt))
438 {
439 fsi_elem_pt->include_external_load_data();
440 }
441
442 // Find out number of external data
443 unsigned next = Backup_ext_data[i].size();
444
445 // Loop over external data
446 for (unsigned j = 0; j < next; j++)
447 {
448 // Backed up external data
450
451 // Add external data
453 }
454
455 // Find out number of internal data
456 unsigned nint = elem_pt->ninternal_data();
457
458 // Loop over internal data
459 for (unsigned j = 0; j < nint; j++)
460 {
462
463 // Loop over internal values
464 unsigned nval = data_pt->nvalue();
465 for (unsigned ival = 0; ival < nval; ival++)
466 {
467 // Restore pinned status (values were all pinned)
468 if (!Backup_pinned[count])
469 {
470 data_pt->unpin(ival);
471 }
472 }
473 }
474
475
476#ifdef PARANOID
477 // If there is internal solid data, complain
478 if (elem_pt->has_internal_solid_data())
479 {
480 std::string error_message =
481 "Automatic assignment of initial conditions doesn't work yet\n";
482 error_message +=
483 "for elasticity elements with internal solid dofs (pressures)\n";
484
485 throw OomphLibError(
487 }
488#endif
489 // for(unsigned i=0;i<nint_solid;i++)
490 // {
491 // Data* data_pt=elem_pt->internal_solid_data_pt(i);
492
493 // // Loop over values
494 // unsigned nval=data_pt->nvalue();
495 // for (unsigned ival=0;ival<nval;ival++)
496 // {
497 // // Restore pinned status (values were all pinned)
498 // if (!Backup_pinned[count])
499 // {
500 // data_pt->unpin(ival);
501 // }
502 // }
503 // }
504 }
505
506 // Check number of recovered pinned values
507 // oomph_info << "Recovered pin values " << count << std::endl;
508
509 // Flush vector which holds backup of pinned status
510 Backup_pinned.clear();
511
512 // Flush vector which holds vectors with backup of (pointers to) external
513 // data
514 Backup_ext_data.clear();
515 }
516
517
518 //======================================================================
519 /// IC problem for wall: Deform wall into the static initial shape
520 /// described by the IC object at given time.
521 //======================================================================
523 Problem* problem_pt,
526 const double& time)
527 {
528 // Tell this sub-problem it is distributed if the main problem is
529 // distributed
530#ifdef OOMPH_HAS_MPI
531 if (problem_pt->problem_has_been_distributed())
532 {
534 }
535 // This (sub-)problem needs to know about the oomph communicator
536 delete Communicator_pt;
538#endif
539
540
541 // Backup value of time
542 double backup_time = 0.0;
543
544 // Set value of time for IC object (needs to be backed up and
545 // restored since it might be pointed to by other objects)
546 TimeStepper* timestepper_pt = ic_pt->geom_object_pt()->time_stepper_pt();
547 if (timestepper_pt != 0)
548 {
549 backup_time = timestepper_pt->time_pt()->time();
550 timestepper_pt->time_pt()->time() = time;
551 }
552
553 // Delete dummy mesh
554 delete mesh_pt();
555
556 // Set pointer to mesh
558
559 // Set pointer to initial condition object
560 IC_pt = ic_pt;
561
562 // Backup the pinned status of all dofs and remove external data
563 // of all elements
565
566 // Now alter the pinned status so that the IC problem for the
567 // positional variables can be solved; setup equation numbering
568 // scheme
570
571 // Choose the right linear solver
572#if defined(OOMPH_HAS_MUMPS) && \
573 defined(OOMPH_ENABLE_MUMPS_AS_DEFAULT_LINEAR_SOLVER)
575#else
577#endif
578
579 // Assign displacements
580 IC_pt->ic_time_deriv() = 0;
581
582 // Solve the problem for initial shape
583 newton_solve();
584
585 // Impulsive start
587
588 // Reset the pinned status and re-attach the external data to the elements
590
591 // Reset time
592 if (timestepper_pt != 0)
593 {
594 timestepper_pt->time_pt()->time() = backup_time;
595 }
596
597 // Set pointer to dummy mesh so there's something that can be deleted
598 // when static problem finally goes out of scope.
599 mesh_pt() = new DummyMesh;
600
601 // We have temporarily over-written equation numbers -- need
602 // to reset them now
603 oomph_info << "Number of equations in big problem: "
604 << problem_pt->assign_eqn_numbers() << std::endl;
605 }
606
607} // namespace oomph
cstr elem_len * i
Definition cfortran.h:603
A class that represents a collection of data; each Data object may contain many different individual ...
Definition nodes.h:86
void pin(const unsigned &i)
Pin the i-th stored variable.
Definition nodes.h:385
void unpin(const unsigned &i)
Unpin the i-th stored variable.
Definition nodes.h:391
unsigned nvalue() const
Return number of values stored in data object (incl pinned ones).
Definition nodes.h:483
bool is_pinned(const unsigned &i) const
Test whether the i-th variable is pinned (1: true; 0: false).
Definition nodes.h:417
Dummy mesh that can be created and deleted in SolidICProblem.
This is a base class for all SolidFiniteElements that participate in FSI computations....
Definition fsi.h:194
unsigned nnodal_position_type() const
Return the number of coordinate types that the element requires to interpolate the geometry between t...
Definition elements.h:2467
double size() const
Calculate the size of the element (length, area, volume,...) in Eulerian computational coordinates....
Definition elements.cc:4320
unsigned nexternal_data() const
Return the number of external data objects.
Definition elements.h:816
Data *& external_data_pt(const unsigned &i)
Return a pointer to i-th external data object.
Definition elements.h:642
Data *& internal_data_pt(const unsigned &i)
Return a pointer to i-th internal data object.
Definition elements.h:605
unsigned ninternal_data() const
Return the number of internal data objects.
Definition elements.h:810
void flush_external_data()
Flush all external data.
Definition elements.cc:392
unsigned add_external_data(Data *const &data_pt, const bool &fd=true)
Add a (pointer to an) external data object to the element and return its index (i....
Definition elements.cc:312
TimeStepper *& time_stepper_pt()
Access function for pointer to time stepper: Null if object is not time-dependent.
A general mesh class.
Definition mesh.h:67
Node *& node_pt(const unsigned long &n)
Return pointer to global node n.
Definition mesh.h:440
unsigned long nnode() const
Return number of nodes in the mesh.
Definition mesh.h:604
GeneralisedElement *& element_pt(const unsigned long &e)
Return pointer to element e.
Definition mesh.h:452
unsigned long nelement() const
Return number of elements in the mesh.
Definition mesh.h:598
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
Definition nodes.h:1054
An oomph-lib wrapper to the MPI_Comm communicator object. Just contains an MPI_Comm object (which is ...
An OomphLibError object which should be thrown when an run-time error is encountered....
////////////////////////////////////////////////////////////////// //////////////////////////////////...
Definition problem.h:154
unsigned long assign_eqn_numbers(const bool &assign_local_eqn_numbers=true)
Assign all equation numbers for problem: Deals with global data (= data that isn't attached to any el...
Definition problem.cc:2085
void assign_initial_values_impulsive()
Initialise data and nodal positions to simulate impulsive start from initial configuration/solution.
Definition problem.cc:11575
OomphCommunicator * communicator_pt()
access function to the oomph-lib communicator
Definition problem.h:1266
bool Problem_has_been_distributed
Has the problem been distributed amongst multiple processors?
Definition problem.h:984
void newton_solve()
Use Newton method to solve the problem.
Definition problem.cc:8816
OomphCommunicator * Communicator_pt
The communicator for this problem.
Definition problem.h:1262
bool problem_has_been_distributed()
Access to Problem_has_been_distributed flag.
Definition problem.h:2283
LinearSolver *& linear_solver_pt()
Return a pointer to the linear solver object.
Definition problem.h:1486
double & time()
Return the current value of continuous time.
Definition problem.cc:11607
Mesh *& mesh_pt()
Return a pointer to the global mesh.
Definition problem.h:1300
SolidFiniteElement class.
Definition elements.h:3565
void backup_original_state()
Backup original state of all data associated with mesh.
Vector< Vector< Data * > > Backup_ext_data
Vector of Vectors to store pointers to exernal data in the elements.
MumpsSolver * Mumps_solver_pt
Pointer to mumps solver.
void setup_problem()
Change pinned status of all data associated with mesh so that the IC problem can be solved.
void set_static_initial_condition(Problem *problem_pt, Mesh *mesh_pt, SolidInitialCondition *ic_pt, const double &time)
Force the elastic structure that is discretised on the specified mesh to deform in the shape of the i...
Vector< int > Backup_pinned
Vector to store pinned status of all data.
SuperLUSolver * SuperLU_solver_pt
Pointer to mumps solver.
void reset_original_state()
Reset original state of all data associated with mesh.
SolidInitialCondition * IC_pt
Pointer to initial condition object.
A class to specify the initial conditions for a solid body. Solid bodies are often discretised with H...
Definition elements.h:3500
unsigned & ic_time_deriv()
Which time derivative are we currently assigning?
Definition elements.h:3521
A Class for nodes that deform elastically (i.e. position is an unknown in the problem)....
Definition nodes.h:1686
void pin_position(const unsigned &i)
Pin the nodal position.
Definition nodes.h:1816
void unpin_position(const unsigned &i)
Unpin the nodal position.
Definition nodes.h:1829
bool position_is_pinned(const unsigned &i)
Test whether the i-th coordinate is pinned, 0: false; 1: true.
Definition nodes.h:1803
TAdvectionDiffusionReactionElement<NREAGENT,DIM,NNODE_1D> elements are isoparametric triangular DIM-d...
Base class for time-stepping schemes. Timestepper provides an approximation of the temporal derivativ...
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...