action functions
|
Please note that the library has not been "officially" released. While we continue to work on the documentation, these web pages are likely to contain broken links and documents in draft form. Please send an email to if you wish to be informed of the library's "official" release. |
This document provides an overview of the general coding conventions that are used throughout oomph-lib. Knowledge of these conventions will greatly facilitate the use of the library. Contributors to the library are expected to adhere to these standards.
*.h: Contains the class definitions and any inline functions.*.cc: Contains all non-inline member functions that can be compiled once and for all. This includes*.template.cc: Contains any non-inline member function of templated classes. This file must be included (together with the corresponding *.h file) when a specific instantiation of a templated class is required. For instance, most specific Mesh classes are templated by the element type and the mesh writer can obviously not predict which element types his/her specific mesh is going to be used with.FiniteElement* surface_element_pt;
class Shape
class AlgebraicElement
private: /// Pointer to boundary node Node* Boundary_node_pt;
public: /// Access to boundary node (const version) Node* boundary_node_pt() const {return Boundary_node_pt;} /// Access to boundary node Node*& boundary_node_pt() {return Boundary_node_pt;}
Note: Do not use public data -- ever! Make it private and and provide an access function -- even if it seems "perfectly obvious" at the time of writing the class that the internal storage for the data item is "never going to be changed".
/// Return pointer to e-th element FiniteElement* element_pt(const unsigned& e);
elements_pt(...)n' for the access function for the number of entries in the container, i.e. /// Total number of elements unsigned nelement();
_pt in the function that returns the number of objects in the container.template<unsigned DIM> class NavierStokesEquations { public: [...] };
for (unsigned i=0;i<10;i++) { [...] std::cout << "doing something" << std::endl; [...] }
// ============================================================= /// \short (add \short to make sure that multi-line descriptions /// appear in doxygen's short documentation. Include lists with items /// - first item /// - second item /// - first item of sublist /// - second item of sublist /// . //end of sublist /// . //end of main list // ============================================================= void SomeClass::some_function() { for (unsigned i=0;i<10;i++) { std::cout << "doing something" << std::endl; } }
oomph-lib is contained in its own namespace, oomph, to avoid clashes of class names with those of other (third-party) libraries. If there is no danger of name clashes, the entire oomph namespace may be imported at the beginning of each driver code by placing the statement using namespace oomph;
oomph-lib classes inside a driver code!) must be included into the oomph namespace by surrounding the code by namespace oomph { // Additions to the library go here... [...] }
std must not be included globally in any header files. The statement using namespace std;
#ifndef OOMPH_SOME_CLASS_HEADER // Assuming that the file is #define OOMPH_SOME_CLASS_HEADER // called some_class.h // Include generic oomph-lib library #include "generic.h" // Add to oomph-lib namespace namespace oomph { // ============================================================= /// Waffle about what the class does etc. /// // ============================================================= template<class T> class SomeClass : public SomeBaseClass { public: /// Constructor: Pass coefficients n1 and n2 SomeClass(const unsigned& n1, const T& n2) : N1(n1), N2(n2) {} /// Access function to coefficient inline unsigned n1() const { return N1; } /// Access function to other coefficient inline T& n2() const { return N2; } protected: /// Coefficient unsigned N1; private: /// Second coefficient T N2; }; } #endif
OOMPH_* in the include guard. This is to avoid clashes with include guards of other libraries.
-DPARANOID is specified as a compilation flag for the C++ compiler. If errors are detected, a meaningful diagnostic should be issued, by throwing an OomphLibError. If the code is compiled without the PARANOID flag, all sanity checks are bypassed -- good for the overall execution speed, bad for error handling... The user can choose. //Has a global mesh already been built? if(Mesh_pt!=0) { std::string error_message = "Problem::build_global_mesh() called,\n"; error_message += " but a global mesh has already been built:\n"; error_message += "Problem::Mesh_pt is not zero!\n"; throw OomphLibError(error_message, "Problem::build_global_mesh()", OOMPH_EXCEPTION_LOCATION); }
oomph-lib also has an object that allows warning messages to be issued in a uniform format. Here's an example of its use: // Was it a duplicate? unsigned nel_now=element_set_pt.size(); if (nel_now==nel_before) { std::ostringstream warning_stream; warning_stream <<"WARNING: " << std::endl <<"Element " << e << " in submesh " << imesh <<" is a duplicate \n and was ignored when assembling " <<"global mesh." << std::endl; OomphLibWarning(warning_stream.str(), "Problem::rebuild_global_mesh()", OOMPH_EXCEPTION_LOCATION); }
generic library is compiled with the RANGE_CHECKING flag, i.e. if -DRANGE_CHECKING is specified as a compilation flag for the C++ compiler. Note: While it is generally a good idea to compile with PARANOID while developing code, RANGE_CHECKING is very expensive and is therefore activated via a second independent flag. We only tend to active this flag as a last resort, typically to track down particularly stubborn segmentation faults. unsigned self_test()
// Return i-th coordinate of Point double& operator[](const unsigned& i){return x[i];} // Return i-th coordinate of Point -- const version const double& operator[](const unsigned& i) const {return x[i];}
// Create a counter int counter=0;
// Create a counter unsigned counter=0;
oomph-lib objects have (deliberately) broken copy constructors and assignment operators, making a "pass by value" impossible. The only exceptions are cases in which we could see a good reason why a fully-functional, non-memory-leaking copy/assignment operator might be required.oomph-lib's Vector class). The same applies to assignment operators. BrokenCopy provides two helper functions, BrokenCopy::broken_copy(...) and BrokenCopy::broken_assign(...) that issue a suitable error message and then throw an OomphLibError. The name of the class should be passed to these functions as a string, as in this example from the Mesh class: /// Broken copy constructor Mesh(const Mesh& dummy) { BrokenCopy::broken_copy("Mesh"); } /// Broken assignment operator void operator=(const Mesh&) { BrokenCopy::broken_assign("Mesh"); }
/// \short Return FE interpolated coordinate x[i] at local coordinate s /// at previous timestep t (t=0: present; t>0: previous timestep) virtual double interpolated_x(const unsigned& t, const Vector<double> &s, const unsigned &i) const;
OOMPH_EXCEPTION_LOCATION to make the file name and line number available to the OomphLibException object -- the object that is thrown if a run-time error is detected.
1.4.7