mesh_as_geometric_object.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// Version 1.0; svn revision $LastChangedRevision$
7 // LIC//
8 // LIC// $LastChangedDate$
9 // LIC//
10 // LIC// Copyright (C) 2006-2016 Matthias Heil and Andrew Hazel
11 // LIC//
12 // LIC// This library is free software; you can redistribute it and/or
13 // LIC// modify it under the terms of the GNU Lesser General Public
14 // LIC// License as published by the Free Software Foundation; either
15 // LIC// version 2.1 of the License, or (at your option) any later version.
16 // LIC//
17 // LIC// This library is distributed in the hope that it will be useful,
18 // LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 // LIC// Lesser General Public License for more details.
21 // LIC//
22 // LIC// You should have received a copy of the GNU Lesser General Public
23 // LIC// License along with this library; if not, write to the Free Software
24 // LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 // LIC// 02110-1301 USA.
26 // LIC//
27 // LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
28 // LIC//
29 // LIC//====================================================================
30 // Header file for a class that is used to represent a mesh
31 // as a geometric object
32 
33 // Include guards to prevent multiple inclusion of the header
34 #ifndef OOMPH_MESH_AS_GEOMETRIC_OBJECT_HEADER
35 #define OOMPH_MESH_AS_GEOMETRIC_OBJECT_HEADER
36 
37 // Config header generated by autoconfig
38 #ifdef HAVE_CONFIG_H
39 #include <oomph-lib-config.h>
40 #endif
41 
42 #include <float.h>
43 #include <limits.h>
44 
45 // Include the geometric object header file
46 #include "geom_objects.h"
47 
48 // Sample point container
49 #include "sample_point_container.h"
50 
51 
53 
54 namespace oomph
55 {
56 
57 ////////////////////////////////////////////////////////////////////////
58 ////////////////////////////////////////////////////////////////////////
59 ////////////////////////////////////////////////////////////////////////
60 
61 //========================================================================
62 /// Helper namespace for MeshAsGeomObject -- its only function creates
63 /// SamplePointContainerParameters of the right type for the default sample point
64 /// container
65 //========================================================================
66 namespace MeshAsGeomObject_Helper
67 {
68 
69  /// Default sample point container type
71 
72  /// \short "Factory" for SamplePointContainerParameters of the right type as selected
73  /// by Default_sample_point_container_version
74  extern void create_sample_point_container_parameters(Mesh* mesh_pt,
75  SamplePointContainerParameters*&
76  sample_point_container_parameters_pt);
77 
78 }
79 
80 
81 
82 ////////////////////////////////////////////////////////////////////////
83 ////////////////////////////////////////////////////////////////////////
84 ////////////////////////////////////////////////////////////////////////
85 
86 
87 //========================================================================
88 /// This class provides a GeomObject representation of a given
89 /// finite element mesh. The Lagrangian coordinate is taken to be the
90 /// dimension of the (first) element in the mesh and the Eulerian
91 /// coordinate is taken to be the dimension of the (first) node in
92 /// the mesh. If there are no elements or nodes the appropriate dimensions
93 /// will be set to zero.
94 /// The constituent elements of the mesh must have their own
95 /// GeomObject representations, so they must be FiniteElements,
96 /// and they become sub-objects
97 /// in this compound GeomObject.
98 //========================================================================
100 {
101 
102  private:
103 
104 
105  /// Helper function to actually build the thing
107  sample_point_container_parameters_pt)
108  {
109  Mesh_pt=sample_point_container_parameters_pt->mesh_pt();
110  if (dynamic_cast<RefineableBinArrayParameters*>(
111  sample_point_container_parameters_pt)!=0)
112  {
113  Sample_point_container_version=UseRefineableBinArray;
114  }
115  else if (dynamic_cast<NonRefineableBinArrayParameters*>(
116  sample_point_container_parameters_pt)!=0)
117  {
118  Sample_point_container_version=UseNonRefineableBinArray;
119  }
120 #ifdef OOMPH_HAS_CGAL
121  else if (dynamic_cast<CGALSamplePointContainerParameters*>(
122  sample_point_container_parameters_pt)!=0)
123  {
124  Sample_point_container_version=UseCGALSamplePointContainer;
125  }
126 #endif
127  else
128  {
129  throw OomphLibError("Wrong sample_point_container_parameters_pt",
130  OOMPH_CURRENT_FUNCTION,
131  OOMPH_EXCEPTION_LOCATION);
132  }
133 
134 #ifdef OOMPH_HAS_MPI
135 
136  // Set communicator
137  Communicator_pt=Mesh_pt->communicator_pt();
138 
139 #endif
140 
141 
142  //Storage for the Lagrangian and Eulerian dimension
143  int dim[2]={0,0};
144 
145  //Set the Lagrangian dimension from the dimension of the first element
146  //if it exists (if not the Lagrangian dimension will be zero)
147  if(Mesh_pt->nelement()!=0)
148  {
149  dim[0] = Mesh_pt->finite_element_pt(0)->dim();
150  }
151 
152  //Read out the Eulerian dimension from the first node, if it exists.
153  //(if not the Eulerian dimension will be zero);
154  if(Mesh_pt->nnode()!=0)
155  {
156  dim[1] = Mesh_pt->node_pt(0)->ndim();
157  }
158 
159  // Need to do an Allreduce to ensure that the dimension is consistent
160  // even when no elements are assigned to a certain processor
161 #ifdef OOMPH_HAS_MPI
162 
163 //Only a problem if the mesh has been distributed
164  if(Mesh_pt->is_mesh_distributed())
165  {
166  //Need a non-null communicator
167  if(Communicator_pt!=0)
168  {
169  int n_proc=Communicator_pt->nproc();
170  if (n_proc > 1)
171  {
172  int dim_reduce[2];
173  MPI_Allreduce(&dim,&dim_reduce,2,MPI_INT,
174  MPI_MAX,Communicator_pt->mpi_comm());
175 
176  dim[0] = dim_reduce[0];
177  dim[1] = dim_reduce[1];
178  }
179  }
180  }
181 #endif
182 
183  //Set the Lagrangian and Eulerian dimensions within this geometric object
184  this->set_nlagrangian_and_ndim(static_cast<unsigned>(dim[0]),
185  static_cast<unsigned>(dim[1]));
186 
187  // Create temporary storage for geometric Data (don't count
188  // Data twice!
189  std::set<Data*> tmp_geom_data;
190 
191  //Copy all the elements in the mesh into local storage
192  //N.B. elements must be able to have a geometric object representation.
193  unsigned n_sub_object = Mesh_pt->nelement();
194  Sub_geom_object_pt.resize(n_sub_object);
195  for(unsigned e=0;e<n_sub_object;e++)
196  {
197  // (Try to) cast to a finite element:
198  Sub_geom_object_pt[e]=
199  dynamic_cast<FiniteElement*>(Mesh_pt->element_pt(e));
200 
201 #ifdef PARANOID
202  if (Sub_geom_object_pt[e]==0)
203  {
204  std::ostringstream error_message;
205  error_message
206  << "Unable to dynamic cast element: " << std::endl
207  << "into a FiniteElement: GeomObject representation is not possible\n";
208  throw OomphLibError(
209  error_message.str(),
210  OOMPH_CURRENT_FUNCTION,
211  OOMPH_EXCEPTION_LOCATION);
212  }
213 #endif
214 
215  // Add the geometric Data of each element into set
216  unsigned ngeom_data=Sub_geom_object_pt[e]->ngeom_data();
217  for (unsigned i=0;i<ngeom_data;i++)
218  {
219  tmp_geom_data.insert(Sub_geom_object_pt[e]->geom_data_pt(i));
220  }
221  }
222 
223  // Now copy unique geom Data values across into vector
224  unsigned ngeom=tmp_geom_data.size();
225  Geom_data_pt.resize(ngeom);
226  typedef std::set<Data*>::iterator IT;
227  unsigned count=0;
228  for (IT it=tmp_geom_data.begin();it!=tmp_geom_data.end();it++)
229  {
230  Geom_data_pt[count]=*it;
231  count++;
232  }
233 
234  // Build the right type of bin array
235  switch (Sample_point_container_version)
236  {
238 
239  Sample_point_container_pt=new RefineableBinArray(sample_point_container_parameters_pt);
240  break;
241 
243 
244  Sample_point_container_pt=new NonRefineableBinArray(sample_point_container_parameters_pt);
245  break;
246 
247 #ifdef OOMPH_HAS_CGAL
248 
250 
251  Sample_point_container_pt=new CGALSamplePointContainer(sample_point_container_parameters_pt);
252  break;
253 
254 #endif
255 
256  default:
257 
258  oomph_info << "Sample_point_container_version = "
259  << Sample_point_container_version << std::endl;
260  throw OomphLibError("Sample_point_container_version",
261  OOMPH_CURRENT_FUNCTION,
262  OOMPH_EXCEPTION_LOCATION);
263  }
264  }
265 
266 
267  /// \short Vector of pointers to Data items that affects the object's shape
269 
270  /// Internal storage for the elements that constitute the object
272 
273  /// \short Pointer to the sample point container
275 
276 #ifdef OOMPH_HAS_MPI
277 
278  /// Communicator
280 
281 #endif
282 
283  /// Pointer to mesh
285 
286  /// \short Which version of the sample point container
287  /// are we using?
289 
290  public:
291 
292  /// \short Pointer to the sample point container
294  {
295  return Sample_point_container_pt;
296  }
297 
298  /// Return pointer to e-th finite element
300  {
301  return Sub_geom_object_pt[e];
302  }
303 
304 
305  /// \short Which sample point container is used in locate zeta? (uses enum
306  /// Sample_Point_Container_Type)
308  {
309  return Sample_point_container_version;
310  }
311 
312  /// Number of elements in the underlying mesh
313  unsigned nelement()
314  {
315  return Sub_geom_object_pt.size();
316  }
317 
318  ///\short Constructor
319  MeshAsGeomObject(Mesh* const& mesh_pt)
320  : GeomObject()
321  {
322  // Create default parameters
323  SamplePointContainerParameters* sample_point_container_parameters_pt=0;
325  mesh_pt,sample_point_container_parameters_pt);
326 
327  // Build the bastard
328  build_it(sample_point_container_parameters_pt);
329  delete sample_point_container_parameters_pt;
330  }
331 
332 
333  ///\short Constructor
335  sample_point_container_parameters_pt)
336  : GeomObject()
337  {
338  build_it(sample_point_container_parameters_pt);
339  }
340 
341  /// Empty Constructor
343 
344  /// Destructor
346  {
347  delete Sample_point_container_pt;
348  }
349 
350  /// Broken copy constructor
352  {
353  BrokenCopy::broken_copy("MeshAsGeomObject");
354  }
355 
356  /// Broken assignment operator
358  {
359  BrokenCopy::broken_assign("MeshAsGeomObject");
360  }
361 
362  /// How many items of Data does the shape of the object depend on?
363  unsigned ngeom_data() const { return Geom_data_pt.size(); }
364 
365  /// \short Return pointer to the j-th Data item that the object's
366  /// shape depends on
367  Data* geom_data_pt(const unsigned& j) { return Geom_data_pt[j]; }
368 
369  /// \short Find the sub geometric object and local coordinate therein that
370  /// corresponds to the intrinsic coordinate zeta. If sub_geom_object_pt=0
371  /// on return from this function, none of the constituent sub-objects
372  /// contain the required coordinate. Following from the general
373  /// interface to this function in GeomObjects,
374  /// setting the optional bool argument to true means that each
375  /// time the sub-object's locate_zeta function is called, the coordinate
376  /// argument "s" is used as the initial guess. However, this doesn't
377  /// make sense here and the argument is ignored (though a warning
378  /// is issued when the code is compiled in PARANOID setting)
379  void locate_zeta(const Vector<double>& zeta,
380  GeomObject*& sub_geom_object_pt,
381  Vector<double>& s,
382  const bool& use_coordinate_as_initial_guess = false)
383  {
384 #ifdef PARANOID
385  if (use_coordinate_as_initial_guess)
386  {
388  "Ignoring the use_coordinate_as_initial_guess argument.",
389  "MeshAsGeomObject::locate_zeta()",
390  OOMPH_EXCEPTION_LOCATION);
391  }
392 #endif
393 
394 
395  // Do locate in sample point container
396  Sample_point_container_pt->locate_zeta(zeta,sub_geom_object_pt,s);
397 
398  }
399 
400  /// \short Return the position as a function of the intrinsic coordinate zeta.
401  /// This provides an (expensive!) default implementation in which
402  /// we loop over all the constituent sub-objects and check if they
403  /// contain zeta and then evaluate their position() function.
404  void position(const Vector<double>& zeta, Vector<double>& r) const
405  {
406  // Call position function at current timestep:
407  unsigned t = 0;
408  position(t, zeta, r);
409  }
410 
411  /// \short Parametrised position on object: r(zeta). Evaluated at
412  /// previous timestep. t=0: current time; t>0: previous
413  /// timestep. This provides an (expensive!) default implementation in which
414  /// we loop over all the constituent sub-objects and check if they
415  /// contain zeta and then evaluate their position() function.
416  void position(const unsigned& t, const Vector<double>& zeta,
417  Vector<double>& r) const
418  {
419  // Storage for the GeomObject that contains the zeta coordinate
420  // and the intrinsic coordinate within it.
421  GeomObject* sub_geom_object_pt;
422  const unsigned n_lagrangian = this->nlagrangian();
423  Vector<double> s(n_lagrangian);
424 
425  // Find the sub object containing zeta, and the local intrinsic coordinate
426  // within it
427  const_cast<MeshAsGeomObject*>(this)->locate_zeta(zeta, sub_geom_object_pt, s);
428  if (sub_geom_object_pt == 0)
429  {
430  std::ostringstream error_message;
431  error_message << "Cannot locate zeta ";
432  for (unsigned i = 0; i < n_lagrangian; i++)
433  {
434  error_message << zeta[i] << " ";
435  }
436  error_message << std::endl;
437  Mesh_pt->output("most_recent_mesh.dat");
438  throw OomphLibError(error_message.str(),
439  OOMPH_CURRENT_FUNCTION,
440  OOMPH_EXCEPTION_LOCATION);
441  }
442  // Call that sub-object's position function
443  sub_geom_object_pt->position(t, s, r);
444 
445  }// end of position
446 
447  /// Return the derivative of the position
448  void dposition(const Vector<double>& xi, DenseMatrix<double>& drdxi) const
449  {
450  throw OomphLibError("dposition() not implemented",
451  OOMPH_CURRENT_FUNCTION,
452  OOMPH_EXCEPTION_LOCATION);
453  }
454 
455 };
456 
457 }
458 
459 #endif
void broken_copy(const std::string &class_name)
Issue error message and terminate execution.
MeshAsGeomObject(Mesh *const &mesh_pt)
Constructor.
Mesh * Mesh_pt
Pointer to mesh.
SamplePointContainer * sample_point_container_pt() const
Pointer to the sample point container.
Helper object for dealing with the parameters used for the SamplePointContainer objects.
cstr elem_len * i
Definition: cfortran.h:607
void create_sample_point_container_parameters(Mesh *mesh_pt, SamplePointContainerParameters *&sample_point_container_parameters_pt)
"Factory" for SamplePointContainerParameters of the right type as selected by Default_sample_point_co...
void operator=(const MeshAsGeomObject &)
Broken assignment operator.
FiniteElement * finite_element_pt(const unsigned &e)
Return pointer to e-th finite element.
A general Finite Element class.
Definition: elements.h:1274
RefineableBinArray class.
virtual void locate_zeta(const Vector< double > &zeta, GeomObject *&sub_geom_object_pt, Vector< double > &s)=0
Find sub-GeomObject (finite element) and the local coordinate s within it that contains point with gl...
char t
Definition: cfortran.h:572
SamplePointContainer * Sample_point_container_pt
Pointer to the sample point container.
CGAL-based SamplePointContainer.
void locate_zeta(const Vector< double > &zeta, GeomObject *&sub_geom_object_pt, Vector< double > &s, const bool &use_coordinate_as_initial_guess=false)
Find the sub geometric object and local coordinate therein that corresponds to the intrinsic coordina...
virtual void position(const Vector< double > &zeta, Vector< double > &r) const =0
Parametrised position on object at current time: r(zeta).
OomphInfo oomph_info
e
Definition: cfortran.h:575
MeshAsGeomObject(const MeshAsGeomObject &)
Broken copy constructor.
void output(std::ostream &outfile)
Output for all elements.
Definition: mesh.cc:1761
MeshAsGeomObject()
Empty Constructor.
unsigned ngeom_data() const
How many items of Data does the shape of the object depend on?
OomphCommunicator * Communicator_pt
Communicator.
void position(const Vector< double > &zeta, Vector< double > &r) const
Return the position as a function of the intrinsic coordinate zeta. This provides an (expensive!) def...
unsigned Default_sample_point_container_version
Default sample point container type. Must currently be one of UseCGALSamplePointContainer, UseRefineableBinArray or UseNonRefineableBinArray.
static char t char * s
Definition: cfortran.h:572
Data * geom_data_pt(const unsigned &j)
Return pointer to the j-th Data item that the object&#39;s shape depends on.
A class that represents a collection of data; each Data object may contain many different individual ...
Definition: nodes.h:89
Vector< Data * > Geom_data_pt
Vector of pointers to Data items that affects the object&#39;s shape.
void build_it(SamplePointContainerParameters *sample_point_container_parameters_pt)
Helper function to actually build the thing.
void broken_assign(const std::string &class_name)
Issue error message and terminate execution.
Vector< FiniteElement * > Sub_geom_object_pt
Internal storage for the elements that constitute the object.
NonRefineableBinArray class.
void dposition(const Vector< double > &xi, DenseMatrix< double > &drdxi) const
Return the derivative of the position.
MeshAsGeomObject(SamplePointContainerParameters *sample_point_container_parameters_pt)
Constructor.
unsigned Sample_point_container_version
Which version of the sample point container are we using?
void position(const unsigned &t, const Vector< double > &zeta, Vector< double > &r) const
Parametrised position on object: r(zeta). Evaluated at previous timestep. t=0: current time; t>0: pre...
Base class for all sample point containers.
A general mesh class.
Definition: mesh.h:74
unsigned sample_point_container_version() const
Which sample point container is used in locate zeta? (uses enum Sample_Point_Container_Type) ...
unsigned nelement()
Number of elements in the underlying mesh.
Mesh * mesh_pt() const
Pointer to mesh from whose FiniteElements sample points are created.
An oomph-lib wrapper to the MPI_Comm communicator object. Just contains an MPI_Comm object (which is ...
Definition: communicator.h:57