oomph::PeriodicOrbitAssemblyHandler< NNODE_1D > Class Template Reference

#include <periodic_orbit_handler.h>

+ Inheritance diagram for oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >:

Public Member Functions

 PeriodicOrbitAssemblyHandler (Problem *const &problem_pt, const unsigned &n_element_in_period, const DenseMatrix< double > &initial_guess, const double &omega)
 Constructor, initialises values and constructs mesh of elements. More...
 
void set_previous_dofs_to_current_dofs ()
 Update the previous dofs. More...
 
unsigned ndof (GeneralisedElement *const &elem_pt)
 Return the number of degrees of freedom in the element elem_pt. More...
 
unsigned long eqn_number (GeneralisedElement *const &elem_pt, const unsigned &ieqn_local)
 
void get_residuals (GeneralisedElement *const &elem_pt, Vector< double > &residuals)
 Return the contribution to the residuals of the element elem_pt. More...
 
void get_dofs_for_element (GeneralisedElement *const elem_pt, Vector< double > &dofs)
 
void get_previous_dofs_for_element (GeneralisedElement *const elem_pt, Vector< double > &dofs)
 
void set_dofs_for_element (GeneralisedElement *const elem_pt, Vector< double > const &dofs)
 
void get_jacobian (GeneralisedElement *const &elem_pt, Vector< double > &residuals, DenseMatrix< double > &jacobian)
 
void orbit_output (std::ostream &outfile, const unsigned &n_plot)
 Return the contribution to the residuals of the element elem_pt. More...
 
void discrete_times (Vector< double > &t)
 Tell me the times at which you want the solution. More...
 
void adapt_temporal_mesh ()
 Adapt the time mesh. More...
 
 ~PeriodicOrbitAssemblyHandler ()
 Destructor, destroy the time mesh. More...
 
- Public Member Functions inherited from oomph::PeriodicOrbitAssemblyHandlerBase
 PeriodicOrbitAssemblyHandlerBase ()
 
- Public Member Functions inherited from oomph::AssemblyHandler
 AssemblyHandler ()
 Empty constructor. More...
 
virtual void dof_vector (GeneralisedElement *const &elem_pt, const unsigned &t, Vector< double > &dof)
 Return vector of dofs at time level t in the element elem_pt. More...
 
virtual void dof_pt_vector (GeneralisedElement *const &elem_pt, Vector< double * > &dof_pt)
 Return vector of pointers to dofs in the element elem_pt. More...
 
virtual doublelocal_problem_dof (Problem *const &problem_pt, const unsigned &t, const unsigned &i)
 
virtual void get_all_vectors_and_matrices (GeneralisedElement *const &elem_pt, Vector< Vector< double >> &vec, Vector< DenseMatrix< double >> &matrix)
 
virtual void get_dresiduals_dparameter (GeneralisedElement *const &elem_pt, double *const &parameter_pt, Vector< double > &dres_dparam)
 
virtual void get_djacobian_dparameter (GeneralisedElement *const &elem_pt, double *const &parameter_pt, Vector< double > &dres_dparam, DenseMatrix< double > &djac_dparam)
 
virtual void get_hessian_vector_products (GeneralisedElement *const &elem_pt, Vector< double > const &Y, DenseMatrix< double > const &C, DenseMatrix< double > &product)
 
virtual int bifurcation_type () const
 
virtual doublebifurcation_parameter_pt () const
 
virtual void get_eigenfunction (Vector< DoubleVector > &eigenfunction)
 
virtual void get_inner_products (GeneralisedElement *const &elem_pt, Vector< std::pair< unsigned, unsigned >> const &history_index, Vector< double > &inner_product)
 
virtual void get_inner_product_vectors (GeneralisedElement *const &elem_pt, Vector< unsigned > const &history_index, Vector< Vector< double >> &inner_product_vector)
 
virtual ~AssemblyHandler ()
 Empty virtual destructor. More...
 

Private Attributes

PeriodicOrbitTimeDiscretisationTime_stepper_pt
 Pointer to the timestepper. More...
 
ProblemProblem_pt
 Pointer to the problem. More...
 
PeriodicOrbitTemporalMesh< SpectralPeriodicOrbitElement< NNODE_1D > > * Time_mesh_pt
 Storage for mesh of temporal elements. More...
 
MeshBasic_time_mesh_pt
 Storage for the mesh of temporal elements with a simple mesh pointer. More...
 
Vector< doublePrevious_dofs
 Storage for the previous solution. More...
 
unsigned Ndof
 Store number of degrees of freedom in the original problem. More...
 
unsigned N_element_in_period
 Storage for number of elements in the period. More...
 
unsigned N_tstorage
 Storage for the number of unknown time values. More...
 
double Omega
 Storage for the frequency of the orbit (scaled by 2pi) More...
 

Detailed Description

template<unsigned NNODE_1D>
class oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >

A class that is used to assemble and solve the augmented system of equations associated with calculating periodic orbits directly

Constructor & Destructor Documentation

◆ PeriodicOrbitAssemblyHandler()

template<unsigned NNODE_1D>
oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::PeriodicOrbitAssemblyHandler ( Problem *const &  problem_pt,
const unsigned n_element_in_period,
const DenseMatrix< double > &  initial_guess,
const double omega 
)
inline

