pseudosolid_node_update_elements.h
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 // This header file contains elements that combine two element types in
27 // a generic way.
28 
29 #ifndef OOMPH_PSEUDO_SOLID_REMESH_ELEMENTS_HEADER
30 #define OOMPH_PSEUDO_SOLID_REMESH_ELEMENTS_HEADER
31 
32 #include "elements.h"
33 
34 namespace oomph
35 {
36  //===========================================================================
38  //===========================================================================
39  namespace PseudoSolidHelper
40  {
43  extern double Zero;
44 
45  } // namespace PseudoSolidHelper
46 
47 
48  //==========================================================================
53  //==========================================================================
54  template<class BASIC, class SOLID>
55  class PseudoSolidNodeUpdateElement : public virtual BASIC,
56  public virtual SOLID
57 
58  {
61 
62  public:
67  {
68  SOLID::lambda_sq_pt() = &PseudoSolidHelper::Zero;
69  }
70 
79  void describe_local_dofs(std::ostream& out,
80  const std::string& current_string) const
81  {
82  BASIC::describe_local_dofs(out, current_string);
83  SOLID::describe_local_dofs(out, current_string);
84  }
85 
88  void compute_norm(double& el_norm)
89  {
90  BASIC::compute_norm(el_norm);
91  }
92 
94  unsigned required_nvalue(const unsigned& n) const
95  {
96  return BASIC::required_nvalue(n) + SOLID::required_nvalue(n);
97  }
98 
103  {
104  // At the moment, we can't handle this case in generality so throw an
105  // error if the solid pressure is stored at the nodes
106  if (SOLID::solid_p_nodal_index() >= 0)
107  {
108  throw OomphLibError("Cannot handle (non-refineable) continuous solid "
109  "pressure interpolation",
112  }
113 
114  return SOLID::solid_p_nodal_index();
115  }
116 
120  {
121  // Call the basic equations first
123  // Add the solid equations contribution
125  }
126 
130  DenseMatrix<double>& jacobian)
131  {
132  // Call the basic equations first
133  BASIC::fill_in_contribution_to_jacobian(residuals, jacobian);
134  // Call the solid equations
135  SOLID::fill_in_contribution_to_jacobian(residuals, jacobian);
136 
137  // Now fill in the off-diagonal entries (the shape derivatives),
138  fill_in_shape_derivatives(jacobian);
139  }
140 
144  Vector<double>& residuals,
145  DenseMatrix<double>& jacobian,
146  DenseMatrix<double>& mass_matrix)
147  {
148  // Call the basic equations first
150  residuals, jacobian, mass_matrix);
151  // Call the solid equations
153  residuals, jacobian, mass_matrix);
154 
155  // Now fill in the off-diagonal entries (the shape derivatives),
156  fill_in_shape_derivatives(jacobian);
157  }
158 
159 
162  {
164  }
165 
168  {
170  }
171 
172 
176  {
177  // Default is to use finite differences
179  {
180  this->fill_in_shape_derivatives_by_fd(jacobian);
181  }
182  // Otherwise need to do a bit more work
183  else
184  {
185  // Calculate storage requirements
186  const unsigned n_dof = this->ndof();
187  const unsigned n_node = this->nnode();
188  const unsigned nodal_dim = this->nodal_dimension();
189 
190  // If there are no nodes or dofs return
191  if ((n_dof == 0) || (n_node == 0))
192  {
193  return;
194  }
195 
196  // Generalised dofs have NOT been considered, shout
197  if (this->nnodal_position_type() != 1)
198  {
199  throw OomphLibError("Shape derivatives do not (yet) allow for "
200  "generalised position dofs\n",
203  }
204 
205  // Storage for derivatives of residuals w.r.t. nodal coordinates
206  RankThreeTensor<double> dresidual_dnodal_coordinates(
207  n_dof, nodal_dim, n_node, 0.0);
208 
209  // Get the analytic derivatives for the BASIC equations
210  BASIC::get_dresidual_dnodal_coordinates(dresidual_dnodal_coordinates);
211 
212  // Now add the appropriate contributions to the Jacobian
213  int local_unknown = 0;
214 
215  // Loop over dofs
216  //(this will include the solid dofs,
217  // but all those contributions should be zero)
218  for (unsigned l = 0; l < n_dof; l++)
219  {
220  // Loop over the nodes
221  for (unsigned n = 0; n < n_node; n++)
222  {
223  // Loop over the position_types (only one)
224  unsigned k = 0;
225  // Loop over the coordinates
226  for (unsigned i = 0; i < nodal_dim; i++)
227  {
228  // Get the equation of the local unknown
229  local_unknown = this->position_local_eqn(n, k, i);
230 
231  // If not pinned, add the contribution to the Jacobian
232  if (local_unknown >= 0)
233  {
234  jacobian(l, local_unknown) +=
235  dresidual_dnodal_coordinates(l, i, n);
236  }
237  }
238  }
239  }
240  }
241  }
242 
243 
247  {
248  // Flag to indicate if we use first or second order FD
249  // bool use_first_order_fd=false;
250 
251  // Find the number of nodes
252  const unsigned n_node = this->nnode();
253 
254  // If there aren't any nodes, then return straight away
255  if (n_node == 0)
256  {
257  return;
258  }
259 
260  // Call the update function to ensure that the element is in
261  // a consistent state before finite differencing starts
262  this->update_before_solid_position_fd();
263 
264  // Get the number of position dofs and dimensions at the node
265  const unsigned n_position_type = this->nnodal_position_type();
266  const unsigned nodal_dim = this->nodal_dimension();
267 
268  // Find the number of dofs in the element
269  const unsigned n_dof = this->ndof();
270 
271  // Create residual newres vectors
272  Vector<double> residuals(n_dof);
273  Vector<double> newres(n_dof);
274  // Vector<double> newres_minus(n_dof);
275 
276  // Calculate the residuals (for the BASIC) equations
277  // Need to do this using fill_in because get_residuals will
278  // compute all residuals for the problem, which is
279  // a little ineffecient
280  for (unsigned m = 0; m < n_dof; m++)
281  {
282  residuals[m] = 0.0;
283  }
285 
286  // Need to determine which degrees of freedom are solid degrees of
287  // freedom
288  // A vector of booleans that will be true if the dof is associated
289  // with the solid equations
290  std::vector<bool> dof_is_solid(n_dof, false);
291 
292  // Now set all solid positional dofs in the vector
293  for (unsigned n = 0; n < n_node; n++)
294  {
295  for (unsigned k = 0; k < n_position_type; k++)
296  {
297  for (unsigned i = 0; i < nodal_dim; i++)
298  {
299  int local_dof = this->position_local_eqn(n, k, i);
300  if (local_dof >= 0)
301  {
302  dof_is_solid[local_dof] = true;
303  }
304  }
305  }
306  }
307 
308  // Add the solid pressures (in solid elements without
309  // solid pressure the number will be zero).
310  unsigned n_solid_pres = this->npres_solid();
311  for (unsigned l = 0; l < n_solid_pres; l++)
312  {
313  int local_dof = this->solid_p_local_eqn(l);
314  if (local_dof >= 0)
315  {
316  dof_is_solid[local_dof] = true;
317  }
318  }
319 
320 
321  // Integer storage for local unknown
322  int local_unknown = 0;
323 
324  // Use default value defined in GeneralisedElement
325  const double fd_step = this->Default_fd_jacobian_step;
326 
327  // Loop over the nodes
328  for (unsigned n = 0; n < n_node; n++)
329  {
330  // Loop over position dofs
331  for (unsigned k = 0; k < n_position_type; k++)
332  {
333  // Loop over dimension
334  for (unsigned i = 0; i < nodal_dim; i++)
335  {
336  // If the variable is free
337  local_unknown = this->position_local_eqn(n, k, i);
338  if (local_unknown >= 0)
339  {
340  // Store a pointer to the (generalised) Eulerian nodal position
341  double* const value_pt = &(this->node_pt(n)->x_gen(k, i));
342 
343  // Save the old value of the (generalised) Eulerian nodal position
344  const double old_var = *value_pt;
345 
346  // Increment the (generalised) Eulerian nodal position
347  *value_pt += fd_step;
348 
349  // Perform any auxialiary node updates
350  this->node_pt(n)->perform_auxiliary_node_update_fct();
351 
352  // Calculate the new residuals
353  // Need to do this using fill_in because get_residuals will
354  // compute all residuals for the problem, which is
355  // a little ineffecient
356  for (unsigned m = 0; m < n_dof; m++)
357  {
358  newres[m] = 0.0;
359  }
361 
362  // if (use_first_order_fd)
363  {
364  // Do forward finite differences
365  for (unsigned m = 0; m < n_dof; m++)
366  {
367  // Stick the entry into the Jacobian matrix
368  // but only if it's not a solid dof
369  if (dof_is_solid[m] == false)
370  {
371  jacobian(m, local_unknown) =
372  (newres[m] - residuals[m]) / fd_step;
373  }
374  }
375  }
376  // else
377  // {
378  // //Take backwards step for the (generalised)
379  // Eulerian nodal
380  // // position
381  // node_pt(n)->x_gen(k,i) = old_var-fd_step;
382 
383  // //Calculate the new residuals at backward position
384  // //BASIC::get_residuals(newres_minus);
385 
386  // //Do central finite differences
387  // for(unsigned m=0;m<n_dof;m++)
388  // {
389  // //Stick the entry into the Jacobian matrix
390  // jacobian(m,local_unknown) =
391  // (newres[m] - newres_minus[m])/(2.0*fd_step);
392  // }
393  // }
394 
395  // Reset the (generalised) Eulerian nodal position
396  *value_pt = old_var;
397 
398  // Perform any auxialiary node updates
399  this->node_pt(n)->perform_auxiliary_node_update_fct();
400  }
401  }
402  }
403  }
404 
405  // End of finite difference loop
406  // Final reset of any dependent data
407  this->reset_after_solid_position_fd();
408  }
409 
410 
415  void identify_geometric_data(std::set<Data*>& geometric_data_pt)
416  {
417  // Loop over the node update data and add to the set
418  const unsigned n_node = this->nnode();
419  for (unsigned j = 0; j < n_node; j++)
420  {
421  geometric_data_pt.insert(
422  dynamic_cast<SolidNode*>(this->node_pt(j))->variable_position_pt());
423  }
424  }
425 
426 
428  void output(std::ostream& outfile)
429  {
430  BASIC::output(outfile);
431  }
432 
435  void output(std::ostream& outfile, const unsigned& n_p)
436  {
437  BASIC::output(outfile, n_p);
438  }
439 
441  void output(FILE* file_pt)
442  {
443  BASIC::output(file_pt);
444  }
445 
447  void output(FILE* file_pt, const unsigned& n_p)
448  {
449  BASIC::output(file_pt, n_p);
450  }
451 
454  unsigned num_Z2_flux_terms()
455  {
456  return BASIC::num_Z2_flux_terms();
457  }
458 
459 
464  std::ostream& outfile,
466  double& error,
467  double& norm)
468  {
469  BASIC::compute_exact_Z2_error(outfile, exact_flux_pt, error, norm);
470  }
471 
475  {
477  }
478 
480  unsigned nvertex_node() const
481  {
482  return BASIC::nvertex_node();
483  }
484 
486  Node* vertex_node_pt(const unsigned& j) const
487  {
488  return BASIC::vertex_node_pt(j);
489  }
490 
493  unsigned nrecovery_order()
494  {
495  return BASIC::nrecovery_order();
496  }
497 
498 
501  unsigned ndof_types() const
502  {
503  return BASIC::ndof_types() + SOLID::ndof_types();
504  }
505 
508  unsigned nbasic_dof_types() const
509  {
510  return BASIC::ndof_types();
511  }
512 
515  unsigned nsolid_dof_types() const
516  {
517  return SOLID::ndof_types();
518  }
519 
529  std::list<std::pair<unsigned long, unsigned>>& dof_lookup_list) const
530  {
531  // get the solid list
532  std::list<std::pair<unsigned long, unsigned>> solid_list;
533  SOLID::get_dof_numbers_for_unknowns(solid_list);
534 
535  // get the basic list
536  BASIC::get_dof_numbers_for_unknowns(dof_lookup_list);
537 
538  // get the number of basic dof types
539  unsigned nbasic_dof_types = BASIC::ndof_types();
540 
541  // add the solid lookup list to the basic lookup list
542  // incrementing the solid dof numbers by nbasic_dof_types
543  typedef std::list<std::pair<unsigned long, unsigned>>::iterator IT;
544  for (IT it = solid_list.begin(); it != solid_list.end(); it++)
545  {
546  std::pair<unsigned long, unsigned> new_pair;
547  new_pair.first = it->first;
548  new_pair.second = it->second + nbasic_dof_types;
549  dof_lookup_list.push_front(new_pair);
550  }
551  }
552  };
553 
555  template<class BASIC, class SOLID>
557  : public virtual FaceGeometry<SOLID>
558  {
559  public:
563  };
564 
566  template<class BASIC, class SOLID>
568  : public virtual FaceGeometry<FaceGeometry<SOLID>>
569  {
570  public:
574 
575  protected:
576  };
577 
578 
579  //===================================================================
581  //===================================================================
582  template<class BASIC, class SOLID>
584  public virtual SOLID
585  {
586  public:
590  : RefineableElement(), BASIC(), SOLID()
591  {
592  SOLID::lambda_sq_pt() = &PseudoSolidHelper::Zero;
593  }
594 
603  void describe_local_dofs(std::ostream& out,
604  const std::string& current_string) const
605  {
606  BASIC::describe_local_dofs(out, current_string);
607  SOLID::describe_local_dofs(out, current_string);
608  }
609 
611  unsigned required_nvalue(const unsigned& n) const
612  {
613  return BASIC::required_nvalue(n) + SOLID::required_nvalue(n);
614  }
615 
618  unsigned ncont_interpolated_values() const
619  {
620  return BASIC::ncont_interpolated_values() +
621  SOLID::ncont_interpolated_values();
622  }
623 
628  {
629  // Find the index in the solid
630  int solid_p_index = SOLID::solid_p_nodal_index();
631  // If there is a solid pressure at the nodes, return the
632  // index after all the BASIC stuff
633  if (solid_p_index >= 0)
634  {
635  return BASIC::ncont_interpolated_values() +
636  SOLID::solid_p_nodal_index();
637  }
638  else
639  {
640  return solid_p_index;
641  }
642  }
643 
647  {
648  // Call the basic equations first
650  // Call the solid equations
652  }
653 
657  DenseMatrix<double>& jacobian)
658  {
659  // Call the basic equations first
660  BASIC::fill_in_contribution_to_jacobian(residuals, jacobian);
661 
662  // Call the solid equations
663  SOLID::fill_in_contribution_to_jacobian(residuals, jacobian);
664 
665  // Now fill in the off-diagonal entries (the shape derivatives),
667  }
668 
672  Vector<double>& residuals,
673  DenseMatrix<double>& jacobian,
674  DenseMatrix<double>& mass_matrix)
675  {
676  // Call the basic equations first
678  residuals, jacobian, mass_matrix);
679  // Call the solid equations
681  residuals, jacobian, mass_matrix);
682 
683  // Now fill in the off-diagonal entries (the shape derivatives),
685  }
686 
687 
692  {
693  // Find the number of nodes
694  const unsigned n_node = this->nnode();
695 
696  // If there are no nodes, return straight away
697  if (n_node == 0)
698  {
699  return;
700  }
701 
702  // Call the update function to ensure that the element is in
703  // a consistent state before finite differencing starts
704  this->update_before_solid_position_fd();
705 
706  // bool use_first_order_fd=false;
707 
708  // Find the number of positional dofs and nodal dimension
709  const unsigned n_position_type = this->nnodal_position_type();
710  const unsigned nodal_dim = this->nodal_dimension();
711 
712  // Find the number of dofs in the element
713  const unsigned n_dof = this->ndof();
714 
715  // Create residual newres vectors
716  Vector<double> residuals(n_dof);
717  Vector<double> newres(n_dof);
718  // Vector<double> newres_minus(n_dof);
719 
720  // Calculate the residuals (for the BASIC) equations
721  // Need to do this using fill_in because get_residuals will
722  // compute all residuals for the problem, which is
723  // a little ineffecient
724  for (unsigned m = 0; m < n_dof; m++)
725  {
726  residuals[m] = 0.0;
727  }
729 
730  // Need to determine which degrees of freedom are solid degrees of
731  // freedom
732  // A vector of booleans that will be true if the dof is associated
733  // with the solid equations
734  std::vector<bool> dof_is_solid(n_dof, false);
735 
736  // Now set all solid positional dofs in the vector
737  // This is a bit more involved because we need to take account of
738  // any hanging nodes
739  for (unsigned n = 0; n < n_node; n++)
740  {
741  // Get pointer to the local node
742  Node* const local_node_pt = this->node_pt(n);
743 
744  // If the node is not a hanging node
745  if (local_node_pt->is_hanging() == false)
746  {
747  for (unsigned k = 0; k < n_position_type; k++)
748  {
749  for (unsigned i = 0; i < nodal_dim; i++)
750  {
751  int local_dof = this->position_local_eqn(n, k, i);
752  if (local_dof >= 0)
753  {
754  dof_is_solid[local_dof] = true;
755  }
756  }
757  }
758  }
759  // Otherwise the node is hanging
760  else
761  {
762  // Find the local hanging object
763  HangInfo* hang_info_pt = local_node_pt->hanging_pt();
764  // Loop over the master nodes
765  const unsigned n_master = hang_info_pt->nmaster();
766  for (unsigned m = 0; m < n_master; m++)
767  {
768  // Get the local equation numbers for the master node
769  DenseMatrix<int> Position_local_eqn_at_node =
770  this->local_position_hang_eqn(hang_info_pt->master_node_pt(m));
771 
772  // Loop over position dofs
773  for (unsigned k = 0; k < n_position_type; k++)
774  {
775  // Loop over dimension
776  for (unsigned i = 0; i < nodal_dim; i++)
777  {
778  int local_dof = Position_local_eqn_at_node(k, i);
779  if (local_dof >= 0)
780  {
781  dof_is_solid[local_dof] = true;
782  }
783  }
784  }
785  }
786  }
787  } // End of loop over nodes
788 
789  // Add the solid pressures (in solid elements without
790  // solid pressure the number will be zero).
791  unsigned n_solid_pres = this->npres_solid();
792  // Now is the solid pressure hanging
793  const int solid_p_index = this->solid_p_nodal_index();
794  // Find out whether the solid node is hanging
795  std::vector<bool> solid_p_is_hanging(n_solid_pres);
796  // If we have nodal solid pressures then read out the hanging status
797  if (solid_p_index >= 0)
798  {
799  // Loop over the solid dofs
800  for (unsigned l = 0; l < n_solid_pres; l++)
801  {
802  solid_p_is_hanging[l] =
803  this->solid_pressure_node_pt(l)->is_hanging(solid_p_index);
804  }
805  }
806  // Otherwise the pressure is not nodal, so cannot hang
807  else
808  {
809  for (unsigned l = 0; l < n_solid_pres; l++)
810  {
811  solid_p_is_hanging[l] = false;
812  }
813  }
814 
815  // Now we can loop of the dofs again to actually set that the appropriate
816  // dofs are solid
817  for (unsigned l = 0; l < n_solid_pres; l++)
818  {
819  // If the solid pressure is not hanging
820  // we just read out the local equation numbers directly
821  if (solid_p_is_hanging[l] == false)
822  {
823  int local_dof = this->solid_p_local_eqn(l);
824  if (local_dof >= 0)
825  {
826  dof_is_solid[local_dof] = true;
827  }
828  }
829  // Otherwise solid pressure is hanging and we need to take
830  // care of the master nodes
831  else
832  {
833  // Find the local hanging object
834  HangInfo* hang_info_pt =
835  this->solid_pressure_node_pt(l)->hanging_pt(solid_p_index);
836  // Loop over the master nodes
837  const unsigned n_master = hang_info_pt->nmaster();
838  for (unsigned m = 0; m < n_master; m++)
839  {
840  // Get the local dof
841  int local_dof = this->local_hang_eqn(
842  hang_info_pt->master_node_pt(m), solid_p_index);
843 
844  if (local_dof >= 0)
845  {
846  dof_is_solid[local_dof] = true;
847  }
848  }
849  }
850  } // end of loop over solid pressure dofs
851 
852 
853  // Used default value defined in GeneralisedElement
854  const double fd_step = this->Default_fd_jacobian_step;
855 
856  // Integer storage for local unknowns
857  int local_unknown = 0;
858 
859  // Loop over the nodes
860  for (unsigned l = 0; l < n_node; l++)
861  {
862  // Get the pointer to the node
863  Node* const local_node_pt = this->node_pt(l);
864 
865  // If the node is not a hanging node
866  if (local_node_pt->is_hanging() == false)
867  {
868  // Loop over position dofs
869  for (unsigned k = 0; k < n_position_type; k++)
870  {
871  // Loop over dimension
872  for (unsigned i = 0; i < nodal_dim; i++)
873  {
874  local_unknown = this->position_local_eqn(l, k, i);
875  // If the variable is free
876  if (local_unknown >= 0)
877  {
878  // Store a pointer to the (generalised) Eulerian nodal position
879  double* const value_pt = &(local_node_pt->x_gen(k, i));
880 
881  // Save the old value of the (generalised) Eulerian nodal
882  // position
883  const double old_var = *value_pt;
884 
885  // Increment the (generalised) Eulerian nodal position
886  *value_pt += fd_step;
887 
888  // Perform any auxialiary node updates
889  local_node_pt->perform_auxiliary_node_update_fct();
890 
891  // Calculate the new residuals
892  // Need to do this using fill_in because get_residuals will
893  // compute all residuals for the problem, which is
894  // a little ineffecient
895  for (unsigned m = 0; m < n_dof; m++)
896  {
897  newres[m] = 0.0;
898  }
900 
901 
902  // if (use_first_order_fd)
903  {
904  // Do forward finite differences
905  for (unsigned m = 0; m < n_dof; m++)
906  {
907  // Stick the entry into the Jacobian matrix
908  // But only if it's not a solid dof
909  if (dof_is_solid[m] == false)
910  {
911  jacobian(m, local_unknown) =
912  (newres[m] - residuals[m]) / fd_step;
913  }
914  }
915  }
916  // else
917  // {
918  // //Take backwards step for the (generalised)
919  // Eulerian nodal
920  // // position
921  // node_pt(l)->x_gen(k,i) = old_var-fd_step;
922 
923  // //Calculate the new residuals at backward
924  // position BASIC::get_residuals(newres_minus);
925 
926  // //Do central finite differences
927  // for(unsigned m=0;m<n_dof;m++)
928  // {
929  // //Stick the entry into the Jacobian matrix
930  // jacobian(m,local_unknown) =
931  // (newres[m] - newres_minus[m])/(2.0*fd_step);
932  // }
933  // }
934 
935  // Reset the (generalised) Eulerian nodal position
936  *value_pt = old_var;
937 
938  // Perform any auxialiary node updates
939  local_node_pt->perform_auxiliary_node_update_fct();
940  }
941  }
942  }
943  }
944  // Otherwise it's a hanging node
945  else
946  {
947  // Find the local hanging object
948  HangInfo* hang_info_pt = local_node_pt->hanging_pt();
949  // Loop over the master nodes
950  const unsigned n_master = hang_info_pt->nmaster();
951  for (unsigned m = 0; m < n_master; m++)
952  {
953  // Get the pointer to the master node
954  Node* const master_node_pt = hang_info_pt->master_node_pt(m);
955 
956  // Get the local equation numbers for the master node
957  DenseMatrix<int> Position_local_eqn_at_node =
958  this->local_position_hang_eqn(master_node_pt);
959 
960  // Loop over position dofs
961  for (unsigned k = 0; k < n_position_type; k++)
962  {
963  // Loop over dimension
964  for (unsigned i = 0; i < nodal_dim; i++)
965  {
966  local_unknown = Position_local_eqn_at_node(k, i);
967  // If the variable is free
968  if (local_unknown >= 0)
969  {
970  // Store a pointer to the (generalised) Eulerian nodal
971  // position
972  double* const value_pt = &(master_node_pt->x_gen(k, i));
973 
974  // Save the old value of the (generalised) Eulerian nodal
975  // position
976  const double old_var = *value_pt;
977 
978  // Increment the (generalised) Eulerian nodal position
979  *value_pt += fd_step;
980 
981  // Perform any auxialiary node updates
982  master_node_pt->perform_auxiliary_node_update_fct();
983 
984  // Calculate the new residuals
985  // Need to do this using fill_in because get_residuals will
986  // compute all residuals for the problem, which is
987  // a little ineffecient
988  for (unsigned m = 0; m < n_dof; m++)
989  {
990  newres[m] = 0.0;
991  }
993 
994  // if (use_first_order_fd)
995  {
996  // Do forward finite differences
997  for (unsigned m = 0; m < n_dof; m++)
998  {
999  // Stick the entry into the Jacobian matrix
1000  // But only if it's not a solid dof
1001  if (dof_is_solid[m] == false)
1002  {
1003  jacobian(m, local_unknown) =
1004  (newres[m] - residuals[m]) / fd_step;
1005  }
1006  }
1007  }
1008  // else
1009  // {
1010  // //Take backwards step for the (generalised)
1011  // Eulerian nodal
1012  // // position
1013  // master_node_pt->x_gen(k,i) =
1014  // old_var-fd_step;
1015 
1016  // //Calculate the new residuals at backward
1017  // position
1018  // BASIC::get_residuals(newres_minus);
1019 
1020  // //Do central finite differences
1021  // for(unsigned m=0;m<n_dof;m++)
1022  // {
1023  // //Stick the entry into the Jacobian
1024  // matrix jacobian(m,local_unknown) =
1025  // (newres[m] -
1026  // newres_minus[m])/(2.0*fd_step);
1027  // }
1028  // }
1029 
1030  // Reset the (generalised) Eulerian nodal position
1031  *value_pt = old_var;
1032 
1033  // Perform any auxialiary node updates
1034  master_node_pt->perform_auxiliary_node_update_fct();
1035  }
1036  }
1037  }
1038  }
1039  } // End of hanging node case
1040 
1041  } // End of loop over nodes
1042 
1043  // End of finite difference loop
1044 
1045  // Final reset of any dependent data
1046  this->reset_after_solid_position_fd();
1047  }
1048 
1049 
1054  void identify_geometric_data(std::set<Data*>& geometric_data_pt)
1055  {
1056  // Loop over the node update data and add to the set
1057  const unsigned n_node = this->nnode();
1058  for (unsigned j = 0; j < n_node; j++)
1059  {
1060  // If the node is a hanging node
1061  if (this->node_pt(j)->is_hanging())
1062  {
1063  // Find the local hang info object
1064  HangInfo* hang_info_pt = this->node_pt(j)->hanging_pt();
1065 
1066  // Find the number of master nodes
1067  unsigned n_master = hang_info_pt->nmaster();
1068 
1069  // Loop over the master nodes
1070  for (unsigned m = 0; m < n_master; m++)
1071  {
1072  // Get the m-th master node
1073  Node* Master_node_pt = hang_info_pt->master_node_pt(m);
1074 
1075  // Add to set
1076  geometric_data_pt.insert(
1077  dynamic_cast<SolidNode*>(Master_node_pt)->variable_position_pt());
1078  }
1079  }
1080  // Not hanging
1081  else
1082  {
1083  // Add node itself to set
1084  geometric_data_pt.insert(
1085  dynamic_cast<SolidNode*>(this->node_pt(j))->variable_position_pt());
1086  }
1087  }
1088  }
1089 
1090 
1094  {
1095  BASIC::assign_additional_local_eqn_numbers();
1096  SOLID::assign_additional_local_eqn_numbers();
1097  }
1098 
1100  void rebuild_from_sons(Mesh*& mesh_pt)
1101  {
1102  BASIC::rebuild_from_sons(mesh_pt);
1103  SOLID::rebuild_from_sons(mesh_pt);
1104  }
1105 
1108  void get_interpolated_values(const unsigned& t,
1109  const Vector<double>& s,
1110  Vector<double>& values)
1111  {
1112  Vector<double> basic_values;
1113  BASIC::get_interpolated_values(t, s, basic_values);
1114  Vector<double> solid_values;
1115  SOLID::get_interpolated_values(t, s, solid_values);
1116 
1117  // Now add the basic value first
1118  for (Vector<double>::iterator it = basic_values.begin();
1119  it != basic_values.end();
1120  ++it)
1121  {
1122  values.push_back(*it);
1123  }
1124  // Then the solid
1125  for (Vector<double>::iterator it = solid_values.begin();
1126  it != solid_values.end();
1127  ++it)
1128  {
1129  values.push_back(*it);
1130  }
1131  }
1132 
1133 
1137  Vector<double>& values)
1138  {
1139  Vector<double> basic_values;
1140  BASIC::get_interpolated_values(s, basic_values);
1141  Vector<double> solid_values;
1142  SOLID::get_interpolated_values(s, solid_values);
1143 
1144  // Now add the basic value first
1145  for (Vector<double>::iterator it = basic_values.begin();
1146  it != basic_values.end();
1147  ++it)
1148  {
1149  values.push_back(*it);
1150  }
1151  // Then the solid
1152  for (Vector<double>::iterator it = solid_values.begin();
1153  it != solid_values.end();
1154  ++it)
1155  {
1156  values.push_back(*it);
1157  }
1158  }
1159 
1162  Node* interpolating_node_pt(const unsigned& n, const int& value_id)
1163  {
1164  // Find the number of interpolated values in the BASIC equations
1165  int n_basic_values = BASIC::ncont_interpolated_values();
1166  // If the id is below this number, we call the BASIC functon
1167  if (value_id < n_basic_values)
1168  {
1169  return BASIC::interpolating_node_pt(n, value_id);
1170  }
1171  // Otherwise it's the solid and its value_id is the the current
1172  // it minus n_basic_values
1173  else
1174  {
1175  return SOLID::interpolating_node_pt(n, (value_id - n_basic_values));
1176  }
1177  }
1178 
1182  const unsigned& i,
1183  const int& value_id)
1184  {
1185  // Find the number of interpolated values in the BASIC equations
1186  int n_basic_values = BASIC::ncont_interpolated_values();
1187  // If the id is below this number, we call the BASIC functon
1188  if (value_id < n_basic_values)
1189  {
1190  return BASIC::local_one_d_fraction_of_interpolating_node(
1191  n1d, i, value_id);
1192  }
1193  // Otherwise it's the solid and its value_id is the the current
1194  // it minus n_basic_values
1195  else
1196  {
1197  return SOLID::local_one_d_fraction_of_interpolating_node(
1198  n1d, i, (value_id - n_basic_values));
1199  }
1200  }
1201 
1202 
1208  const int& value_id)
1209  {
1210  // Find the number of interpolated values in the BASIC equations
1211  int n_basic_values = BASIC::ncont_interpolated_values();
1212  // If the id is below this number, we call the BASIC functon
1213  if (value_id < n_basic_values)
1214  {
1215  return BASIC::get_interpolating_node_at_local_coordinate(s, value_id);
1216  }
1217  // Otherwise it's the solid and its value_id is the the current
1218  // it minus n_basic_values
1219  else
1220  {
1221  return SOLID::get_interpolating_node_at_local_coordinate(
1222  s, (value_id - n_basic_values));
1223  }
1224  }
1225 
1228  unsigned ninterpolating_node_1d(const int& value_id)
1229  {
1230  // Find the number of interpolated values in the BASIC equations
1231  int n_basic_values = BASIC::ncont_interpolated_values();
1232  // If the id is below this number, we call the BASIC functon
1233  if (value_id < n_basic_values)
1234  {
1235  return BASIC::ninterpolating_node_1d(value_id);
1236  }
1237  // Otherwise it's the solid and its value_id is the the current
1238  // it minus n_basic_values
1239  else
1240  {
1241  return SOLID::ninterpolating_node_1d((value_id - n_basic_values));
1242  }
1243  }
1244 
1247  unsigned ninterpolating_node(const int& value_id)
1248  {
1249  // Find the number of interpolated values in the BASIC equations
1250  int n_basic_values = BASIC::ncont_interpolated_values();
1251  // If the id is below this number, we call the BASIC functon
1252  if (value_id < n_basic_values)
1253  {
1254  return BASIC::ninterpolating_node(value_id);
1255  }
1256  // Otherwise it's the solid and its value_id is the the current
1257  // it minus n_basic_values
1258  else
1259  {
1260  return SOLID::ninterpolating_node((value_id - n_basic_values));
1261  }
1262  }
1263 
1267  Shape& psi,
1268  const int& value_id) const
1269  {
1270  // Find the number of interpolated values in the BASIC equations
1271  int n_basic_values = BASIC::ncont_interpolated_values();
1272  // If the id is below this number, we call the BASIC functon
1273  if (value_id < n_basic_values)
1274  {
1275  return BASIC::interpolating_basis(s, psi, value_id);
1276  }
1277  // Otherwise it's the solid and its value_id is the the current
1278  // it minus n_basic_values
1279  else
1280  {
1281  return SOLID::interpolating_basis(s, psi, (value_id - n_basic_values));
1282  }
1283  }
1284 
1285 
1289  {
1290  return BASIC::num_Z2_flux_terms();
1291  }
1292 
1296  {
1298  }
1299 
1304  {
1305  BASIC::further_setup_hanging_nodes();
1306  SOLID::further_setup_hanging_nodes();
1307  }
1308 
1309 
1312  void build(Mesh*& mesh_pt,
1313  Vector<Node*>& new_node_pt,
1314  bool& was_already_built,
1315  std::ofstream& new_nodes_file)
1316  {
1317  SOLID::build(mesh_pt, new_node_pt, was_already_built, new_nodes_file);
1318  }
1319 
1320 
1323  void build(Mesh*& mesh_pt,
1324  Vector<Node*>& new_node_pt,
1325  bool& was_already_built)
1326  {
1327  SOLID::build(mesh_pt, new_node_pt, was_already_built);
1328  }
1329 
1333  {
1334  BASIC::further_build();
1335  SOLID::further_build();
1336  }
1337 
1338 
1340  unsigned nvertex_node() const
1341  {
1342  return BASIC::nvertex_node();
1343  }
1344 
1346  Node* vertex_node_pt(const unsigned& j) const
1347  {
1348  return BASIC::vertex_node_pt(j);
1349  }
1350 
1352  void compute_norm(double& norm)
1353  {
1354  BASIC::compute_norm(norm);
1355  }
1356 
1361  std::ostream& outfile,
1363  double& error,
1364  double& norm)
1365  {
1366  BASIC::compute_exact_Z2_error(outfile, exact_flux_pt, error, norm);
1367  }
1368 
1371  unsigned nrecovery_order()
1372  {
1373  return BASIC::nrecovery_order();
1374  }
1375 
1377  void output(std::ostream& outfile)
1378  {
1379  BASIC::output(outfile);
1380  }
1381 
1383  void output(std::ostream& outfile, const unsigned& n_p)
1384  {
1385  BASIC::output(outfile, n_p);
1386  }
1387 
1389  void output(FILE* file_pt)
1390  {
1391  BASIC::output(file_pt);
1392  }
1393 
1395  void output(FILE* file_pt, const unsigned& n_p)
1396  {
1397  BASIC::output(file_pt, n_p);
1398  }
1399 
1402  unsigned ndof_types() const
1403  {
1404  return BASIC::ndof_types() + SOLID::ndof_types();
1405  }
1406 
1409  unsigned nbasic_dof_types() const
1410  {
1411  return BASIC::ndof_types();
1412  }
1413 
1416  unsigned nsolid_dof_types() const
1417  {
1418  return SOLID::ndof_types();
1419  }
1420 
1430  std::list<std::pair<unsigned long, unsigned>>& dof_lookup_list) const
1431  {
1432  // get the solid list
1433  std::list<std::pair<unsigned long, unsigned>> solid_list;
1434  SOLID::get_dof_numbers_for_unknowns(solid_list);
1435 
1436  // get the basic list
1437  BASIC::get_dof_numbers_for_unknowns(dof_lookup_list);
1438 
1439  // get the number of basic dof types
1440  unsigned nbasic_dof_types = BASIC::ndof_types();
1441 
1442  // add the solid lookup list to the basic lookup list
1443  // incrementing the solid dof numbers by nbasic_dof_types
1444  typedef std::list<std::pair<unsigned long, unsigned>>::iterator IT;
1445  for (IT it = solid_list.begin(); it != solid_list.end(); it++)
1446  {
1447  std::pair<unsigned long, unsigned> new_pair;
1448  new_pair.first = it->first;
1449  new_pair.second = it->second + nbasic_dof_types;
1450  dof_lookup_list.push_front(new_pair);
1451  }
1452  }
1453  };
1454 
1455 
1457  template<class BASIC, class SOLID>
1459  : public virtual FaceGeometry<SOLID>
1460  {
1461  public:
1465 
1466  protected:
1467  };
1468 
1470  template<class BASIC, class SOLID>
1473  : public virtual FaceGeometry<FaceGeometry<SOLID>>
1474  {
1475  public:
1479 
1480  protected:
1481  };
1482 
1483 
1484 } // namespace oomph
1485 
1486 #endif
int i
Definition: BiCGSTAB_step_by_step.cpp:9
const unsigned n
Definition: CG3DPackingUnitTest.cpp:11
FaceGeometry()
Definition: pseudosolid_node_update_elements.h:562
FaceGeometry()
Definition: pseudosolid_node_update_elements.h:1464
Definition: elements.h:4998
void(* SteadyExactSolutionFctPt)(const Vector< double > &, Vector< double > &)
Definition: elements.h:1759
Definition: nodes.h:742
Node *const & master_node_pt(const unsigned &i) const
Return a pointer to the i-th master node.
Definition: nodes.h:791
unsigned nmaster() const
Return the number of master nodes.
Definition: nodes.h:785
Definition: mesh.h:67
Definition: nodes.h:906
double & x_gen(const unsigned &k, const unsigned &i)
Definition: nodes.h:1126
HangInfo *const & hanging_pt() const
Definition: nodes.h:1228
void perform_auxiliary_node_update_fct()
Definition: nodes.h:1615
bool is_hanging() const
Test whether the node is geometrically hanging.
Definition: nodes.h:1285
Definition: oomph_definitions.h:222
Definition: pseudosolid_node_update_elements.h:58
bool Shape_derivs_by_direct_fd
Boolean flag to indicate shape derivative method.
Definition: pseudosolid_node_update_elements.h:60
void fill_in_contribution_to_residuals(Vector< double > &residuals)
Definition: pseudosolid_node_update_elements.h:119
void describe_local_dofs(std::ostream &out, const std::string &current_string) const
Definition: pseudosolid_node_update_elements.h:79
void compute_exact_Z2_error(std::ostream &outfile, FiniteElement::SteadyExactSolutionFctPt exact_flux_pt, double &error, double &norm)
Definition: pseudosolid_node_update_elements.h:463
unsigned required_nvalue(const unsigned &n) const
The required number of values is the sum of the two.
Definition: pseudosolid_node_update_elements.h:94
unsigned nsolid_dof_types() const
Definition: pseudosolid_node_update_elements.h:515
void fill_in_shape_derivatives(DenseMatrix< double > &jacobian)
Definition: pseudosolid_node_update_elements.h:175
void output(std::ostream &outfile, const unsigned &n_p)
Definition: pseudosolid_node_update_elements.h:435
void output(std::ostream &outfile)
Overload the output function: Call that of the basic element.
Definition: pseudosolid_node_update_elements.h:428
void compute_norm(double &el_norm)
Definition: pseudosolid_node_update_elements.h:88
unsigned nrecovery_order()
Definition: pseudosolid_node_update_elements.h:493
void get_Z2_flux(const Vector< double > &s, Vector< double > &flux)
Definition: pseudosolid_node_update_elements.h:474
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Definition: pseudosolid_node_update_elements.h:129
Node * vertex_node_pt(const unsigned &j) const
Pointer to the j-th vertex node in the element.
Definition: pseudosolid_node_update_elements.h:486
void fill_in_shape_derivatives_by_fd(DenseMatrix< double > &jacobian)
Definition: pseudosolid_node_update_elements.h:246
unsigned nbasic_dof_types() const
Definition: pseudosolid_node_update_elements.h:508
unsigned nvertex_node() const
Number of vertex nodes in the element.
Definition: pseudosolid_node_update_elements.h:480
void evaluate_shape_derivs_by_chain_rule()
Evaluate shape derivatives by chain rule.
Definition: pseudosolid_node_update_elements.h:167
void fill_in_contribution_to_jacobian_and_mass_matrix(Vector< double > &residuals, DenseMatrix< double > &jacobian, DenseMatrix< double > &mass_matrix)
Definition: pseudosolid_node_update_elements.h:143
void output(FILE *file_pt, const unsigned &n_p)
Output function is just the same as the basic equations.
Definition: pseudosolid_node_update_elements.h:447
void evaluate_shape_derivs_by_direct_fd()
Evaluate shape derivatives by direct finite differencing.
Definition: pseudosolid_node_update_elements.h:161
int solid_p_nodal_index() const
Definition: pseudosolid_node_update_elements.h:102
unsigned num_Z2_flux_terms()
Definition: pseudosolid_node_update_elements.h:454
void output(FILE *file_pt)
Overload the output function: Call that of the basic element.
Definition: pseudosolid_node_update_elements.h:441
void identify_geometric_data(std::set< Data * > &geometric_data_pt)
Definition: pseudosolid_node_update_elements.h:415
void get_dof_numbers_for_unknowns(std::list< std::pair< unsigned long, unsigned >> &dof_lookup_list) const
Definition: pseudosolid_node_update_elements.h:528
unsigned ndof_types() const
Definition: pseudosolid_node_update_elements.h:501
PseudoSolidNodeUpdateElement()
Definition: pseudosolid_node_update_elements.h:65
A Rank 3 Tensor class.
Definition: matrices.h:1370
Definition: refineable_elements.h:97
Refineable version of the PseudoSolidNodeUpdateELement.
Definition: pseudosolid_node_update_elements.h:585
unsigned nbasic_dof_types() const
Definition: pseudosolid_node_update_elements.h:1409
void get_interpolated_values(const Vector< double > &s, Vector< double > &values)
Definition: pseudosolid_node_update_elements.h:1136
unsigned ndof_types() const
Definition: pseudosolid_node_update_elements.h:1402
void get_interpolated_values(const unsigned &t, const Vector< double > &s, Vector< double > &values)
Definition: pseudosolid_node_update_elements.h:1108
Node * get_interpolating_node_at_local_coordinate(const Vector< double > &s, const int &value_id)
Definition: pseudosolid_node_update_elements.h:1207
void further_build()
Definition: pseudosolid_node_update_elements.h:1332
Node * interpolating_node_pt(const unsigned &n, const int &value_id)
Definition: pseudosolid_node_update_elements.h:1162
void output(FILE *file_pt)
Overload the output function: Use that of the BASIC element.
Definition: pseudosolid_node_update_elements.h:1389
void compute_norm(double &norm)
Compute norm of solution. Use version in BASIC element.
Definition: pseudosolid_node_update_elements.h:1352
unsigned nvertex_node() const
Number of vertex nodes in the element.
Definition: pseudosolid_node_update_elements.h:1340
void fill_in_contribution_to_residuals(Vector< double > &residuals)
Definition: pseudosolid_node_update_elements.h:646
unsigned nrecovery_order()
Definition: pseudosolid_node_update_elements.h:1371
void output(std::ostream &outfile, const unsigned &n_p)
Output function, plotting at n_p points: Use that of the BASIC element.
Definition: pseudosolid_node_update_elements.h:1383
unsigned ncont_interpolated_values() const
Definition: pseudosolid_node_update_elements.h:618
int solid_p_nodal_index() const
Definition: pseudosolid_node_update_elements.h:627
unsigned nsolid_dof_types() const
Definition: pseudosolid_node_update_elements.h:1416
void interpolating_basis(const Vector< double > &s, Shape &psi, const int &value_id) const
Definition: pseudosolid_node_update_elements.h:1266
void compute_exact_Z2_error(std::ostream &outfile, FiniteElement::SteadyExactSolutionFctPt exact_flux_pt, double &error, double &norm)
Definition: pseudosolid_node_update_elements.h:1360
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Definition: pseudosolid_node_update_elements.h:656
unsigned num_Z2_flux_terms()
Definition: pseudosolid_node_update_elements.h:1288
void get_dof_numbers_for_unknowns(std::list< std::pair< unsigned long, unsigned >> &dof_lookup_list) const
Definition: pseudosolid_node_update_elements.h:1429
RefineablePseudoSolidNodeUpdateElement()
Definition: pseudosolid_node_update_elements.h:589
void build(Mesh *&mesh_pt, Vector< Node * > &new_node_pt, bool &was_already_built)
Definition: pseudosolid_node_update_elements.h:1323
unsigned ninterpolating_node_1d(const int &value_id)
Definition: pseudosolid_node_update_elements.h:1228
void fill_in_contribution_to_jacobian_and_mass_matrix(Vector< double > &residuals, DenseMatrix< double > &jacobian, DenseMatrix< double > &mass_matrix)
Definition: pseudosolid_node_update_elements.h:671
void further_setup_hanging_nodes()
Definition: pseudosolid_node_update_elements.h:1303
void output(std::ostream &outfile)
Overload the output function: Use that of the BASIC element.
Definition: pseudosolid_node_update_elements.h:1377
double local_one_d_fraction_of_interpolating_node(const unsigned &n1d, const unsigned &i, const int &value_id)
Definition: pseudosolid_node_update_elements.h:1181
void output(FILE *file_pt, const unsigned &n_p)
Output function: Use that of the BASIC element.
Definition: pseudosolid_node_update_elements.h:1395
void build(Mesh *&mesh_pt, Vector< Node * > &new_node_pt, bool &was_already_built, std::ofstream &new_nodes_file)
Definition: pseudosolid_node_update_elements.h:1312
void assign_additional_local_eqn_numbers()
Definition: pseudosolid_node_update_elements.h:1093
unsigned ninterpolating_node(const int &value_id)
Definition: pseudosolid_node_update_elements.h:1247
Node * vertex_node_pt(const unsigned &j) const
Pointer to the j-th vertex node in the element.
Definition: pseudosolid_node_update_elements.h:1346
void rebuild_from_sons(Mesh *&mesh_pt)
Call rebuild_from_sons() for both of the underlying element types.
Definition: pseudosolid_node_update_elements.h:1100
void fill_in_shape_derivatives_by_fd(DenseMatrix< double > &jacobian)
Definition: pseudosolid_node_update_elements.h:691
void get_Z2_flux(const Vector< double > &s, Vector< double > &flux)
Definition: pseudosolid_node_update_elements.h:1295
void describe_local_dofs(std::ostream &out, const std::string &current_string) const
Definition: pseudosolid_node_update_elements.h:603
unsigned required_nvalue(const unsigned &n) const
The required number of values is the sum of the two.
Definition: pseudosolid_node_update_elements.h:611
void identify_geometric_data(std::set< Data * > &geometric_data_pt)
Definition: pseudosolid_node_update_elements.h:1054
Definition: shape.h:76
Definition: nodes.h:1686
RealScalar s
Definition: level1_cplx_impl.h:130
int * m
Definition: level2_cplx_impl.h:294
char char char int int * k
Definition: level2_impl.h:374
void flux(const double &time, const Vector< double > &x, double &flux)
Get flux applied along boundary x=0.
Definition: pretend_melt.cc:59
int error
Definition: calibrate.py:297
std::string string(const unsigned &i)
Definition: oomph_definitions.cc:286
double Zero
Definition: pseudosolid_node_update_elements.cc:35
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
Definition: AnisotropicHookean.h:10
void fill_in_contribution_to_jacobian_and_mass_matrix(Vector< double > &residuals, DenseMatrix< double > &jacobian, DenseMatrix< double > &mass_matrix)
Definition: gen_axisym_advection_diffusion_elements.h:547
void fill_in_contribution_to_residuals(Vector< double > &residuals)
Add the element's contribution to its residual vector (wrapper)
Definition: gen_axisym_advection_diffusion_elements.h:522
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Definition: gen_axisym_advection_diffusion_elements.h:536
t
Definition: plotPSD.py:36
#define OOMPH_EXCEPTION_LOCATION
Definition: oomph_definitions.h:61
#define OOMPH_CURRENT_FUNCTION
Definition: oomph_definitions.h:86
void get_Z2_flux(const Vector< double > &s, Vector< double > &flux)
Get 'flux' for Z2 error recovery.
Definition: overloaded_element_body.h:745
void output(std::ostream &outfile, const unsigned &nplot)
Overload output function.
Definition: overloaded_element_body.h:490
std::ofstream out("Result.txt")
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2