my_problem.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 
27 #ifndef OOMPH_MY_GENERIC_PROBLEM_H
28 #define OOMPH_MY_GENERIC_PROBLEM_H
29 
30 #include "generic.h"
31 
32 #include <ctime>
33 #include <ostream>
34 #include <string>
35 
36 namespace oomph
37 {
38 
45 //??ds compatability wrapper, remove?
46  template<class T>
48  {
49  T bp_pt = dynamic_cast<T> (prec_pt);
50  if(bp_pt != 0)
51  {
52  return bp_pt;
53  }
54  else
55  {
56  return 0;
57  }
58  }
59 
60  using namespace StringConversion;
61 
62  class ElementalFunction;
63 
65  {
66  time_t rawtime;
67  struct tm * timeinfo;
68  char buffer [80];
69 
70  // Get time
71  time(&rawtime);
72  timeinfo = localtime(&rawtime);
73 
74  // Write into cstring
75  strftime(buffer, 80, "%Y-%m-%d-%H-%M-%S", timeinfo);
76 
77  // Return as "real" string
78  return std::string(buffer);
79  }
80 
82  {
84  {
85  linear_solver_pt = 0;
86  mass_matrix_solver_for_explicit_timestepper_pt = 0;
87  }
88 
90 
91  // Newton options
94  double max_residuals;
97 
98  // Linear optimisations
102 
103  // Explicit solver
108  };
109 
110 
111  class MyDocInfo : public DocInfo
112  {
113  public:
115  MyDocInfo() : DocInfo(), output_jacobian("never") {}
116 
119  {
120  std::ostringstream stream;
122  args_str.assign(stream.str());
123  }
124 
127  };
128 
129 
130  class MyProblem : public Problem
131  {
132  public:
135  Trace_filename("trace"),
136  Info_filename("info"),
137  Trace_seperator("; "),
138  Dummy_doc_data(-1)
139  {
140  Dim = 0;
141  Output_precision = 8;
142  Error_norm_limit = -1.0;
143  Solution_norm_limit = -1.0;
144 
145  // Throw a real error (not just a warning) if the output directory
146  // does not exist.
147  Doc_info.enable_error_if_directory_does_not_exist();
148 
149  Disable_mass_matrix_solver_optimisations = false;
150 
151  // By default output to trace file every step
152  Always_write_trace = true;
153 
154  Dump = false;
155  Output_ltes = false;
156  Output_predictor_values = false;
157  Want_doc_exact = false;
158  Output_initial_condition = false;
159  Should_doc_boundaries = false;
160 
161  N_steps_taken = 0;
162  Total_step_time= 0;
163  }
164 
169  virtual ~MyProblem() {}
170 
173  double smart_time_step(double dt, const double& tol)
174  {
175  double step_time_start = TimingHelpers::timer();
176 
177  // The Newton step itself, adaptive if requested.
178  if(explicit_flag())
179  {
180  explicit_timestep(dt);
181  }
182  else if(tol != 0.0)
183  {
184  dt = adaptive_unsteady_newton_solve(dt, tol);
185  }
186  else
187  {
188  unsteady_newton_solve(dt);
189  }
190 
191  double step_time_stop = TimingHelpers::timer();
192  Total_step_time = step_time_stop - step_time_start;
193 
194 
195  oomph_info << "Time for step " << Total_step_time
196  << std::endl;
197 
198  N_steps_taken++;
199 
200  return dt;
201  }
202 
205  virtual bool finished() const
206  {
207  return false;
208  }
209 
211  {
212  sp.linear_solver_pt = linear_solver_pt();
213 
214  // Newton options
215  sp.newton_solver_tolerance = newton_solver_tolerance();
216  sp.max_newton_iterations = max_newton_iterations();
217  sp.max_residuals = max_residuals();
218  sp.shut_up_in_newton_solve = Shut_up_in_newton_solve;
219  sp.always_take_one_newton_step = Always_take_one_newton_step;
220 
221  // Linear optimisations
222  sp.jacobian_reuse_is_enabled = jacobian_reuse_is_enabled();
223  sp.jacobian_has_been_computed = Jacobian_has_been_computed;
224  sp.problem_is_nonlinear = Problem_is_nonlinear;
225 
226  // Explicit solver
227  sp.mass_matrix_solver_for_explicit_timestepper_pt = mass_matrix_solver_for_explicit_timestepper_pt();
228  sp.mass_matrix_reuse_is_enabled = mass_matrix_reuse_is_enabled();
229  sp.mass_matrix_has_been_computed = Mass_matrix_has_been_computed;
230  sp.discontinuous_element_formulation = Discontinuous_element_formulation;
231  }
232 
234  {
235  linear_solver_pt() = sp.linear_solver_pt;
236 
237  // Newton options
238  newton_solver_tolerance() = sp.newton_solver_tolerance;
239  max_newton_iterations() = sp.max_newton_iterations;
240  max_residuals() = sp.max_residuals;
241  Shut_up_in_newton_solve = sp.shut_up_in_newton_solve;
242  Always_take_one_newton_step = sp.always_take_one_newton_step;
243 
244  // Linear optimisations
245  Jacobian_reuse_is_enabled = sp.jacobian_reuse_is_enabled;
246  Jacobian_has_been_computed = sp.jacobian_has_been_computed;
247  Problem_is_nonlinear = sp.problem_is_nonlinear;
248 
249  // Explicit solver
250  mass_matrix_solver_for_explicit_timestepper_pt() = sp.mass_matrix_solver_for_explicit_timestepper_pt;
251  Mass_matrix_reuse_is_enabled = sp.mass_matrix_reuse_is_enabled;
252  Mass_matrix_has_been_computed = sp.mass_matrix_has_been_computed;
253  Discontinuous_element_formulation = sp.discontinuous_element_formulation;
254  }
255 
257  {
258  return (explicit_time_stepper_pt() != 0)
259  && (time_stepper_pt()->is_steady());
260  }
261 
262  bool is_steady()
263  {
264  return (explicit_time_stepper_pt() == 0)
265  && (time_stepper_pt()->is_steady());
266  }
267 
269  {
270  // Output Jacobian and residuals if requested
271  if(to_lower(Doc_info.output_jacobian) == "always")
272  {
273  // label with doc_info number and the newton step number
274  std::string label = to_string(Doc_info.number())
275  + "_"
276  + to_string(nnewton_step_this_solve() + 1);
277 
278  dump_current_mm_or_jacobian_residuals(label);
279  }
280  }
281 
282  unsigned nnewton_step_this_solve() const
283  {
284  return Jacobian_setup_times.size();
285  }
286 
289 
291  {
292  Jacobian_setup_times.push_back
293  (this->mass_matrix_solver_for_explicit_timestepper_pt()->jacobian_setup_time());
294  Solver_times.push_back
295  (this->mass_matrix_solver_for_explicit_timestepper_pt()->linear_solver_solution_time());
296 
297  // No non-linear residuals to store
298 
299  const IterativeLinearSolver* its_pt
300  = dynamic_cast<const IterativeLinearSolver*>(this->mass_matrix_solver_for_explicit_timestepper_pt());
301  if(its_pt != 0)
302  {
303  Solver_iterations.push_back(its_pt->iterations());
304  Preconditioner_setup_times.push_back(its_pt->preconditioner_setup_time());
305  }
306  else
307  {
308  // Fill in dummy data
309  Solver_iterations.push_back(Dummy_doc_data);
310  Preconditioner_setup_times.push_back(Dummy_doc_data);
311  }
312 
313  // Not quite the same as actions after newton step because we are
314  // interested in what happened in the explicit solver instead of the
315  // main solver.
316  }
317 
319 
321  {
323  check_norm_limits();
324  }
325 
327  {
329  }
330 
332 
334  {
335  check_norm_limits();
336  }
337 
338 
340  {
341  Jacobian_setup_times.push_back
342  (this->linear_solver_pt()->jacobian_setup_time());
343  Solver_times.push_back
344  (this->linear_solver_pt()->linear_solver_solution_time());
345 
346  const IterativeLinearSolver* its_pt
347  = dynamic_cast<const IterativeLinearSolver*>(this->linear_solver_pt());
348  if(its_pt != 0)
349  {
350  Solver_iterations.push_back(its_pt->iterations());
351  Preconditioner_setup_times.push_back(its_pt->preconditioner_setup_time());
352  }
353  else
354  {
355  // Fill in dummy data
356  Solver_iterations.push_back(Dummy_doc_data);
357  Preconditioner_setup_times.push_back(Dummy_doc_data);
358  }
359  }
360 
362  {
363  // Clean up times vectors
364  Jacobian_setup_times.clear();
365  Solver_times.clear();
366  Solver_iterations.clear();
367  Preconditioner_setup_times.clear();
368  }
369 
370 
371 
377  {
378  for(unsigned msh=0, nmsh=nsub_mesh(); msh<nmsh; msh++)
379  {
380  Mesh* mesh_pt = this->mesh_pt(msh);
381  for(unsigned nd=0, nnd=mesh_pt->nnode(); nd<nnd; nd++)
382  {
383  Node* nd_pt = mesh_pt->node_pt(nd);
384  for(unsigned j=0; j<indices.size(); j++)
385  {
386  if(!nd_pt->is_pinned(indices[j]))
387  {
388  nd_pt->eqn_number(indices[j])
390  }
391  }
392  }
393  }
394  // Output information
395  oomph_info << "Segregated solve, without indices:\n";
396 
397  // Loop over the entries of indices and output
398  unsigned indices_length=indices.size();
399  if (indices_length==0)
400  {
401  oomph_info << Trace_seperator << "[]";
402  }
403  else
404  {
405  oomph_info << Trace_seperator << "[" << indices[0];
406  if (indices_length>1)
407  {
408  for (unsigned i=1;i<indices_length;i++)
409  {
410  oomph_info << ", " << indices[i];
411  }
412  }
413  oomph_info << "]";
414  }
415 
416  // Output the number of equations
417  oomph_info << "Number of equations: " << assign_eqn_numbers() << std::endl;
418  }
419 
422  {
423  for(unsigned msh=0, nmsh=nsub_mesh(); msh<nmsh; msh++)
424  {
425  Mesh* mesh_pt = this->mesh_pt(msh);
426  for(unsigned nd=0, nnd=mesh_pt->nnode(); nd<nnd; nd++)
427  {
428  Node* nd_pt = mesh_pt->node_pt(nd);
429  for(unsigned j=0; j<nd_pt->nvalue(); j++)
430  {
432  {
434  }
435  }
436  }
437  }
438  oomph_info << "un-segregated n eqn " << assign_eqn_numbers() << std::endl;
439  }
440 
441 
443  void check_not_segregated(const char* function) const
444  {
445 #ifdef PARANOID
446  for(unsigned msh=0, nmsh=nsub_mesh(); msh<nmsh; msh++)
447  {
448  Mesh* mesh_pt = this->mesh_pt(msh);
449  for(unsigned nd=0, nnd=mesh_pt->nnode(); nd<nnd; nd++)
450  {
451  Node* nd_pt = mesh_pt->node_pt(nd);
452  for(unsigned j=0; j<nd_pt->nvalue(); j++)
453  {
455  {
456  throw OomphLibError("Some dofs already segregated",
458  function);
459  }
460  }
461  }
462  }
463 #endif
464  }
465 
466 
468  {
469  // If a limit has been set
470  if(Error_norm_limit != -1.0)
471  {
472  double error_norm = get_error_norm();
473 
474  if((error_norm != Dummy_doc_data)
475  && (error_norm > Error_norm_limit))
476  {
477  std::string err = "Error norm " + to_string(error_norm);
478  err += " exceeds the limit " + to_string(Error_norm_limit);
481  }
482  }
483 
484  // Same for solution norm
485  if(Solution_norm_limit != -1.0)
486  {
487  double solution_norm = get_solution_norm();
488 
489  if((solution_norm != Dummy_doc_data)
490  && (solution_norm > Solution_norm_limit))
491  {
492  std::string err = "Solution norm " + to_string(solution_norm);
493  err += " exceeds the limit " + to_string(Solution_norm_limit);
496  }
497  }
498  }
499 
501  double min_element_size();
502 
505  void write_trace(const unsigned& t_hist=0);
506 
507 
511  virtual void write_additional_trace_data(const unsigned& t_hist,
512  std::ofstream& trace_file) const {}
513 
517  virtual void write_additional_trace_headers(std::ofstream& trace_file)
518  const {}
519 
521  virtual void output_solution(std::ofstream& soln_file) const {}
522  virtual void final_doc_additional() const {}
523  virtual void initial_doc_additional() const {}
524 
525 
529  void initial_doc();
530 
533  void final_doc()
534  {
535  // Output Jacobian if requested
536  if((to_lower(Doc_info.output_jacobian) == "at_end")
537  || (to_lower(Doc_info.output_jacobian) == "always"))
538  {
539  dump_current_mm_or_jacobian_residuals("at_end");
540  }
541 
542  // Write end of .pvd XML file
543  std::ofstream pvd_file((Doc_info.directory() + "/" + "soln.pvd").c_str(),
544  std::ios::app);
545  pvd_file << "</Collection>" << std::endl
546  << "</VTKFile>" << std::endl;
547  pvd_file.close();
548 
549  // Write end of exact.pvd XML file
550  if(doc_exact())
551  {
552  std::ofstream pvd_file((Doc_info.directory() + "/" + "exact.pvd").c_str(),
553  std::ios::app);
554  pvd_file << "</Collection>" << std::endl
555  << "</VTKFile>" << std::endl;
556  pvd_file.close();
557  }
558 
559  // Write out anything requested from an inheriting class.
560  final_doc_additional();
561  }
562 
569  void doc_solution(const unsigned& t_hist=0,
570  const std::string& prefix = "" );
571 
572 
575  virtual void output_solution(const unsigned& t, std::ostream& outstream,
576  const unsigned& npoints=2) const
577  {
578  const unsigned n_msh = nsub_mesh();
579  for(unsigned msh=0; msh<n_msh; msh++)
580  {
581  Mesh* msh_pt = mesh_pt(msh);
582 
583  const unsigned n_ele = msh_pt->nelement();
584  for(unsigned ele=0; ele<n_ele; ele++)
585  {
586  FiniteElement* ele_pt = msh_pt->finite_element_pt(ele);
587  ele_pt->output(t, outstream, npoints);
588  }
589  }
590  }
591 
593  virtual void doc_boundaries(const std::string& boundary_file_basename) const;
594 
597  void output_solution(std::ostream& outstream,
598  const unsigned& npoints=2) const
599  {
600  output_solution(0, outstream, npoints);
601  }
602 
605  virtual void output_exact_solution(const unsigned& t_hist,
606  std::ostream& outstream,
607  const unsigned& npoints=2) const
608  {
609  const double time = time_pt()->time();
610 
611  const unsigned n_msh = nsub_mesh();
612  for(unsigned msh=0; msh<n_msh; msh++)
613  {
614  Mesh* msh_pt = mesh_pt(msh);
615 
616  const unsigned n_ele = msh_pt->nelement();
617  for(unsigned ele=0; ele<n_ele; ele++)
618  {
619  FiniteElement* ele_pt = msh_pt->finite_element_pt(ele);
620  ele_pt->output_fct(outstream, npoints, time,
621  *Exact_solution_pt);
622  }
623  }
624  }
625 
627  virtual double get_error_norm(const unsigned& t_hist=0) const
628  {
629  if(Exact_solution_pt != 0)
630  {
631  // ExactFunctionDiffSquared f;
632  // f.Exact_pt = Exact_solution_pt;
633  // return std::sqrt(integrate_over_problem(&f));
634 
635  // Nodal rms difference
636  const double t = time_pt()->time(t_hist);
637 
638  double diffsq = 0;
639 
640  const unsigned n_node = mesh_pt()->nnode();
641  for(unsigned nd=0; nd<n_node; nd++)
642  {
643  Node* nd_pt = mesh_pt()->node_pt(nd);
644  Vector<double> values(nd_pt->nvalue(), 0.0), x(dim(), 0.0);
645  nd_pt->position(t_hist, x);
646  nd_pt->value(t_hist, values);
647 
648  Vector<double> exact = exact_solution(t, x);
649 
650  const unsigned ni = values.size();
651  for(unsigned i=0; i<ni; i++)
652  {
653  diffsq += std::pow(values[i] - exact[i], 2);
654  }
655  }
656 
657  return std::sqrt(diffsq);
658  }
659  else
660  {
661  return Dummy_doc_data;
662  }
663  }
664 
666  virtual double get_solution_norm(const unsigned& t_hist=0) const
667  {
668  DoubleVector dofs;
669  get_dofs(t_hist, dofs);
670  return dofs.norm();
671  }
672 
676  virtual bool should_doc_this_step(const double &dt, const double &time) const
677  {
678  // I'm sure there should be a more efficient way to do this if we
679  // know that Doc_times is ordered, but it shouldn't really matter I
680  // guess--Jacobian calculation and solve times will always be far
681  // far larger than this brute force search.
682 
683  // If no Doc_times have been set then always output.
684  if(Doc_times.empty()) return true;
685 
686  // Loop over entries of Doc_times and check if they are in the
687  // range (t - dt, t].
688  for(unsigned j=0; j<Doc_times.size(); j++)
689  {
690  if(( time >= Doc_times[j]) && ((time - dt) < Doc_times[j]))
691  {
692  return true;
693  }
694  }
695  return false;
696  }
697 
699  void set_doc_times(Vector<double> &doc_times)
700  {
701  Doc_times = doc_times;
702  }
703 
704 
707  double lte_norm()
708  {
709  if(time_stepper_pt()->adaptive_flag())
710  {
711  // Just return the error that would be used for adaptivity.
712  return global_temporal_error_norm();
713  }
714  else
715  {
716  return Dummy_doc_data;
717  }
718  }
719 
720  bool doc_exact() const
721  {
722  return Want_doc_exact && (Exact_solution_pt != 0);
723  }
724 
725  virtual Vector<double> trace_values(const unsigned& t_hist=0) const
726  {
727  unsigned nele = mesh_pt()->nelement();
728  unsigned e = nele/2;
729 
730  Vector<double> values;
731  if(dynamic_cast<FiniteElement*>(mesh_pt()->element_pt(e)))
732  {
733  // Just use an element somewhere in the middle...
734  Node* nd_pt = mesh_pt()->finite_element_pt(e)->node_pt(0);
735  values.assign(nd_pt->nvalue(), 0.0);
736  nd_pt->value(t_hist, values);
737  }
738  else
739  {
740  // Not finite elements so no idea what to use
741  values.assign(1, Dummy_doc_data);
742  }
743 
744  return values;
745  }
746 
747 
748  void dump_current_mm_or_jacobian_residuals(const std::string& label);
749 
750 
752  {
753  return dynamic_cast<IterativeLinearSolver*>
754  (this->linear_solver_pt());
755  }
756 
757 
759  virtual void build(Vector<Mesh*>& bulk_mesh_pt);
760 
762  const unsigned dim() const {return this->Dim;}
763 
764  virtual std::string problem_name() const {return "unknown";}
765 
767  virtual void set_up_impulsive_initial_condition();
768 
770  virtual void my_set_initial_condition(const SolutionFunctorBase& ic);
771 
774  virtual void actions_after_set_initial_condition();
775 
778  virtual double integrate_over_problem(const ElementalFunction* func_pt,
779  const Integral* quadrature_pt=0) const;
780 
781 
782  virtual void dump(std::ofstream& dump_file) const
783  {
784  // Set very high precision to avoid any issues
785  dump_file.precision(14);
786 
787  dump_file << Doc_info.number() << " # Doc_info.number()" << std::endl;
788  dump_file << N_steps_taken << " # N_steps_taken" << std::endl;
789  Problem::dump(dump_file);
790  }
791 
792  virtual void read(std::ifstream& restart_file)
793  {
794  // buffer
795  std::string input_string;
796 
797  // Read in Doc_info number. Read line up to termination sign then
798  // ignore.
799  getline(restart_file, input_string, '#');
800  restart_file.ignore(80,'\n');
801  Doc_info.number() = std::atoi(input_string.c_str());
802 
803  // Read in number of steps taken. Read line up to termination sign
804  // then ignore.
805  getline(restart_file, input_string, '#');
806  restart_file.ignore(80,'\n');
807  N_steps_taken = std::atoi(input_string.c_str());
808 
809  // Let base class handle the rest
810  Problem::read(restart_file);
811 
812  // Decrement doc info number so that it is correct after initial doc
813  // Doc_info.number()--;
814  }
815 
816 
824  void output_ltes(const unsigned& t_hist, std::ostream& output) const
825  {
826  // Output position labels
827  for(unsigned j=0; j<Dim; j++)
828  {
829  output << "x" << j << ", ";
830  }
831 
832  // Output labels for ltes, assuming that all nodes have the same
833  // number of values...
834  for(unsigned j=0; j<mesh_pt()->node_pt(0)->nvalue(); j++)
835  {
836  output << "error" << j << ", ";
837  }
838 
839  output << std::endl;
840 
841  // Output actual positions and ltes
842  for(unsigned i=0, ni=mesh_pt()->nnode(); i<ni; i++)
843  {
844  Node* nd_pt = mesh_pt()->node_pt(i);
845 
846  // Output position of node
847  for(unsigned j=0; j<Dim; j++)
848  {
849  output << nd_pt->x(j) << ", ";
850  }
851 
852  // Output ltes of node
853  for(unsigned j=0; j<nd_pt->nvalue(); j++)
854  {
855  // Get timestepper's error estimate for this direction of m
856  // at this point.
857  double error = nd_pt->time_stepper_pt()->
858  temporal_error_in_value(nd_pt, j);
859 
860  output << error << ", ";
861  }
862 
863  output << std::endl;
864  }
865  }
866 
867 
870 
871  unsigned N_steps_taken;
873 
876 
879 
883 
886 
889 
892 
894  bool Dump;
895 
898 
901 
904 
907 
909  Vector<double> exact_solution(const double& t, const Vector<double>& x) const
910  {
911 #ifdef PARANOID
912  if(Exact_solution_pt == 0)
913  {
914  std::string err = "Exact_solution_pt is null!";
917  }
918 #endif
919  return (*Exact_solution_pt)(t, x);
920  }
921 
922  protected:
923 
928  unsigned Dim;
929 
930  private:
931 
936 
939 
941  MyProblem(const MyProblem &dummy)
942  {BrokenCopy::broken_copy("MyProblem");}
943 
945  void operator=(const MyProblem &dummy)
946  {BrokenCopy::broken_assign("MyProblem");}
947  };
948 
951  double MyProblem::integrate_over_problem(const ElementalFunction* func_pt,
952  const Integral* quadrature_pt) const
953  {
954  throw OomphLibError("Not implemented (yet?).", OOMPH_CURRENT_FUNCTION,
956 
957  }
958 
959 
961  {
962  throw OomphLibError("Not implemented (yet?).", OOMPH_CURRENT_FUNCTION,
964  }
965 
967  void MyProblem::build(Vector<Mesh*>& bulk_mesh_pt)
968  {
969  // Copy the first mesh's first timestepper to the problem
970 
971  FiniteElement* fele_pt = dynamic_cast<FiniteElement*>
972  (bulk_mesh_pt[0]->element_pt(0));
973 
974  // Finite element mesh: grab ts from node
975  if(fele_pt != 0)
976  {
977  TimeStepper* ts_pt = bulk_mesh_pt[0]->node_pt(0)->time_stepper_pt();
978  this->add_time_stepper_pt(ts_pt);
979 
980  // ??ds assumed any timesteppers hiding somewhere else are added elsewhere
981 
982 #ifdef PARANOID
983  for(unsigned j=0; j<bulk_mesh_pt.size(); j++)
984  {
985  if(bulk_mesh_pt[j]->node_pt(0)->time_stepper_pt()
986  != ts_pt)
987  {
988  std::string err = "Multiple timesteppers, you need to do somedhing more fancy here";
991  }
992  }
993 #endif
994  }
995 
996  // Non finite element mesh: grab ts from internal data
997  else
998  {
999  TimeStepper* ts_pt = bulk_mesh_pt[0]->element_pt(0)->
1000  internal_data_pt(0)->time_stepper_pt();
1001  this->add_time_stepper_pt(ts_pt);
1002 
1003  // ??ds again assumed any timesteppers hiding somewhere else are added elsewhere
1004 
1005 #ifdef PARANOID
1006  for(unsigned j=0; j<bulk_mesh_pt.size(); j++)
1007  {
1008  if(bulk_mesh_pt[j]->element_pt(0)->
1009  internal_data_pt(0)->time_stepper_pt() != ts_pt)
1010  {
1011  std::string err = "Multiple timesteppers? you need to do somedhing more fancy here";
1014  }
1015  }
1016 #endif
1017  }
1018 
1019 
1020  // Push all the meshes into the problem's sub mesh list
1021  for(unsigned j=0; j<bulk_mesh_pt.size(); j++)
1022  {
1023  add_sub_mesh(bulk_mesh_pt[j]);
1024  }
1025 
1026  // If we have an iterative solver with a block preconditioner then
1027  // add all the meshes to the block preconditioner as well.
1028  IterativeLinearSolver* its_pt = iterative_linear_solver_pt();
1029  if(its_pt != 0)
1030  {
1031 // RRR add comments to why this is incorrect:
1032 // We cannot call set_nmesh and set_mesh, this is handled by the derived
1033 // classes.
1034  // Try to get a block preconditioner from the preconditioner
1036  = smart_cast_preconditioner<BlockPreconditioner<CRDoubleMatrix>*>
1037  (its_pt->preconditioner_pt());
1038 
1039  if(bp_pt != 0)
1040  {
1041 #ifdef PARANOID
1042  {
1043  std::string err = "IS THIS EVER USED?";
1046  }
1047 #endif
1048 
1049  // This part of the code is never executed in the driver code.
1050  // Commented out since it no longer make sense. The functions
1051  // set_nmesh() and set_mesh() are made protected. Each derived
1052  // block preconditioner has to call set_nmesh() and set_mesh(),
1053  // since the preconditioner knows which mesh goes where, the
1054  // writer of the driver code does not necessarily know.
1055 
1056 // // Set up meshes
1057 // bp_pt->set_nmesh(nsub_mesh());
1058 // for(unsigned i=0; i< nsub_mesh(); i++)
1059 // {
1060 // bp_pt->set_mesh(i, mesh_pt(i));
1061 // }
1062  }
1063  }
1064 
1065  // Get the problem dimension
1066  if(fele_pt != 0)
1067  {
1068  Dim = fele_pt->nodal_dimension();
1069  }
1070  else
1071  {
1072  // Presumably if a "bulk" mesh contains non-finite elements
1073  // then this is not a pde, so no dimension as such.
1074  Dim = 0;
1075  }
1076 
1077  if(!Disable_mass_matrix_solver_optimisations)
1078  {
1079  // Set the solver for explicit timesteps (mass matrix) to CG with a
1080  // diagonal predconditioner.
1081  IterativeLinearSolver* expl_solver_pt = new CG<CRDoubleMatrix>;
1082  expl_solver_pt->preconditioner_pt() =
1084 
1085  // If it takes more than 100 iterations then something has almost
1086  // certainly gone wrong!
1087  expl_solver_pt->max_iter() = 100;
1088  expl_solver_pt->enable_error_after_max_iter();
1089  mass_matrix_solver_for_explicit_timestepper_pt() = expl_solver_pt;
1090 
1091  // expl_solver_pt->enable_doc_convergence_history();
1092 
1093  // Store + re-use the mass matrix used in explicit steps (since we
1094  // are almost certainly not going to do spatially adaptivity
1095  // anytime soon this is safe).
1096  this->enable_mass_matrix_reuse();
1097  }
1098 
1099 
1100  // If we requested exact solution output then check we have a solution
1101  if(Want_doc_exact && Exact_solution_pt == 0)
1102  {
1103  std::string warning = "Requested doc'ing exact solution, but we don't have an exact solution function pointer.";
1106 
1107  }
1108  }
1109 
1110 
1114  {
1115  // If using TR calculate initial derivative with these initial conditions
1116  TR* tr_pt = dynamic_cast<TR*>(time_stepper_pt());
1117  if(tr_pt != 0)
1118  {
1119  tr_pt->setup_initial_derivative(this);
1120  }
1121  }
1122 
1124  {
1125 #ifdef PARANOID
1126  if(*(Doc_info.directory().end()-1) == '/')
1127  {
1128  std::string error_msg = "Don't put a / on the end of results dir";
1129  throw OomphLibError(error_msg, OOMPH_CURRENT_FUNCTION,
1131  }
1132 #endif
1133 
1134  const std::string& dir = Doc_info.directory();
1135 
1136  // Output Jacobian if requested
1137  if((to_lower(Doc_info.output_jacobian) == "at_start")
1138  || (to_lower(Doc_info.output_jacobian) == "always"))
1139  {
1140  dump_current_mm_or_jacobian_residuals("at_start");
1141  }
1142 
1143  // pvd files
1144  // ============================================================
1145  // Write start of .pvd XML file
1146  std::ofstream pvd_file((dir + "/" + "soln.pvd").c_str(),
1147  std::ios::out);
1148  pvd_file << "<?xml version=\"1.0\"?>" << std::endl
1149  << "<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"LittleEndian\">"
1150  << std::endl
1151  << "<Collection>" << std::endl;
1152  pvd_file.close();
1153 
1154  // Write start of exact.pvd XML file
1155  if(doc_exact())
1156  {
1157  std::ofstream pvd_file((dir + "/" + "exact.pvd").c_str(),
1158  std::ios::out);
1159  pvd_file << "<?xml version=\"1.0\"?>" << std::endl
1160  << "<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"LittleEndian\">"
1161  << std::endl
1162  << "<Collection>" << std::endl;
1163  pvd_file.close();
1164  }
1165 
1166  // Trace file
1167  // ============================================================
1168 
1169  // Clear (by overwriting) and write headers
1170  std::ofstream trace_file((dir + "/" + Trace_filename).c_str());
1171  trace_file
1172  << "DocInfo_numbers"
1173  << Trace_seperator << "times"
1174  << Trace_seperator << "dts"
1175  << Trace_seperator << "error_norms"
1176 
1177  << Trace_seperator << "n_newton_iters"
1178  << Trace_seperator << "n_solver_iters"
1179 
1180  << Trace_seperator << "solver_times"
1181  << Trace_seperator << "jacobian_setup_times"
1182  << Trace_seperator << "preconditioner_setup_times"
1183 
1184  << Trace_seperator << "LTE_norms"
1185  << Trace_seperator << "trace_values"
1186 
1187  << Trace_seperator << "unix_timestamp"
1188  << Trace_seperator << "newton_residuals"
1189  << Trace_seperator << "solution_norms"
1190  << Trace_seperator << "total_step_time"
1191 
1192 
1193  // Reserved slots in case I think of more things to add later
1194  << Trace_seperator << "dummy"
1195  << Trace_seperator << "dummy"
1196  << Trace_seperator << "dummy"
1197  << Trace_seperator << "dummy"
1198  << Trace_seperator << "dummy"
1199  << Trace_seperator << "dummy";
1200 
1201  // Other headers depending on the derived class
1202  write_additional_trace_headers(trace_file);
1203 
1204  // Finish the line and close
1205  trace_file << std::endl;
1206  trace_file.close();
1207 
1208 
1209  // Info file
1210  // ============================================================
1211  std::ofstream info_file((dir + "/" + Info_filename).c_str());
1212  info_file
1213  << "real_time " << real_date_time() << std::endl
1214  << "unix_time " << std::time(0) << std::endl
1215  << "driver_name " << problem_name() << std::endl
1216  << "initial_nnode " << mesh_pt()->nnode() << std::endl
1217  << "initial_nelement " << mesh_pt()->nelement() << std::endl
1218  << "initial_nsub_mesh " << nsub_mesh() << std::endl;
1219 
1220  info_file << Doc_info.args_str;
1221  info_file.close();
1222 
1223  // If requested then output history values before t=0.
1224  if(Output_initial_condition)
1225  {
1226 #ifdef PARANOID
1227  if(ntime_stepper() != 1)
1228  {
1229  std::string err = "More/less that 1 time stepper, not sure what to output.";
1232  }
1233 #endif
1234 
1235  // Output info for each history value in order.
1236  const unsigned nval = time_stepper_pt()->nprev_values();
1237  for(unsigned it=nval-1; it>0; it--)
1238  {
1239  doc_solution(it);
1240  }
1241  }
1242 
1243  // Output boundary numbers for each boundary node
1244  // ============================================================
1245  if(Should_doc_boundaries)
1246  {
1247  this->doc_boundaries(dir + "/nodes_on_boundary");
1248  }
1249 
1250 
1251  // Write initial solution and anything else problem specific
1252  // (e.g. more trace file headers)
1253  initial_doc_additional();
1254 
1255  // Doc the initial condition
1256  this->doc_solution();
1257  }
1258 
1259  void MyProblem::doc_solution(const unsigned& t_hist,
1260  const std::string& prefix)
1261  {
1262  bool doc_this_step = true;
1263  if(!is_steady())
1264  {
1265  doc_this_step = should_doc_this_step(time_pt()->dt(t_hist),
1266  time_pt()->time(t_hist));
1267  }
1268 
1269  const std::string dir = Doc_info.directory();
1270  const std::string num = to_string(Doc_info.number());
1271 
1272  if(Always_write_trace || doc_this_step)
1273  {
1274  // Always output trace file data
1275  write_trace(t_hist);
1276  }
1277 
1278  // Output full set of data if requested for this timestep
1279  if(doc_this_step)
1280  {
1281 
1282  // Solution itself
1283  std::ofstream soln_file((dir + "/" + prefix + "soln" + num + ".dat").c_str(),
1284  std::ios::out);
1285  soln_file.precision(Output_precision);
1286  output_solution(t_hist, soln_file);
1287  soln_file.close();
1288 
1289  // Exact solution if available and requested
1290  if(doc_exact())
1291  {
1292  std::ofstream exact_file((dir + "/" + prefix + "exact" + num + ".dat").c_str(),
1293  std::ios::out);
1294  exact_file.precision(Output_precision);
1295  output_exact_solution(t_hist, exact_file);
1296  exact_file.close();
1297  }
1298 
1299  // If not a steady state problem then write time information
1300  if(!is_steady() && prefix == "")
1301  {
1302  // Write the simulation time and filename to the solution pvd
1303  // file
1304  std::ofstream pvd_file((dir + "/" + "soln.pvd").c_str(),
1305  std::ios::app);
1306  pvd_file.precision(Output_precision);
1307 
1308  pvd_file << "<DataSet timestep=\"" << time_pt()->time(t_hist)
1309  << "\" group=\"\" part=\"0\" file=\"" << "soln"
1310  << num << ".vtu"
1311  << "\"/>" << std::endl;
1312 
1313  pvd_file.close();
1314 
1315 
1316  // Write the simulation time and filename to the exact solution
1317  // pvd file
1318  if(doc_exact())
1319  {
1320  std::ofstream exact_pvd_file((dir + "/" + "exact.pvd").c_str(),
1321  std::ios::app);
1322  exact_pvd_file.precision(Output_precision);
1323 
1324  exact_pvd_file << "<DataSet timestep=\"" << time()
1325  << "\" group=\"\" part=\"0\" file=\"" << "exact"
1326  << num << ".vtu"
1327  << "\"/>" << std::endl;
1328 
1329  exact_pvd_file.close();
1330  }
1331  }
1332 
1333 
1334  // Maybe dump the restart data
1335  if(Dump)
1336  {
1337  std::ofstream dump_file((dir + "/" + "dump" + num + ".dat").c_str(),
1338  std::ios::out);
1339  this->dump(dump_file);
1340  dump_file.close();
1341  }
1342 
1343  // Maybe dump ltes
1344  if(Output_ltes)
1345  {
1346  std::ofstream ltefile((dir + "/ltes" + num + ".csv").c_str(),
1347  std::ios::out);
1348  output_ltes(t_hist, ltefile);
1349  ltefile.close();
1350  }
1351 
1352  // Maybe write out predicted values, check we only have one time
1353  // stepper first though.
1354 #ifdef PARANOID
1355  if(Output_predictor_values && ntime_stepper() != 1)
1356  {
1357  std::string err = "Can only output predictor values for a single time stepper";
1360 
1361  // Otherwise we would have multiple "predictor_time" values
1362  // below.
1363  }
1364 #endif
1365 
1366  if(t_hist != 0)
1367  {
1368  std::string err = "Can't output history of predicted value: they aren't stored.";
1370  }
1371  else if(Output_predictor_values && time_stepper_pt()->adaptive_flag())
1372  {
1373  const unsigned predictor_time =
1374  time_stepper_pt()->predictor_storage_index();
1375 
1376  std::ofstream pred_file((dir + "/" + "predsoln" + num + ".dat").c_str(),
1377  std::ios::out);
1378  pred_file.precision(Output_precision);
1379  output_solution(predictor_time, pred_file, 2);
1380  pred_file.close();
1381  }
1382 
1383 
1384  Doc_info.number()++;
1385  }
1386  }
1387 
1389  {
1390  // Check that we have finite elements ??ds this will still go wrong
1391  // if there are only some none finite elements in the mesh...
1392 
1393  //??ds what happens with face elements?
1394  FiniteElement* test_pt = dynamic_cast<FiniteElement*>
1395  (mesh_pt(0)->element_pt(0));
1396 
1397  if(test_pt != 0)
1398  {
1399  double min_size = mesh_pt(0)->finite_element_pt(0)->compute_physical_size();
1400 
1401  // Loop over all meshes in problem
1402  for(unsigned msh=0, nmsh=nsub_mesh(); msh<nmsh; msh++)
1403  {
1404  Mesh* mesh_pt = this->mesh_pt(msh);
1405  for(unsigned ele=0, nele=mesh_pt->nelement(); ele<nele; ele++)
1406  {
1407  FiniteElement* ele_pt = mesh_pt->finite_element_pt(ele);
1408  double new_size = ele_pt->compute_physical_size();
1409  if(new_size < min_size)
1410  {
1411  min_size = new_size;
1412  }
1413  }
1414  }
1415 
1416  return min_size;
1417  }
1418  // If it's not a finite element then we can't get a size so return
1419  // a dummy value.
1420  else
1421  {
1422  return Dummy_doc_data;
1423  }
1424  }
1425 
1426  void MyProblem::write_trace(const unsigned& t_hist)
1427  {
1428  std::ofstream trace_file((Doc_info.directory() + "/" + Trace_filename).c_str(),
1429  std::ios::app);
1430  trace_file.precision(Output_precision);
1431 
1432  double time = Dummy_doc_data, dt = Dummy_doc_data;
1433  if(!is_steady())
1434  {
1435  time = this->time_pt()->time(t_hist);
1436  dt = this->time_pt()->dt(t_hist);
1437  }
1438 
1439  // Some values are impossible to get for history values, print dummy
1440  // values instead.
1441  double nnewton_iter_taken = Dummy_doc_data,
1442  lte_norm = Dummy_doc_data,
1443  real_time = Dummy_doc_data,
1444  total_step_time = Dummy_doc_data;
1445 
1446  Vector<double> solver_iterations(1, Dummy_doc_data),
1447  solver_times(1, Dummy_doc_data),
1448  jacobian_setup_times(1, Dummy_doc_data),
1449  preconditioner_setup_times(1, Dummy_doc_data),
1450  max_res(1, Dummy_doc_data);
1451 
1452  if(t_hist == 0)
1453  {
1454  nnewton_iter_taken = Nnewton_iter_taken;
1455  solver_iterations = Solver_iterations;
1456  solver_times = Solver_times;
1457  jacobian_setup_times = Jacobian_setup_times;
1458  preconditioner_setup_times = Preconditioner_setup_times;
1459  real_time = std::time(0);
1460  total_step_time = Total_step_time;
1461  max_res = Max_res;
1462 
1463  if(!is_steady())
1464  {
1465  lte_norm = this->lte_norm();
1466  }
1467  }
1468 
1469  // Write out data that can be done for every problem
1470  trace_file
1471  << Doc_info.number()
1472  << Trace_seperator << time
1473  << Trace_seperator << dt
1474  << Trace_seperator << get_error_norm(t_hist)
1475 
1476  << Trace_seperator << nnewton_iter_taken;
1477 
1478  // Loop over the entries of solver_iterations and output
1479  unsigned solver_iterations_length=solver_iterations.size();
1480  if (solver_iterations_length==0)
1481  {
1482  trace_file << Trace_seperator << "[]";
1483  }
1484  else
1485  {
1486  trace_file << Trace_seperator << "[" << solver_iterations[0];
1487  if (solver_iterations_length>1)
1488  {
1489  for (unsigned i=1;i<solver_iterations_length;i++)
1490  {
1491  trace_file << ", " << solver_iterations[i];
1492  }
1493  }
1494  trace_file << "]";
1495  }
1496 
1497  // Loop over the entries of solver_times and output
1498  unsigned solver_times_length=solver_times.size();
1499  if (solver_times_length==0)
1500  {
1501  trace_file << Trace_seperator << "[]";
1502  }
1503  else
1504  {
1505  trace_file << Trace_seperator << "[" << solver_times[0];
1506  if (solver_times_length>1)
1507  {
1508  for (unsigned i=1;i<solver_times_length;i++)
1509  {
1510  trace_file << ", " << solver_times[i];
1511  }
1512  }
1513  trace_file << "]";
1514  }
1515 
1516  // Loop over the entries of jacobian_setup_times and output
1517  unsigned jacobian_setup_times_length=jacobian_setup_times.size();
1518  if (jacobian_setup_times_length==0)
1519  {
1520  trace_file << Trace_seperator << "[]";
1521  }
1522  else
1523  {
1524  trace_file << Trace_seperator << "[" << jacobian_setup_times[0];
1525  if (jacobian_setup_times_length>1)
1526  {
1527  for (unsigned i=1;i<jacobian_setup_times_length;i++)
1528  {
1529  trace_file << ", " << jacobian_setup_times[i];
1530  }
1531  }
1532  trace_file << "]";
1533  }
1534 
1535  // Loop over the entries of preconditioner_setup_times and output
1536  unsigned preconditioner_setup_times_length=preconditioner_setup_times.size();
1537  if (preconditioner_setup_times_length==0)
1538  {
1539  trace_file << Trace_seperator << "[]";
1540  }
1541  else
1542  {
1543  trace_file << Trace_seperator << "[" << preconditioner_setup_times[0];
1544  if (preconditioner_setup_times_length>1)
1545  {
1546  for (unsigned i=1;i<preconditioner_setup_times_length;i++)
1547  {
1548  trace_file << ", " << preconditioner_setup_times[i];
1549  }
1550  }
1551  trace_file << "]";
1552  }
1553 
1554  trace_file << Trace_seperator << lte_norm;
1555 
1556  // Create a temporary vector
1557  Vector<double> output_vector=trace_values(t_hist);
1558 
1559  // Loop over the entries of output_vector and output
1560  unsigned output_vector_length=output_vector.size();
1561  if (output_vector_length==0)
1562  {
1563  trace_file << Trace_seperator << "[]";
1564  }
1565  else
1566  {
1567  trace_file << Trace_seperator << "[" << output_vector[0];
1568  if (output_vector_length>1)
1569  {
1570  for (unsigned i=1;i<output_vector_length;i++)
1571  {
1572  trace_file << ", " << output_vector[i];
1573  }
1574  }
1575  trace_file << "]";
1576  }
1577 
1578  trace_file << Trace_seperator << real_time;
1579 
1580  // Loop over the entries of output_vector and output
1581  unsigned max_res_length=max_res.size();
1582  if (max_res_length==0)
1583  {
1584  trace_file << Trace_seperator << "[]";
1585  }
1586  else
1587  {
1588  trace_file << Trace_seperator << "[" << max_res[0];
1589  if (max_res_length>1)
1590  {
1591  for (unsigned i=1;i<max_res_length;i++)
1592  {
1593  trace_file << ", " << max_res[i];
1594  }
1595  }
1596  trace_file << "]";
1597  }
1598 
1599  trace_file << Trace_seperator << get_solution_norm(t_hist)
1600  << Trace_seperator << total_step_time
1601 
1602  // Reserved slots in case I think of more things to add later
1603  << Trace_seperator << Dummy_doc_data
1604  << Trace_seperator << Dummy_doc_data
1605  << Trace_seperator << Dummy_doc_data
1606  << Trace_seperator << Dummy_doc_data
1607  << Trace_seperator << Dummy_doc_data
1608  << Trace_seperator << Dummy_doc_data;
1609 
1610 
1611  // Add problem specific data
1612  write_additional_trace_data(t_hist, trace_file);
1613 
1614  // Finish off this line
1615  trace_file << std::endl;
1616  trace_file.close();
1617  }
1618 
1619  void MyProblem::doc_boundaries(const std::string& boundary_file_basename) const
1620  {
1621  const unsigned n_boundary = mesh_pt()->nboundary();
1622  for(unsigned b=0; b<n_boundary; b++)
1623  {
1624  std::ofstream boundary_file((boundary_file_basename +
1625  to_string(b) + ".csv").c_str(),
1626  std::ios::out);
1627 
1628  // write headers
1629  boundary_file << "x,y,z,b" << std::endl;
1630 
1631  const unsigned n_boundary_node = mesh_pt()->nboundary_node(b);
1632  for(unsigned nd=0; nd<n_boundary_node; nd++)
1633  {
1634  Node* node_pt = mesh_pt()->boundary_node_pt(b, nd);
1635  Vector<double> position = node_pt->position();
1636 
1637  // Write out this node
1638  for(unsigned i=0; i<dim(); i++)
1639  {
1640  boundary_file << position[i] << ",";
1641  }
1642  for(unsigned i=dim(); i<3; i++)
1643  {
1644  boundary_file << 0.0 << ",";
1645  }
1646  boundary_file << b << std::endl;
1647  }
1648 
1649  boundary_file.close();
1650  }
1651  }
1652 
1654  {
1655 
1656 #ifdef PARANOID
1657  if(nglobal_data() != 0)
1658  {
1659  std::string err = "Problem has global data which cannot be set from function pt.";
1662  }
1663 #endif
1664  unsigned nprev_steps=this->time_stepper_pt()->nprev_values();
1665  for(unsigned t=0; t< nprev_steps; t++)
1666  {
1667  // Loop over all nodes in all meshes in problem and set values.
1668  for(unsigned msh=0, nmsh=nsub_mesh(); msh<nmsh; msh++)
1669  {
1670  Mesh* mesh_pt = this->mesh_pt(msh);
1671 
1672  for(unsigned nd=0, nnd=mesh_pt->nnode(); nd<nnd; nd++)
1673  {
1674  Node* nd_pt = mesh_pt->node_pt(nd);
1675  for(unsigned j=0, nj=nd_pt->nvalue(); j<nj; j++)
1676  {
1677  nd_pt->set_value(t, j, nd_pt->value(0, j));
1678  }
1679  }
1680 
1681 #ifdef PARANOID
1682  for(unsigned ele=0, nele=mesh_pt->nelement(); ele<nele; ele++)
1683  {
1684  FiniteElement* ele_pt = mesh_pt->finite_element_pt(ele);
1685  if(ele_pt->ninternal_data() != 0)
1686  {
1687  std::string err =
1688  "Element with non-nodal data, cannot set via function...";
1691  }
1692  }
1693 #endif
1694 
1695  }
1696  }
1697 
1698  actions_after_set_initial_condition();
1699  }
1700 
1702  {
1703 #ifdef PARANOID
1704  // Can't set global data from a function of space... have to overload this
1705  // if you have any
1706  if(nglobal_data() != 0)
1707  {
1708  std::string err = "Problem has global data which cannot be set from function pt.";
1711  }
1712 #endif
1713 
1714  // Loop over current & previous timesteps (so we need t<nprev_values+1).
1715  const int nprev_values = this->time_stepper_pt()->nprev_values();
1716  for(int tindex=0; tindex<nprev_values+1; tindex++)
1717  {
1718  double time = time_pt()->time(tindex);
1719 
1720  // Loop over all nodes in all meshes in problem and set values.
1721  const unsigned nmsh = nsub_mesh();
1722  for(unsigned msh=0; msh<nmsh; msh++)
1723  {
1724  Mesh* mesh_pt = this->mesh_pt(msh);
1725 
1726  for(unsigned nd=0, nnd=mesh_pt->nnode(); nd<nnd; nd++)
1727  {
1728  Node* nd_pt = mesh_pt->node_pt(nd);
1729 
1730  // Get the position at present time
1731  const unsigned dim = nd_pt->ndim();
1732  Vector<double> x(dim);
1733  nd_pt->position(x);
1734 
1735  // Set position at tindex time to be the same as at present
1736  // (impulsive positions).
1737  for(unsigned j=0; j<dim; j++)
1738  {
1739  nd_pt->x(tindex, j) = x[j];
1740  }
1741 
1742  // Get the values
1743  Vector<double> values = ic(time, x);
1744 
1745 #ifdef PARANOID
1746  if(values.size() != nd_pt->nvalue())
1747  {
1748  std::string err = "Wrong number of values in initial condition.";
1751  }
1752 #endif
1753  // Copy into dofs
1754  for(unsigned j=0, nj=values.size(); j<nj; j++)
1755  {
1756  nd_pt->set_value(tindex, j, values[j]);
1757  }
1758  }
1759 
1760 #ifdef PARANOID
1761  // Can't set internal data like this so check that we have none.
1762  for(unsigned ele=0, nele=mesh_pt->nelement(); ele<nele; ele++)
1763  {
1764  FiniteElement* ele_pt = mesh_pt->finite_element_pt(ele);
1765  if(ele_pt->ninternal_data() != 0)
1766  {
1767  std::string err =
1768  "Element with non-nodal data, cannot set via function...";
1771  }
1772  }
1773 #endif
1774  }
1775  }
1776 
1777  actions_after_set_initial_condition();
1778  }
1779 
1780 } // End of oomph namespace
1781 
1782 #endif
AnnoyingScalar sqrt(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:134
int i
Definition: BiCGSTAB_step_by_step.cpp:9
Array< double, 1, 3 > e(1./3., 0.5, 2.)
Scalar * b
Definition: benchVecAdd.cpp:17
The conjugate gradient method.
Definition: iterative_linear_solver.h:284
long & eqn_number(const unsigned &i)
Return the equation number of the i-th stored variable.
Definition: nodes.h:367
TimeStepper *& time_stepper_pt()
Return the pointer to the timestepper.
Definition: nodes.h:238
void set_value(const unsigned &i, const double &value_)
Definition: nodes.h:271
unsigned nvalue() const
Return number of values stored in data object (incl pinned ones).
Definition: nodes.h:483
static long Is_unclassified
Definition: nodes.h:192
static long Is_segregated_solve_pinned
Definition: nodes.h:188
bool is_pinned(const unsigned &i) const
Test whether the i-th variable is pinned (1: true; 0: false).
Definition: nodes.h:417
Definition: oomph_utilities.h:499
Definition: double_vector.h:58
double norm() const
compute the 2 norm of this vector
Definition: double_vector.cc:867
Definition: elements.h:1313
virtual void output_fct(std::ostream &outfile, const unsigned &n_plot, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt)
Output an exact solution over the element.
Definition: elements.h:3104
virtual void output(std::ostream &outfile)
Definition: elements.h:3050
virtual double compute_physical_size() const
Definition: elements.h:2825
unsigned nodal_dimension() const
Return the required Eulerian dimension of the nodes in this element.
Definition: elements.h:2484
unsigned ninternal_data() const
Return the number of internal data objects.
Definition: elements.h:823
Definition: integral.h:49
Definition: iterative_linear_solver.h:54
virtual unsigned iterations() const =0
Number of iterations taken.
void enable_error_after_max_iter()
Throw an error if we don't converge within max_iter.
Definition: iterative_linear_solver.h:198
Preconditioner *& preconditioner_pt()
Access function to preconditioner.
Definition: iterative_linear_solver.h:95
virtual double preconditioner_setup_time() const
returns the the time taken to setup the preconditioner
Definition: iterative_linear_solver.h:180
unsigned & max_iter()
Access to max. number of iterations.
Definition: iterative_linear_solver.h:113
Definition: linear_solver.h:68
Matrix-based lumped preconditioner.
Definition: general_purpose_preconditioners.h:81
Definition: mesh.h:67
FiniteElement * finite_element_pt(const unsigned &e) const
Definition: mesh.h:473
unsigned long nnode() const
Return number of nodes in the mesh.
Definition: mesh.h:596
Node *& node_pt(const unsigned long &n)
Return pointer to global node n.
Definition: mesh.h:436
unsigned long nelement() const
Return number of elements in the mesh.
Definition: mesh.h:590
Definition: my_problem.h:112
std::string args_str
Definition: my_problem.h:126
void copy_args_string()
Copy dump of args into args_str.
Definition: my_problem.h:118
std::string output_jacobian
Definition: my_problem.h:125
MyDocInfo()
Default constructor.
Definition: my_problem.h:115
Definition: my_problem.h:131
Vector< double > exact_solution(const double &t, const Vector< double > &x) const
Get exact solution.
Definition: my_problem.h:909
double Total_step_time
Definition: my_problem.h:872
virtual void actions_after_explicit_stage()
Definition: my_problem.h:290
double Error_norm_limit
Definition: my_problem.h:877
bool Should_doc_boundaries
Should we output the locations of the boundary nodes?
Definition: my_problem.h:891
void initial_doc()
Definition: my_problem.h:1123
virtual void actions_before_explicit_stage()
Definition: my_problem.h:287
bool Want_doc_exact
Should we try to output exact solution?
Definition: my_problem.h:888
virtual void actions_before_time_integration()
Definition: my_problem.h:318
virtual void build(Vector< Mesh * > &bulk_mesh_pt)
Perform set up of problem.
Definition: my_problem.h:967
double smart_time_step(double dt, const double &tol)
Definition: my_problem.h:173
virtual ~MyProblem()
Definition: my_problem.h:169
virtual void set_up_impulsive_initial_condition()
Set all history values/dts to be the same as the present values/dt.
Definition: my_problem.h:1653
unsigned Output_precision
Definition: my_problem.h:869
virtual double get_error_norm(const unsigned &t_hist=0) const
Error norm calculator.
Definition: my_problem.h:627
void output_solution(std::ostream &outstream, const unsigned &npoints=2) const
Definition: my_problem.h:597
void undo_segregated_pinning()
Remove pinning set up by segregated_pin_indices.
Definition: my_problem.h:421
virtual void actions_after_explicit_timestep()
Actions that should be performed after each explicit time step.
Definition: my_problem.h:326
Vector< double > Solver_times
Definition: my_problem.h:933
virtual void actions_before_implicit_timestep()
Definition: my_problem.h:333
void segregated_pin_indices(const Vector< unsigned > &indices)
Definition: my_problem.h:376
virtual void output_solution(const unsigned &t, std::ostream &outstream, const unsigned &npoints=2) const
Definition: my_problem.h:575
void check_not_segregated(const char *function) const
Check that nothing is currently pinned for a segregated solve.
Definition: my_problem.h:443
void write_trace(const unsigned &t_hist=0)
Definition: my_problem.h:1426
SolutionFunctorBase * Exact_solution_pt
Function pointer for exact solution.
Definition: my_problem.h:906
double lte_norm()
Definition: my_problem.h:707
virtual void actions_after_set_initial_condition()
Definition: my_problem.h:1113
MyProblem()
Default constructor.
Definition: my_problem.h:134
const unsigned dim() const
Get problem dimension (nodal dimension).
Definition: my_problem.h:762
unsigned nnewton_step_this_solve() const
Definition: my_problem.h:282
virtual void actions_after_newton_step()
Definition: my_problem.h:339
void get_solver_parameters(SolverParameters &sp)
Definition: my_problem.h:210
bool Disable_mass_matrix_solver_optimisations
Definition: my_problem.h:882
virtual bool finished() const
Definition: my_problem.h:205
virtual double get_solution_norm(const unsigned &t_hist=0) const
Dummy solution norm calculator (overload in derived classes).
Definition: my_problem.h:666
virtual void my_set_initial_condition(const SolutionFunctorBase &ic)
Assign initial conditions from function pointer.
Definition: my_problem.h:1701
double min_element_size()
??ds
Definition: my_problem.h:1388
virtual void write_additional_trace_headers(std::ofstream &trace_file) const
Definition: my_problem.h:517
virtual void actions_after_implicit_timestep()
Definition: my_problem.h:331
std::string Info_filename
Definition: my_problem.h:875
virtual void actions_before_newton_solve()
Definition: my_problem.h:361
virtual void read(std::ifstream &restart_file)
Definition: my_problem.h:792
unsigned N_steps_taken
Definition: my_problem.h:871
void final_doc()
Definition: my_problem.h:533
virtual std::string problem_name() const
Definition: my_problem.h:764
Vector< double > Preconditioner_setup_times
Definition: my_problem.h:935
virtual void dump(std::ofstream &dump_file) const
Definition: my_problem.h:782
virtual void doc_boundaries(const std::string &boundary_file_basename) const
Output nodes with boundary number to csv file.
Definition: my_problem.h:1619
double Dummy_doc_data
Definition: my_problem.h:927
bool Output_predictor_values
Should we output the predicted values too?
Definition: my_problem.h:900
virtual void write_additional_trace_data(const unsigned &t_hist, std::ofstream &trace_file) const
Definition: my_problem.h:511
Vector< double > Solver_iterations
Definition: my_problem.h:934
MyProblem(const MyProblem &dummy)
Inaccessible copy constructor.
Definition: my_problem.h:941
virtual void output_exact_solution(const unsigned &t_hist, std::ostream &outstream, const unsigned &npoints=2) const
Definition: my_problem.h:605
bool explicit_flag()
Definition: my_problem.h:256
Vector< double > Jacobian_setup_times
Definition: my_problem.h:932
void doc_solution(const unsigned &t_hist=0, const std::string &prefix="")
Definition: my_problem.h:1259
bool Output_ltes
Should we output the local truncation error at each node as well?
Definition: my_problem.h:897
unsigned Dim
Definition: my_problem.h:928
MyDocInfo Doc_info
Definition: my_problem.h:868
bool Dump
Should we dump ready for a restart?
Definition: my_problem.h:894
Vector< double > Doc_times
Times at which we want to output the full solution.
Definition: my_problem.h:938
double Solution_norm_limit
Definition: my_problem.h:878
virtual void actions_before_newton_step()
Definition: my_problem.h:268
const std::string Trace_seperator
Definition: my_problem.h:926
virtual double integrate_over_problem(const ElementalFunction *func_pt, const Integral *quadrature_pt=0) const
Definition: my_problem.h:951
void check_norm_limits()
Definition: my_problem.h:467
virtual void output_solution(std::ofstream &soln_file) const
Overload to write any problem specific data.
Definition: my_problem.h:521
void dump_current_mm_or_jacobian_residuals(const std::string &label)
Definition: my_problem.h:960
bool Output_initial_condition
Should we write output for initial conditions as though they are time steps as well?
Definition: my_problem.h:903
virtual bool should_doc_this_step(const double &dt, const double &time) const
Definition: my_problem.h:676
virtual void initial_doc_additional() const
Definition: my_problem.h:523
void set_doc_times(Vector< double > &doc_times)
Assign a vector of times to output the full solution at.
Definition: my_problem.h:699
bool doc_exact() const
Definition: my_problem.h:720
bool is_steady()
Definition: my_problem.h:262
bool Always_write_trace
Should we output to trace file every step?
Definition: my_problem.h:885
virtual void final_doc_additional() const
Definition: my_problem.h:522
virtual Vector< double > trace_values(const unsigned &t_hist=0) const
Definition: my_problem.h:725
std::string Trace_filename
Definition: my_problem.h:874
virtual void actions_before_explicit_timestep()
Actions that should be performed before each explicit time step.
Definition: my_problem.h:320
void output_ltes(const unsigned &t_hist, std::ostream &output) const
Definition: my_problem.h:824
void set_solver_parameters(SolverParameters &sp)
Definition: my_problem.h:233
IterativeLinearSolver * iterative_linear_solver_pt() const
Definition: my_problem.h:751
void operator=(const MyProblem &dummy)
Inaccessible assignment operator.
Definition: my_problem.h:945
Definition: nodes.h:906
double & x(const unsigned &i)
Return the i-th nodal coordinate.
Definition: nodes.h:1060
void position(Vector< double > &pos) const
Definition: nodes.cc:2499
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
Definition: nodes.h:1054
double value(const unsigned &i) const
Definition: nodes.cc:2408
Definition: oomph_definitions.h:222
Definition: oomph_definitions.h:267
Definition: preconditioner.h:54
Definition: problem.h:151
virtual void actions_after_newton_solve()
Definition: problem.h:1038
virtual void dump(std::ofstream &dump_file) const
Definition: problem.cc:12029
virtual void read(std::ifstream &restart_file, bool &unsteady_restart)
Definition: problem.cc:12251
Definition: oomph_utilities.h:1109
Definition: trapezoid_rule.h:46
void setup_initial_derivative(Problem *problem_pt)
Definition: trapezoid_rule.h:189
Definition: timesteppers.h:231
void output_vector(const Vector< myType > &given_vector)
Definition: crdoublematrix_copy_constructor.cc:49
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bfloat16 pow(const bfloat16 &a, const bfloat16 &b)
Definition: BFloat16.h:625
DocInfo Doc_info
Helper for documenting.
Definition: extrude_triangle_generated_mesh.cc:57
void exact_solution(const double &time, const Vector< double > &x, Vector< double > &u)
Definition: axisym_linear_elasticity/cylinder/cylinder.cc:203
static const unsigned Dim
Problem dimension.
Definition: two_d_tilted_square.cc:62
label
Definition: UniformPSDSelfTest.py:24
int error
Definition: calibrate.py:297
void broken_assign(const std::string &class_name)
Issue error message and terminate execution.
Definition: oomph_utilities.cc:195
void broken_copy(const std::string &class_name)
Issue error message and terminate execution.
Definition: oomph_utilities.cc:212
void doc_all_flags(std::ostream &outstream)
Document the values of all flags (specified or not).
Definition: oomph_utilities.cc:562
std::string string(const unsigned &i)
Definition: oomph_definitions.cc:286
std::string to_string(T object, unsigned float_precision=8)
Definition: oomph_utilities.h:189
std::string to_lower(const std::string &input)
Convert a string to lower case (outputs a copy).
Definition: oomph_utilities.cc:345
double timer()
returns the time in seconds after some point in past
Definition: oomph_utilities.cc:1295
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
Definition: AnisotropicHookean.h:10
void output(std::ostream &outfile)
Output with default number of plot points.
Definition: gen_axisym_advection_diffusion_elements.h:161
std::string real_date_time()
Definition: my_problem.h:64
OomphInfo oomph_info
Definition: oomph_definitions.cc:319
T smart_cast_preconditioner(Preconditioner *prec_pt)
Definition: my_problem.h:47
list x
Definition: plotDoE.py:28
t
Definition: plotPSD.py:36
#define OOMPH_EXCEPTION_LOCATION
Definition: oomph_definitions.h:61
#define OOMPH_CURRENT_FUNCTION
Definition: oomph_definitions.h:86
Definition: my_problem.h:82
bool always_take_one_newton_step
Definition: my_problem.h:96
bool shut_up_in_newton_solve
Definition: my_problem.h:95
bool problem_is_nonlinear
Definition: my_problem.h:101
bool mass_matrix_reuse_is_enabled
Definition: my_problem.h:105
bool mass_matrix_has_been_computed
Definition: my_problem.h:106
bool discontinuous_element_formulation
Definition: my_problem.h:107
bool jacobian_reuse_is_enabled
Definition: my_problem.h:99
unsigned max_newton_iterations
Definition: my_problem.h:93
SolverParameters()
Definition: my_problem.h:83
double max_residuals
Definition: my_problem.h:94
double newton_solver_tolerance
Definition: my_problem.h:92
bool jacobian_has_been_computed
Definition: my_problem.h:100
LinearSolver * mass_matrix_solver_for_explicit_timestepper_pt
Definition: my_problem.h:104
LinearSolver * linear_solver_pt
Definition: my_problem.h:89
std::ofstream out("Result.txt")
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2