Constructor, initialises values and constructs mesh of elements.

728  : Problem_pt(problem_pt),
729  N_element_in_period(n_element_in_period),
731  {
732  // Store the current number of degrees of freedom
733  Ndof = problem_pt->ndof();
734 
735  // Create the appropriate mesh of "1D" time elements depending on
736  // the specified spectral order
737  // The time domain runs from zero to one
738  Time_mesh_pt =
739  new PeriodicOrbitTemporalMesh<SpectralPeriodicOrbitElement<NNODE_1D>>(
740  n_element_in_period);
741 
743 
744  // Set the error estimator
745  Time_mesh_pt->spatial_error_estimator_pt() = new Z2ErrorEstimator;
746  Time_mesh_pt->max_permitted_error() = 1.0e-2;
747  Time_mesh_pt->min_permitted_error() = 1.0e-5;
748  Time_mesh_pt->max_refinement_level() = 10;
749 
750  // Now we need to number the mesh
751  // Dummy dof pointer
752  Vector<double*> dummy_dof_pt;
753  Time_mesh_pt->assign_global_eqn_numbers(dummy_dof_pt);
754  // Assign the local equation numbers
755  Time_mesh_pt->assign_local_eqn_numbers(false);
756 
757  // Find the number of temporal degrees of freedom
758  N_tstorage = dummy_dof_pt.size();
759 
760  // Now we need to do something clever to setup the time storage schemes
761  // and the initial values (don't quite know what that is yet)
762 
763  // Create the "fake" timestepper
764  Time_stepper_pt = new PeriodicOrbitTimeDiscretisation(N_tstorage);
765  // Loop over the temporal elements and set the pointers
766  for (unsigned e = 0; e < n_element_in_period; e++)
767  {
768  SpectralPeriodicOrbitElement<NNODE_1D>* el_pt =
769  dynamic_cast<SpectralPeriodicOrbitElement<NNODE_1D>*>(
770  Time_mesh_pt->element_pt(e));
771 
772  // Set the time and the timestepper
773  el_pt->time_pt() = problem_pt->time_pt();
774  el_pt->time_stepper_pt() = Time_stepper_pt;
775 
776  // Set the number of temporal degrees of freedom
777  el_pt->set_ntstorage(N_tstorage);
778  // Set the frequency
779  el_pt->omega_pt() = &Omega;
780  }
781 
782  // We now need to do something much more drastic which is to loop over all
783  // our the data in the problem and change the timestepper, which is going
784  // to be a real pain when I start to worry about halo nodes, etc.
785 
786  // Will need to use the appropriate mesh-level functions that have
787  // not been written yet ..
788 
789  // Let's just break if there are submeshes
790  if (problem_pt->nsub_mesh() > 0)
791  {
792  throw OomphLibError(
793  "PeriodicOrbitHandler can't cope with submeshes yet",
796  }
797 
798  // OK now we have only one mesh
799  unsigned n_node = problem_pt->mesh_pt()->nnode();
800  for (unsigned n = 0; n < n_node; n++)
801  {
802  Node* const nod_pt = problem_pt->mesh_pt()->node_pt(n);
803  nod_pt->set_time_stepper(Time_stepper_pt, false);
804  // If the unknowns are pinned then copy the value to all values
805  unsigned n_value = nod_pt->nvalue();
806  for (unsigned i = 0; i < n_value; i++)
807  {
808  if (nod_pt->is_pinned(i))
809  {
810  const unsigned n_tstorage = nod_pt->ntstorage();
811  const double value = nod_pt->value(i);
812  for (unsigned t = 1; t < n_tstorage; t++)
813  {
814  nod_pt->set_value(t, i, value);
815  }
816  }
817  }
818  }
819 
820  unsigned n_element = problem_pt->mesh_pt()->nelement();
821  for (unsigned e = 0; e < n_element; e++)
822  {
823  unsigned n_internal =
824  problem_pt->mesh_pt()->element_pt(e)->ninternal_data();
825  for (unsigned i = 0; i < n_internal; i++)
826  {
827  // Cache the internal data
828  Data* const data_pt =
829  problem_pt->mesh_pt()->element_pt(e)->internal_data_pt(i);
830  // and set the timestepper
831  data_pt->set_time_stepper(Time_stepper_pt, false);
832 
833  // If the unknowns are pinned then copy the value to all values
834  unsigned n_value = data_pt->nvalue();
835  for (unsigned j = 0; j < n_value; j++)
836  {
837  if (data_pt->is_pinned(j))
838  {
839  const unsigned n_tstorage = data_pt->ntstorage();
840  const double value = data_pt->value(j);
841  for (unsigned t = 1; t < n_tstorage; t++)
842  {
843  data_pt->set_value(t, j, value);
844  }
845  }
846  }
847  }
848  }
849 
850  // Need to reassign equation numbers so that the DOF pointer, points to
851  // the newly allocated storage
852  oomph_info << "Re-allocated " << problem_pt->assign_eqn_numbers()
853  << " equation numbers\n";
854 
855  // Now's let's add all the unknowns to the problem
856  problem_pt->Dof_pt.resize(Ndof * N_tstorage + 1);
857  // This is reasonably straight forward using pointer arithmetic
858  // but this does rely on knowing how the data is stored in the
859  // Nodes which is a little nasty
860  for (unsigned i = 0; i < N_tstorage; i++)
861  {
862  unsigned offset = Ndof * i;
863  for (unsigned n = 0; n < Ndof; n++)
864  {
865  problem_pt->Dof_pt[offset + n] = problem_pt->Dof_pt[n] + i;
866  }
867  }
868 
869  // Add the frequency of the orbit to the unknowns
870  problem_pt->Dof_pt[Ndof * N_tstorage] = &Omega;
871 
872  // Rebuild everything
873  problem_pt->Dof_distribution_pt->build(
874  problem_pt->communicator_pt(), Ndof * N_tstorage + 1, true);
875 
876 
877  // Set initial condition of constant-ness plus wobble
878  for (unsigned i = 0; i < N_tstorage; i++)
879  {
880  unsigned offset = Ndof * i;
881  for (unsigned n = 0; n < Ndof; n++)
882  {
883  problem_pt->dof(offset + n) =
884  initial_guess(i, n); // problem_pt->dof(n);
885  }
886  }
887 
888  // Set the initial unkowns to be the original problem
889  Previous_dofs.resize(Ndof * N_tstorage + 1, 0.0);
891 
892  // Now check everything is OK ... it seems to be
893  // std::cout << problem_pt->ndof() << "\n";
894  // Let's check it
895  // for(unsigned i=0;i<problem_pt->ndof();i++)
896  // {
897  // std::cout << i << " " << problem_pt->dof(i) << "\n";
898  //}
899  }
int i
Definition: BiCGSTAB_step_by_step.cpp:9
const unsigned n
Definition: CG3DPackingUnitTest.cpp:11
Array< double, 1, 3 > e(1./3., 0.5, 2.)
unsigned N_element_in_period
Storage for number of elements in the period.
Definition: periodic_orbit_handler.h:713
unsigned Ndof
Store number of degrees of freedom in the original problem.
Definition: periodic_orbit_handler.h:710
PeriodicOrbitTemporalMesh< SpectralPeriodicOrbitElement< NNODE_1D > > * Time_mesh_pt
Storage for mesh of temporal elements.
Definition: periodic_orbit_handler.h:701
Vector< double > Previous_dofs
Storage for the previous solution.
Definition: periodic_orbit_handler.h:707
void set_previous_dofs_to_current_dofs()
Update the previous dofs.
Definition: periodic_orbit_handler.h:902
Problem * Problem_pt
Pointer to the problem.
Definition: periodic_orbit_handler.h:697
unsigned N_tstorage
Storage for the number of unknown time values.
Definition: periodic_orbit_handler.h:716
PeriodicOrbitTimeDiscretisation * Time_stepper_pt
Pointer to the timestepper.
Definition: periodic_orbit_handler.h:694
Mesh * Basic_time_mesh_pt
Storage for the mesh of temporal elements with a simple mesh pointer.
Definition: periodic_orbit_handler.h:704
double Omega
Storage for the frequency of the orbit (scaled by 2pi)
Definition: periodic_orbit_handler.h:719
Vector::Scalar omega(const Vector &t, const Vector &s, RealScalar angle)
Definition: IDRS.h:36
squared absolute value
Definition: GlobalFunctions.h:87
const double Pi
50 digits from maple
Definition: oomph_utilities.h:157
OomphInfo oomph_info
Definition: oomph_definitions.cc:319
t
Definition: plotPSD.py:36
#define OOMPH_EXCEPTION_LOCATION
Definition: oomph_definitions.h:61
#define OOMPH_CURRENT_FUNCTION
Definition: oomph_definitions.h:86
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2

◆ ~PeriodicOrbitAssemblyHandler()

template<unsigned NNODE_1D>
oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::~PeriodicOrbitAssemblyHandler ( )
inline

Destructor, destroy the time mesh.

1451  {
1452  delete Time_mesh_pt;
1453  }

References oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::Time_mesh_pt.

Member Function Documentation

◆ adapt_temporal_mesh()

template<unsigned NNODE_1D>
void oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::adapt_temporal_mesh ( )
inline

Adapt the time mesh.

1046  {
1047  // First job is to compute some sort of error measure
1048  // Then we can decide how to refine this is probably best handled
1049  // separately for now
1050 
1051  // The current plan is to copy all (locally held in the case of
1052  // distributed problem) spatial degrees of freedom into the dummy
1053  // storage of the time mesh
1054 
1055  // Probably should kick this down to the mesh level...
1056 
1057  // OK, let's do it, count up all values
1058  unsigned total_n_value = 0;
1059 
1060  // Firstly the global data in the mesh
1061  unsigned n_global_data = Problem_pt->nglobal_data();
1062  for (unsigned i = 0; i < n_global_data; i++)
1063  {
1064  total_n_value += Problem_pt->global_data_pt(i)->nvalue();
1065  }
1066 
1067  // Now the nodal data
1068  unsigned n_node = Problem_pt->mesh_pt()->nnode();
1069  for (unsigned n = 0; n < n_node; n++)
1070  {
1071  total_n_value += Problem_pt->mesh_pt()->node_pt(n)->nvalue();
1072  SolidNode* solid_nod_pt =
1073  dynamic_cast<SolidNode*>(Problem_pt->mesh_pt()->node_pt(n));
1074  if (solid_nod_pt != 0)
1075  {
1076  total_n_value += solid_nod_pt->variable_position_pt()->nvalue();
1077  }
1078  }
1079 
1080  // Now just do the internal data
1081  unsigned n_space_element = Problem_pt->mesh_pt()->nelement();
1082  for (unsigned e = 0; e < n_space_element; e++)
1083  {
1084  const unsigned n_internal_data =
1086  for (unsigned i = 0; i < n_internal_data; i++)
1087  {
1088  total_n_value +=
1090  }
1091  }
1092 
1093  // Now in theory I know the total number of values in the problem
1094  // So I can create another Fake timestepper
1095  TimeStepper* fake_space_time_stepper_pt =
1096  new PeriodicOrbitTimeDiscretisation(total_n_value);
1097 
1098  // Now apply this time stepper to all time nodes
1099  unsigned n_time_node = Time_mesh_pt->nnode();
1100  for (unsigned t = 0; t < n_time_node; t++) // Do include the periodic one
1101  {
1102  Time_mesh_pt->node_pt(t)->set_time_stepper(fake_space_time_stepper_pt,
1103  false);
1104  }
1105 
1106  // Now I "just" copy the values into the new storage
1107  unsigned count = 0;
1108  for (unsigned i = 0; i < n_global_data; i++)
1109  {
1110  Data* const glob_data_pt = Problem_pt->global_data_pt(i);
1111  const unsigned n_value = glob_data_pt->nvalue();
1112  for (unsigned j = 0; j < n_value; j++)
1113  {
1114  for (unsigned t = 0; t < N_tstorage; t++)
1115  {
1116  // Some heavy assumptions here about the time mesh, but that's OK
1117  // because I know exactly how it's laid out
1118  Time_mesh_pt->node_pt(t)->set_value(
1119  count, 0, glob_data_pt->value(t, j));
1120  }
1121  ++count;
1122  }
1123  }
1124 
1125  // Now the nodal data
1126  for (unsigned n = 0; n < n_node; n++)
1127  {
1128  Node* const nod_pt = Problem_pt->mesh_pt()->node_pt(n);
1129  const unsigned n_value = nod_pt->nvalue();
1130  for (unsigned i = 0; i < n_value; i++)
1131  {
1132  for (unsigned t = 0; t < N_tstorage; t++)
1133  {
1134  Time_mesh_pt->node_pt(t)->set_value(count, 0, nod_pt->value(t, i));
1135  }
1136  ++count;
1137  }
1138 
1139  // Now deal with the solid node data
1140  SolidNode* solid_nod_pt = dynamic_cast<SolidNode*>(nod_pt);
1141  if (solid_nod_pt != 0)
1142  {
1143  const unsigned n_solid_value =
1144  solid_nod_pt->variable_position_pt()->nvalue();
1145  for (unsigned i = 0; i < n_solid_value; i++)
1146  {
1147  for (unsigned t = 0; t < N_tstorage; t++)
1148  {
1149  Time_mesh_pt->node_pt(t)->set_value(
1150  count, 0, solid_nod_pt->variable_position_pt()->value(t, i));
1151  }
1152  ++count;
1153  }
1154  }
1155  }
1156 
1157  // Now just do the internal data
1158  for (unsigned e = 0; e < n_space_element; e++)
1159  {
1160  const unsigned n_internal =
1162  for (unsigned i = 0; i < n_internal; i++)
1163  {
1164  Data* const internal_dat_pt =
1166 
1167  const unsigned n_value = internal_dat_pt->nvalue();
1168  for (unsigned j = 0; j < n_value; j++)
1169  {
1170  for (unsigned t = 0; t < N_tstorage; t++)
1171  {
1172  Time_mesh_pt->node_pt(t)->set_value(
1173  count, 0, internal_dat_pt->value(t, j));
1174  }
1175  ++count;
1176  }
1177  }
1178  }
1179 
1180 
1181  // Think it's done but let's check
1182  /*{
1183  std::ofstream munge("data_remunge.dat");
1184  const unsigned n_time_element = Time_mesh_pt->nelement();
1185  for(unsigned e=0;e<n_time_element;e++)
1186  {
1187  const unsigned n_node = Time_mesh_pt->nnode();
1188  for(unsigned n=0;n<n_node;n++)
1189  {
1190  Node* const nod_pt = Time_mesh_pt->node_pt(n);
1191  munge << nod_pt->x(0) << " ";
1192  const unsigned n_space_storage = nod_pt->ntstorage();
1193  for(unsigned t=0;t<n_space_storage;t++)
1194  {
1195  munge << nod_pt->value(t,0) << " ";
1196  }
1197  munge << std::endl;
1198  }
1199  }
1200  munge.close();
1201  }*/
1202 
1203  // Ok get the elemental errors
1204  const unsigned n_time_element = Time_mesh_pt->nelement();
1205  Vector<double> elemental_error(n_time_element);
1206  Time_mesh_pt->spatial_error_estimator_pt()->get_element_errors(
1207  Problem_pt->communicator_pt(), Basic_time_mesh_pt, elemental_error);
1208 
1209  // Let's dump it
1210  for (unsigned e = 0; e < n_time_element; e++)
1211  {
1212  oomph_info << e << " " << elemental_error[e] << "\n";
1213  }
1214 
1215  // Now adapt the mesh
1216  Time_mesh_pt->adapt(Problem_pt->communicator_pt(), elemental_error);
1217 
1218  // I seem to have remunged the data,
1219  // Now let's pretend that we have done the the error adaptation
1220  // Time_mesh_pt->refine_uniformly();
1221 
1222  // Let's just refine the central elements twice
1223  // Vector<unsigned> refine_elements;
1224  // refine_elements.push_back(0);
1225  // refine_elements.push_back(9);
1226  // Time_mesh_pt->refine_selected_elements(refine_elements);
1227  // refine_elements.clear();
1228  // refine_elements.push_back(0);
1229  // refine_elements.push_back(1);
1230  // refine_elements.push_back(10);
1231  // refine_elements.push_back(11);
1232  // Time_mesh_pt->refine_selected_elements(refine_elements);
1233 
1234  /* std::ofstream munge("data_refine.dat");
1235  const unsigned n_time_element = Time_mesh_pt->nelement();
1236  for(unsigned e=0;e<n_time_element;e++)
1237  {
1238  const unsigned n_node = Time_mesh_pt->nnode();
1239  for(unsigned n=0;n<n_node;n++)
1240  {
1241  Node* const nod_pt = Time_mesh_pt->node_pt(n);
1242  munge << nod_pt->x(0) << " ";
1243  const unsigned n_space_storage = nod_pt->ntstorage();
1244  for(unsigned t=0;t<n_space_storage;t++)
1245  {
1246  munge << nod_pt->value(t,0) << " ";
1247  }
1248  munge << std::endl;
1249  }
1250  }
1251  munge.close();*/
1252 
1253  // Now we need to put the refined data back into the problem
1254 
1255  // Now we need to number the mesh
1256  // Dummy dof pointer
1257  Vector<double*> dummy_dof_pt;
1258  Time_mesh_pt->assign_global_eqn_numbers(dummy_dof_pt);
1259  // Assign the local equation numbers
1260  Time_mesh_pt->assign_local_eqn_numbers(false);
1261 
1262  // Find the number of temporal degrees of freedom
1263  N_tstorage = dummy_dof_pt.size();
1264  // and new number of elements
1265  N_element_in_period = Time_mesh_pt->nelement();
1266 
1267  // Create the new "fake" timestepper
1268  PeriodicOrbitTimeDiscretisation* periodic_time_stepper_pt =
1269  new PeriodicOrbitTimeDiscretisation(N_tstorage);
1270 
1271  // Loop over the temporal elements and set the pointers
1272  for (unsigned e = 0; e < N_element_in_period; e++)
1273  {
1274  SpectralPeriodicOrbitElement<NNODE_1D>* el_pt =
1275  dynamic_cast<SpectralPeriodicOrbitElement<NNODE_1D>*>(
1276  Time_mesh_pt->element_pt(e));
1277 
1278  // Set the time and the timestepper
1279  el_pt->time_pt() = Problem_pt->time_pt();
1280  el_pt->time_stepper_pt() = periodic_time_stepper_pt;
1281 
1282  // Set the number of temporal degrees of freedom
1283  el_pt->set_ntstorage(N_tstorage);
1284  // Set the frequency
1285  el_pt->omega_pt() = &Omega;
1286  }
1287 
1288  // We now need to do something much more drastic which is to loop over all
1289  // our the data in the problem and change the timestepper, which is going
1290  // to be a real pain when I start to worry about halo nodes, etc.
1291 
1292  // Will need to use the appropriate mesh-level functions that have
1293  // not been written yet ..
1294 
1295  // Let's just break if there are submeshes
1296  if (Problem_pt->nsub_mesh() > 0)
1297  {
1298  throw OomphLibError(
1299  "PeriodicOrbitHandler can't cope with submeshes yet",
1302  }
1303 
1304  // OK now we have only one mesh
1305  for (unsigned n = 0; n < n_node; n++)
1306  {
1307  Node* const nod_pt = Problem_pt->mesh_pt()->node_pt(n);
1308  nod_pt->set_time_stepper(periodic_time_stepper_pt, false);
1309  }
1310 
1311  for (unsigned e = 0; e < n_space_element; e++)
1312  {
1313  unsigned n_internal =
1315  for (unsigned i = 0; i < n_internal; i++)
1316  {
1317  // Cache the internal data
1318  Data* const data_pt =
1320  // and set the timestepper
1321  data_pt->set_time_stepper(periodic_time_stepper_pt, false);
1322  }
1323  }
1324 
1325  // Now I can delete the old timestepper and switch
1326  delete Time_stepper_pt;
1327  Time_stepper_pt = periodic_time_stepper_pt;
1328 
1329  // Need to reassign equation numbers so that the DOF pointer, points to
1330  // the newly allocated storage
1331  oomph_info << "Re-allocated " << Problem_pt->assign_eqn_numbers()
1332  << " equation numbers\n";
1333 
1334  // Now's let's add all the unknowns to the problem
1335  Problem_pt->Dof_pt.resize(Ndof * N_tstorage + 1);
1336  // This is reasonably straight forward using pointer arithmetic
1337  // but this does rely on knowing how the data is stored in the
1338  // Nodes which is a little nasty
1339  for (unsigned i = 0; i < N_tstorage; i++)
1340  {
1341  unsigned offset = Ndof * i;
1342  for (unsigned n = 0; n < Ndof; n++)
1343  {
1344  Problem_pt->Dof_pt[offset + n] = Problem_pt->Dof_pt[n] + i;
1345  }
1346  }
1347 
1348  // Add the frequency of the orbit to the unknowns
1350 
1351  // Rebuild everything
1353  Problem_pt->communicator_pt(), Ndof * N_tstorage + 1, true);
1354 
1355 
1356  // Now finally transfer the solution accross
1357 
1358  // Now I "just" copy the values into the new storage
1359  count = 0;
1360  for (unsigned i = 0; i < n_global_data; i++)
1361  {
1362  Data* const glob_data_pt = Problem_pt->global_data_pt(i);
1363  const unsigned n_value = glob_data_pt->nvalue();
1364  for (unsigned j = 0; j < n_value; j++)
1365  {
1366  for (unsigned t = 0; t < N_tstorage; t++)
1367  {
1368  // Some heavy assumptions here about the time mesh, but that's OK
1369  // because I know exactly how it's laid out
1370  glob_data_pt->set_value(
1371  t, j, Time_mesh_pt->node_pt(t)->value(count, 0));
1372  }
1373  ++count;
1374  }
1375  }
1376 
1377  // Now the nodal data
1378  for (unsigned n = 0; n < n_node; n++)
1379  {
1380  Node* const nod_pt = Problem_pt->mesh_pt()->node_pt(n);
1381  const unsigned n_value = nod_pt->nvalue();
1382  for (unsigned i = 0; i < n_value; i++)
1383  {
1384  for (unsigned t = 0; t < N_tstorage; t++)
1385  {
1386  nod_pt->set_value(t, i, Time_mesh_pt->node_pt(t)->value(count, 0));
1387  }
1388  ++count;
1389  }
1390 
1391  // Now deal with the solid node data
1392  SolidNode* solid_nod_pt = dynamic_cast<SolidNode*>(nod_pt);
1393  if (solid_nod_pt != 0)
1394  {
1395  const unsigned n_solid_value =
1396  solid_nod_pt->variable_position_pt()->nvalue();
1397  for (unsigned i = 0; i < n_solid_value; i++)
1398  {
1399  for (unsigned t = 0; t < N_tstorage; t++)
1400  {
1401  solid_nod_pt->variable_position_pt()->set_value(
1402  t, i, Time_mesh_pt->node_pt(t)->value(count, 0));
1403  }
1404  ++count;
1405  }
1406  }
1407  }
1408 
1409  // Now just do the internal data
1410  for (unsigned e = 0; e < n_space_element; e++)
1411  {
1412  const unsigned n_internal =
1414  for (unsigned i = 0; i < n_internal; i++)
1415  {
1416  Data* const internal_dat_pt =
1418 
1419  const unsigned n_value = internal_dat_pt->nvalue();
1420  for (unsigned j = 0; j < n_value; j++)
1421  {
1422  for (unsigned t = 0; t < N_tstorage; t++)
1423  {
1424  internal_dat_pt->set_value(
1425  t, j, Time_mesh_pt->node_pt(t)->value(count, 0));
1426  }
1427  ++count;
1428  }
1429  }
1430  }
1431 
1432 
1433  // Now I should be able to delete the fake time timestepper
1434  n_time_node = Time_mesh_pt->nnode();
1435  for (unsigned t = 0; t < n_time_node; t++)
1436  {
1437  Time_mesh_pt->node_pt(t)->set_time_stepper(&Mesh::Default_TimeStepper,
1438  false);
1439  }
1440  // Delete the fake timestepper
1441  delete fake_space_time_stepper_pt;
1442 
1443  // Set the initial unkowns to be the original problem
1444  Previous_dofs.resize(Ndof * N_tstorage + 1, 0.0);
1446  }
unsigned nvalue() const
Return number of values stored in data object (incl pinned ones).
Definition: nodes.h:483
void set_time_stepper(TimeStepper *const &time_stepper_pt, const bool &preserve_existing_data)
Definition: nodes.cc:406
Data *& internal_data_pt(const unsigned &i)
Return a pointer to i-th internal data object.
Definition: elements.h:622
unsigned ninternal_data() const
Return the number of internal data objects.
Definition: elements.h:823
void build(const OomphCommunicator *const comm_pt, const unsigned &first_row, const unsigned &nrow_local, const unsigned &nrow=0)
Definition: linear_algebra_distribution.cc:35
static Steady< 0 > Default_TimeStepper
The Steady Timestepper.
Definition: mesh.h:75
GeneralisedElement *& element_pt(const unsigned long &e)
Return pointer to element e.
Definition: mesh.h:448
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
Time *& time_pt()
Return a pointer to the global time object.
Definition: problem.h:1504
OomphCommunicator * communicator_pt()
access function to the oomph-lib communicator
Definition: problem.h:1246
unsigned nglobal_data() const
Return the number of global data values.
Definition: problem.h:1686
Vector< double * > Dof_pt
Vector of pointers to dofs.
Definition: problem.h:554
Mesh *& mesh_pt()
Return a pointer to the global mesh.
Definition: problem.h:1280
unsigned nsub_mesh() const
Return number of submeshes.
Definition: problem.h:1323
unsigned long assign_eqn_numbers(const bool &assign_local_eqn_numbers=true)
Definition: problem.cc:1989
LinearAlgebraDistribution * Dof_distribution_pt
Definition: problem.h:460
Data *& global_data_pt(const unsigned &i)
Return a pointer to the the i-th global data object.
Definition: problem.h:1647

References oomph::Problem::assign_eqn_numbers(), oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::Basic_time_mesh_pt, oomph::LinearAlgebraDistribution::build(), oomph::Problem::communicator_pt(), oomph::Mesh::Default_TimeStepper, oomph::Problem::Dof_distribution_pt, oomph::Problem::Dof_pt, e(), oomph::Mesh::element_pt(), oomph::Problem::global_data_pt(), i, oomph::GeneralisedElement::internal_data_pt(), j, oomph::Problem::mesh_pt(), n, oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::N_element_in_period, oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::N_tstorage, oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::Ndof, oomph::Mesh::nelement(), oomph::Problem::nglobal_data(), oomph::GeneralisedElement::ninternal_data(), oomph::Mesh::nnode(), oomph::Mesh::node_pt(), oomph::Problem::nsub_mesh(), oomph::Data::nvalue(), oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::Omega, oomph::PeriodicOrbitEquations::omega_pt(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, oomph::oomph_info, oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::Previous_dofs, oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::Problem_pt, oomph::PeriodicOrbitEquations::set_ntstorage(), oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::set_previous_dofs_to_current_dofs(), oomph::Data::set_time_stepper(), oomph::Data::set_value(), plotPSD::t, oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::Time_mesh_pt, oomph::PeriodicOrbitEquations::time_pt(), oomph::Problem::time_pt(), oomph::GeomObject::time_stepper_pt(), oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::Time_stepper_pt, oomph::Data::value(), oomph::Node::value(), and oomph::SolidNode::variable_position_pt().

◆ discrete_times()

template<unsigned NNODE_1D>
void oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::discrete_times ( Vector< double > &  t)
inline

Tell me the times at which you want the solution.

1035  {
1036  const unsigned n_node = Time_mesh_pt->nnode();
1037  t.resize(n_node);
1038  for (unsigned n = 0; n < n_node; n++)
1039  {
1040  t[n] = Time_mesh_pt->node_pt(n)->x(0);
1041  }
1042  }

References n, plotPSD::t, and oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::Time_mesh_pt.

◆ eqn_number()

template<unsigned NNODE_1D>
unsigned long oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::eqn_number ( GeneralisedElement *const &  elem_pt,
const unsigned ieqn_local 
)
inlinevirtual

Return the global equation number of the local unknown ieqn_local in elem_pt.

Reimplemented from oomph::AssemblyHandler.

920  {
921  // Get unaugmented number of (spatial) dofs in element
922  unsigned raw_ndof = elem_pt->ndof();
923  // The final variable (the period) is stored at the end
924  if (ieqn_local == raw_ndof * N_tstorage)
925  {
926  return N_tstorage * Ndof;
927  }
928  // Otherwise we need to do a little more work
929  else
930  {
931  // Now find out the time level
932  unsigned t = ieqn_local / raw_ndof;
933  // and the remainder (original eqn number)
934  unsigned raw_ieqn = ieqn_local % raw_ndof;
935  // hence calculate the global value
936  return t * Ndof + elem_pt->eqn_number(raw_ieqn);
937  }
938  }

References oomph::GeneralisedElement::eqn_number(), oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::N_tstorage, oomph::GeneralisedElement::ndof(), oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::Ndof, and plotPSD::t.

Referenced by oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::get_dofs_for_element(), oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::get_previous_dofs_for_element(), and oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::set_dofs_for_element().

◆ get_dofs_for_element()

template<unsigned NNODE_1D>
void oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::get_dofs_for_element ( GeneralisedElement *const  elem_pt,
Vector< double > &  dofs 
)
inlinevirtual

Implements oomph::PeriodicOrbitAssemblyHandlerBase.

951  {
952  // Find the number of dofs in the element
953  const unsigned n_elem_dof = this->ndof(elem_pt);
954  dofs.resize(n_elem_dof);
955  // Now just get the dofs corresponding to the element's unknowns from the
956  // problem dof
957  for (unsigned i = 0; i < n_elem_dof; i++)
958  {
959  dofs[i] = Problem_pt->dof(this->eqn_number(elem_pt, i));
960  }
961  }
unsigned ndof(GeneralisedElement *const &elem_pt)
Return the number of degrees of freedom in the element elem_pt.
Definition: periodic_orbit_handler.h:911
unsigned long eqn_number(GeneralisedElement *const &elem_pt, const unsigned &ieqn_local)
Definition: periodic_orbit_handler.h:918
double & dof(const unsigned &i)
i-th dof in the problem
Definition: problem.h:1813

References oomph::Problem::dof(), oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::eqn_number(), i, oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::ndof(), and oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::Problem_pt.

◆ get_jacobian()

template<unsigned NNODE_1D>
void oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::get_jacobian ( GeneralisedElement *const &  elem_pt,
Vector< double > &  residuals,
DenseMatrix< double > &  jacobian 
)
inlinevirtual

Calculate the elemental Jacobian matrix "d equation / d variable" for elem_pt.

Reimplemented from oomph::AssemblyHandler.

997  {
998  Time_mesh_pt->assemble_residuals_and_jacobian(
999  this, elem_pt, residuals, jacobian);
1000  }

References oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::Time_mesh_pt.

◆ get_previous_dofs_for_element()

template<unsigned NNODE_1D>
void oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::get_previous_dofs_for_element ( GeneralisedElement *const  elem_pt,
Vector< double > &  dofs 
)
inlinevirtual

Implements oomph::PeriodicOrbitAssemblyHandlerBase.

965  {
966  // Find the number of dofs in the element
967  const unsigned n_elem_dof = this->ndof(elem_pt);
968  dofs.resize(n_elem_dof);
969  // Now just get the dofs corresponding to the element's unknowns from the
970  // problem dof
971  for (unsigned i = 0; i < n_elem_dof; i++)
972  {
973  dofs[i] = Previous_dofs[this->eqn_number(elem_pt, i)];
974  }
975  }

References oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::eqn_number(), i, oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::ndof(), and oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::Previous_dofs.

◆ get_residuals()

template<unsigned NNODE_1D>
void oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::get_residuals ( GeneralisedElement *const &  elem_pt,
Vector< double > &  residuals 
)
inlinevirtual

Return the contribution to the residuals of the element elem_pt.

Reimplemented from oomph::AssemblyHandler.

943  {
944  Time_mesh_pt->assemble_residuals(this, elem_pt, residuals);
945  }

References oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::Time_mesh_pt.

◆ ndof()

◆ orbit_output()

template<unsigned NNODE_1D>
void oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::orbit_output ( std::ostream &  outfile,
const unsigned n_plot 
)
inline

Return the contribution to the residuals of the element elem_pt.

Calculate all desired vectors and matrices provided by the element elem_pt. Return an unsigned integer to indicate whether the handler is a bifurcation tracking handler. The default is zero (not) Return a pointer to the bifurcation parameter in bifurcation tracking problems Return the eigenfunction(s) associated with the bifurcation that has been detected in bifurcation tracking problems

1023  {
1024  const unsigned n_element = Problem_pt->mesh_pt()->nelement();
1025  for (unsigned e = 0; e < n_element; e++)
1026  {
1027  Time_mesh_pt->orbit_output(
1028  Problem_pt->mesh_pt()->element_pt(e), outfile, n_plot);
1029  }
1030  }

References e(), oomph::Mesh::element_pt(), oomph::Problem::mesh_pt(), oomph::Mesh::nelement(), oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::Problem_pt, and oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::Time_mesh_pt.

◆ set_dofs_for_element()

template<unsigned NNODE_1D>
void oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::set_dofs_for_element ( GeneralisedElement *const  elem_pt,
Vector< double > const &  dofs 
)
inlinevirtual

Implements oomph::PeriodicOrbitAssemblyHandlerBase.

980  {
981  // Find the number of dofs in the element
982  const unsigned n_elem_dof = this->ndof(elem_pt);
983  // Now just get the dofs corresponding to the element's unknowns from the
984  // problem dof
985  for (unsigned i = 0; i < n_elem_dof; i++)
986  {
987  Problem_pt->dof(this->eqn_number(elem_pt, i)) = dofs[i];
988  }
989  }

References oomph::Problem::dof(), oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::eqn_number(), i, oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::ndof(), and oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::Problem_pt.

◆ set_previous_dofs_to_current_dofs()

template<unsigned NNODE_1D>
void oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::set_previous_dofs_to_current_dofs ( )
inline

Member Data Documentation

◆ Basic_time_mesh_pt

template<unsigned NNODE_1D>
Mesh* oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::Basic_time_mesh_pt
private

Storage for the mesh of temporal elements with a simple mesh pointer.

Referenced by oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::adapt_temporal_mesh().

◆ N_element_in_period

template<unsigned NNODE_1D>
unsigned oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::N_element_in_period
private

Storage for number of elements in the period.

Referenced by oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::adapt_temporal_mesh().

◆ N_tstorage

◆ Ndof

template<unsigned NNODE_1D>
unsigned oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::Ndof
private

◆ Omega

template<unsigned NNODE_1D>
double oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::Omega
private

Storage for the frequency of the orbit (scaled by 2pi)

Referenced by oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::adapt_temporal_mesh().

◆ Previous_dofs

◆ Problem_pt

◆ Time_mesh_pt

◆ Time_stepper_pt

template<unsigned NNODE_1D>
PeriodicOrbitTimeDiscretisation* oomph::PeriodicOrbitAssemblyHandler< NNODE_1D >::Time_stepper_pt
private

The documentation for this class was generated from the following file: