--- /dev/null
+/********************** parameter-handler.h ****************************/
+/* $Id$ */
+#ifndef __parameter_handler_H
+#define __parameter_handler_H
+/********************** parameter-handler.h ****************************/
+
+
+// public classes; to be declared below
+class ParameterHandler;
+template <class UserClass> class MultipleParameterLoop;
+
+
+#include <map.h>
+#include <vector.h>
+#include <basic/exceptions.h>
+
+#ifdef DEBUG
+# define _G_NO_NRV // don't use GNU's named return values in debug modes
+# include <String.h> // because if we did we'd harvest tons of warnings.
+# undef _G_NO_NRV
+#else
+# include <String.h>
+#endif
+
+
+
+class istream;
+class ostream;
+
+
+
+/**
+ List of possible output formats.
+ */
+enum OutputStyle {
+ Text, LaTeX, HTML
+};
+
+
+
+/**
+ Declare what a multiple entry is: a variant
+ entry ({...}) or an array ({{...}})
+ */
+enum MultipleEntryType {
+ variant, array
+};
+
+
+
+/**
+ The #ParameterHandler# class provides a standard interface to an input file
+ which provides at run-time for program parameters such as time step sizes,
+ geometries, right hand sides etc. The input for the program is given in files,
+ streams or strings in memory using text like
+ \begin{verbatim}
+ set Time step size = 0.3
+ set Geometry = [0,1]x[0,3]
+ \end{verbatim}
+ Input may be sorted into subsection trees in order to give the input a logical
+ structure.
+
+
+ {\bf Declaration of entries}
+
+ In order to use the facilities of a #ParameterHandler# object, one first has
+ to make known the different entries the input file may or may not contain. This
+ is done in the following way:
+ \begin{verbatim}
+ ...
+ ParameterHandler prm;
+ prm.declare_entry ("Time step size",
+ "0.2",
+ ParameterHandler::RegularExpressions::Double);
+ prm.declare_entry ("Geometry",
+ "[0,1]x[0,1]",
+ ".*");
+ ...
+ \end{verbatim}
+ Each entry is declared using the function #declare_entry#. The first parameter is
+ the name of the entry (in short: the entry). The second is the default answer to
+ be taken in case the entry is not specified in the input file. The third parameter
+ is a regular expression which the input (and the default answer) has to match.
+ Several such regular expressions are defined in #ParameterHandler::RegularExpressions#.
+
+ Entries may be located in subsections which form a kind of input tree. For example
+ input parameters for linear solver routines should be classified in a subsection
+ named #Linear solver# or any other suitable name. This is accomplished in the
+ following way:
+ \begin{verbatim}
+ ...
+ LinEq eq;
+ eq.declare_parameters (prm);
+ ...
+
+ void LinEq::declare_parameters (ParameterHandler &prm) {
+ prm.enter_subsection("Linear solver");
+ prm.declare_entry ("Solver",
+ "CG",
+ "CG\\|GMRES\\|GaussElim");
+ prm.declare_entry ("Maximum number of iterations",
+ "20",
+ ParameterHandler::RegularExpressions::Integer);
+ ...
+ prm.leave_subsection ();
+ };
+ \end{verbatim}
+
+ Subsections may be nested. For example a nonlinear solver may have a linear solver
+ as member object. Then the function call tree would be something like (if the class
+ #NonLinEq# has a member variables #eq# of type #LinEq#):
+ \begin{verbatim}
+ void NonLinEq::declare_parameters (ParameterHandler &prm) {
+ prm.enter_subsection ("Nonlinear solver");
+ prm.declare_entry ("Nonlinear method",
+ "Newton-Raphson",
+ ParameterHandler::RegularExpressions::AlphaNum);
+ eq.declare_parameters (prm);
+ prm.leave_subsection ();
+ };
+ \end{verbatim}
+
+ For class member functions which declare the different entries we propose to use the
+ common name #declare_parameters#. In normal cases this method can be #static# since the
+ entries will not depend on any previous knowledge. Classes for which entries should
+ logically be grouped into subsections should declare these subsections themselves. If
+ a class has two or more member variables of the same type both of which should have
+ their own parameters, this parent class' method #declare_parameters# is responsible to
+ group them into different subsections:
+ \begin{verbatim}
+ void NonLinEq::declare_parameters (ParameterHandler &prm) {
+ prm.enter_subsection ("Nonlinear solver");
+ prm.enter_subsection ("Linear solver 1");
+ eq1.declare_parameters (prm);
+ prm.leave_subsection ();
+
+ prm.enter_subsection ("Linear solver 2");
+ eq2.declare_parameters (prm);
+ prm.leave_subsection ();
+ prm.leave_subsection ();
+ };
+ \end{verbatim}
+
+
+ {\bf Input files and special characters}
+
+ For the first example above the input file would look like the following:
+ \begin{verbatim}
+ ...
+ subsection Nonlinear solver
+ set Nonlinear method = Gradient
+ subsection Linear solver
+ set Solver = CG
+ set Maxmimum number of iterations = 30
+ end
+ end
+ ... # other stuff
+ \end{verbatim}
+ The words #subsection#, #set# and #end# may be either written in lowercase or uppercase
+ letters. Leading and trailing whitespace is removed, multiple whitespace is condensed into
+ only one. Since the latter applies also to the name of an entry, an entry name will not
+ be recognised if in the declaration multiple whitespace is used.
+
+ In entry names and values the following characters are not allowed: \#, #{#, #}#, #|#.
+ Their use is reserved for the \ref{MultipleParameterLoop} class.
+
+ Comments starting with \# are skipped.
+
+ We propose to use the following
+ scheme to name entries: start the first word with a capital letter and use lowercase
+ letters further on. The same applies to the possible entry values to the right of the
+ #=# sign.
+
+
+ {\bf Reading data from input sources}
+
+ In order to read input you can use three possibilities: reading from an #istream# object,
+ reading from a file of which the name is given and reading from a string in memory in
+ which the lines are separated by #\n# characters. These possibilites are used as follows:
+ \begin{verbatim}
+ ParameterHandler prm;
+ ...
+ // declaration of entries
+ ...
+ prm.read_input (cin); // read input from standard in,
+ // or
+ prm.read_input ("simulation.in");
+ // or
+ char *in = "set Time step size = 0.3 \n ...";
+ prm.read_input (in);
+ ...
+ \end{verbatim}
+ You can use several sources of input successively. Entries which are changed more than
+ once will be overwritten everytime they are used. It is suggested to let the name of
+ parameter input end in #.prm#.
+
+ You should not try to declare entries using #declare_entry# and #enter_subsection# with as
+ yet unknown subsection names after using #read_input#. The results in this case are
+ unspecified.
+
+ If an error occurs upon reading the input, error messages are written to #cerr#.
+
+
+ {\bf Getting entry values out of a #ParameterHandler# object}
+
+ Each class gets its data out of a #ParameterHandler# object by calling the #get (...)#
+ member functions like this:
+ \begin{verbatim}
+ void NonLinEq::get_parameters (ParameterHandler &prm) {
+ prm.enter_subsection ("Nonlinear solver");
+ String method = prm.get ("Nonlinear method");
+ eq.get_parameters (prm);
+ prm.leave_subsection ();
+ };
+ \end{verbatim}
+ #get()# returns the value of the given entry. If the entry was not specified in the input
+ source(s), the default value is returned. You have to enter and leave subsections
+ exactly as you did when declaring subsection. You may chose the order in which to
+ transverse the subsection tree.
+
+ It is guaranteed that only entries matching the given regular expression are returned,
+ i.e. an input entry value which does not match the regular expression is not stored.
+
+ You can use #get# to retreive the parameter in text form, #get_integer# to get an integer
+ or #get_double# to get a double. It will cause an internal error if
+ the string could not be converted to an integer or a double. This should, though, not
+ happen if you correctly specified the regular expression for this entry; you should not
+ try to get out an integer or a double from an entry for which no according regular
+ expression was set. The internal error is raised through the #Assert()# macro family
+ which only works in debug mode.
+
+
+ {\bf Style guide for data retrieval}
+
+ We propose that every class which gets data out of a #ParameterHandler# object provides
+ a function named #get_parameters#. This should be declared #virtual#. #get_parameters#
+ functions in derived classes should call the #BaseClass::get_parameters# function.
+
+
+ {\bf Possible future extensions}
+
+ \begin{itemize}
+ \item Allow long input lines to be broken by appending a backslash character
+ (just like C macros and shell input).
+ \item Provide an #input filename# command for the input file to enable users to put the
+ most common parameters into separate files.
+ \end{itemize}
+
+
+
+ {\bf Worked Example}
+
+ This is the code:
+ \begin{verbatim}
+ #include <iostream.h>
+ #include "../include/parameter_handler.h"
+
+
+ class LinEq {
+ public:
+ static void declare_parameters (ParameterHandler &prm);
+ void get_parameters (ParameterHandler &prm);
+ private:
+ String Method;
+ int MaxIterations;
+ };
+
+
+ class Problem {
+ private:
+ LinEq eq1, eq2;
+ String Matrix1, Matrix2;
+ String outfile;
+ public:
+ static void declare_parameters (ParameterHandler &prm);
+ void get_parameters (ParameterHandler &prm);
+ };
+
+
+
+ void LinEq::declare_parameters (ParameterHandler &prm) {
+ // declare parameters for the linear
+ // solver in a subsection
+ prm.enter_subsection ("Linear solver");
+ prm.declare_entry ("Solver",
+ "CG",
+ "\\(CG\\|BiCGStab\\|GMRES\\)");
+ prm.declare_entry ("Maximum number of iterations",
+ "20",
+ ParameterHandler::RegularExpressions::Integer);
+ prm.leave_subsection ();
+ };
+
+
+ void LinEq::get_parameters (ParameterHandler &prm) {
+ prm.enter_subsection ("Linear solver");
+ Method = prm.get ("Solver");
+ MaxIterations = prm.get_integer ("Maximum number of iterations");
+ prm.leave_subsection ();
+ cout << " LinEq: Method=" << Method << ", MaxIterations=" << MaxIterations << endl;
+ };
+
+
+
+ void Problem::declare_parameters (ParameterHandler &prm) {
+ // first some global parameter entries
+ prm.declare_entry ("Output file",
+ "out",
+ ".*");
+
+ prm.declare_entry ("Equation 1",
+ "Laplace",
+ ".*");
+ prm.declare_entry ("Equation 2",
+ "Elasticity",
+ ".*");
+
+ // declare parameters for the
+ // first equation
+ prm.enter_subsection ("Equation 1");
+ prm.declare_entry ("Matrix type",
+ "Sparse",
+ "\\(Full\\|Sparse\\|Diagonal\\)");
+ LinEq::declare_parameters (prm); // for eq1
+ prm.leave_subsection ();
+
+ // declare parameters for the
+ // second equation
+ prm.enter_subsection ("Equation 2");
+ prm.declare_entry ("Matrix type",
+ "Sparse",
+ "\\(Full\\|Sparse\\|Diagonal\\)");
+ LinEq::declare_parameters (prm); // for eq2
+ prm.leave_subsection ();
+ };
+
+
+ void Problem::get_parameters (ParameterHandler &prm) {
+ // entries of the problem class
+ outfile = prm.get ("Output file");
+
+ String equation1 = prm.get ("Equation 1"),
+ equation2 = prm.get ("Equation 2");
+
+ // get parameters for the
+ // first equation
+ prm.enter_subsection ("Equation 1");
+ Matrix1 = prm.get ("Matrix type");
+ eq1.get_parameters (prm); // for eq1
+ prm.leave_subsection ();
+
+ // get parameters for the
+ // second equation
+ prm.enter_subsection ("Equation 2");
+ Matrix2 = prm.get ("Matrix type");
+ eq2.get_parameters (prm); // for eq2
+ prm.leave_subsection ();
+
+ cout << " Problem: outfile=" << outfile << endl
+ << " eq1=" << equation1 << ", eq2=" << equation2 << endl
+ << " Matrix1=" << Matrix1 << ", Matrix2=" << Matrix2 << endl;
+ };
+
+
+
+
+ void main () {
+ ParameterHandler prm;
+ Problem p;
+
+ p.declare_parameters (prm);
+
+ // read input from "prmtest.prm"; giving
+ // argv[1] would also be a good idea
+ prm.read_input ("prmtest.prm");
+
+ // print parameters to cout as ASCII text
+ cout << endl << endl;
+ prm.print_parameters (cout, Text);
+
+ // get parameters into the program
+ cout << endl << endl
+ << "Getting parameters:" << endl;
+ p.get_parameters (prm);
+ };
+ \end{verbatim}
+
+
+ This is the input file (named "prmtest.prm"):
+ \begin{verbatim}
+ # first declare the types of equations
+ set Equation 1 = Poisson
+ set Equation 2 = Navier-Stokes
+
+ subsection Equation 1
+ set Matrix type = Sparse
+ subsection Linear solver # parameters for linear solver 1
+ set Solver = Gauss-Seidel
+ set Maximum number of iterations = 40
+ end
+ end
+
+ subsection Equation 2
+ set Matrix type = Full
+ subsection Linear solver
+ set Solver = CG
+ set Maximum number of iterations = 100
+ end
+ end
+ \end{verbatim}
+
+ And here is the ouput of the program:
+ \begin{verbatim}
+ Line 8:
+ The entry value
+ Gauss-Seidel
+ for the entry named
+ Solver
+ does not match the given regular expression
+ \(CG\|BiCGStab\|GMRES\)
+
+
+ Listing of Parameters
+ ---------------------
+ Equation 1 = Poisson <Laplace>
+ Equation 2 = Navier-Stokes <Elasticity>
+ Output file= out
+ subsection Equation 1
+ Matrix type = Sparse <Sparse>
+ subsection Linear solver
+ Maximum number of iterations = 40 <20>
+ Solver = CG
+ subsection Equation 2
+ Matrix type = Full <Sparse>
+ subsection Linear solver
+ Maximum number of iterations = 100 <20>
+ Solver = CG <CG>
+
+
+ Getting parameters:
+ LinEq: Method=CG, MaxIterations=40
+ LinEq: Method=CG, MaxIterations=100
+ Problem: outfile=out
+ eq1=Poisson, eq2=Navier-Stokes
+ Matrix1=Sparse, Matrix2=Full
+ \end{verbatim}
+
+
+ {\bf References}
+
+ This class is inspired by the #MenuSystem# class of #DiffPack#.
+
+ @memo This class provides a standard interface to an input file
+ which provides at run-time for program parameters such as time step sizes,
+ geometries, right hand sides etc.
+
+ @author Wolfgang Bangerth, October 1997, revised February 1998
+ @see MultipleParameterLoop
+ */
+class ParameterHandler {
+ public:
+ /**
+ * Constructor.
+ */
+ ParameterHandler ();
+
+ /**
+ * Read input from a stream until stream
+ * returns #eof# condition or error.
+ *
+ * Return whether the read was successful.
+ */
+ virtual bool read_input (istream &input);
+
+ /**
+ * Read input from a file the name of which
+ * is given.
+ *
+ * Return whether the read was successful.
+ */
+ virtual bool read_input (const String &filename);
+
+ /**
+ * Read input from a string in memory. The
+ * lines in memory have to be separated by
+ * #\n# characters.
+ *
+ * Return whether the read was successful.
+ */
+ virtual bool read_input_from_string (const char *s);
+
+ /**
+ * Return status of this object:
+ * #true#=clean or #false#=error occured.
+ */
+ bool ok() const { return status; };
+
+ /**
+ * clear status bit and contents.
+ */
+ void clear ();
+
+
+ /**
+ * Declare a new entry with name #entry#,
+ * default and for which
+ * any input has to match the #pattern#
+ * (default: any pattern).
+ * @return #false# if entry already exists or
+ * default value does not match the regular
+ * expression; #true# otherwise.
+ */
+ bool declare_entry (const String &entry,
+ const String &default_value,
+ const String &pattern = ".*");
+
+ /**
+ * Enter a subsection; if not yet
+ * existent, declare it.
+ */
+ void enter_subsection (const String &subsection);
+
+ /**
+ * Leave present subsection.
+ * @return #false# if there is no subsection
+ * to leave; true otherwise.
+ */
+ bool leave_subsection ();
+
+ /**
+ * Return value of entry #entry_string#.
+ * If the entry was changed, then the changed
+ * value is returned, otherwise the default
+ * value. If the value of an undeclared entry
+ * is required, an empty string is returned and
+ * #assert# is used to check whether this entry
+ * was declared (therefore an exception may be
+ * thrown).
+ */
+ const String & get (const String &entry_string) const;
+
+ /**
+ * Return value of entry #entry_string# as
+ * long integer.
+ */
+ long int get_integer (const String &entry_string) const;
+
+ /**
+ * Return value of entry #entry_string# as
+ * double.
+ */
+ double get_double (const String &entry_string) const;
+
+ /**
+ * Print all parameters with the given style
+ * to #out#. Presently only Text and LaTeX
+ * are implemented.
+ */
+ ostream & print_parameters (ostream &out, const OutputStyle style);
+
+ /**
+ * Print out the parameters of the subsection
+ * given by the #subsection_path# member
+ * variable.
+ */
+ void print_parameters_section (ostream &out,
+ const OutputStyle Style,
+ const unsigned int indent_level);
+
+ /**
+ * Declare some regexps which
+ * may be used to define patterns.
+ */
+ struct RegularExpressions {
+ /**
+ * #[ \n\t]+#
+ */
+ static const String WhiteSpace;
+
+ /**
+ * #\\(-?[0-9]+[ \n\t]*\\)#
+ */
+ static const String Integer;
+
+ /**
+ * #\\(#
+ * # -?#
+ * # \\(#
+ * # \\([0-9]+\\.[0-9]*\\)#
+ * # \\|#
+ * # \\([0-9]+\\)#
+ * # \\|#
+ * # \\(\\.[0-9]+\\)#
+ * # \\)#
+ * # \\([eE][---+]?[0-9]+\\)?#
+ * # [ \n\t]*#
+ * #\\)#
+ */
+ static const String Double;
+
+ /**
+ * #"\\([0-9A-Za-z]+[ \n\t]*\\)"#
+ */
+ static const String AlphaNum;
+ };
+
+
+ /**
+ * Exception
+ */
+ DeclException1 (ExcEntryAlreadyExists,
+ String,
+ << "The following entry already exists: " << arg1);
+ /**
+ * Exception
+ */
+ DeclException2 (ExcDefaultDoesNotMatchRegex,
+ String, String,
+ << "The default string <" << arg1
+ << "> does not match the given regex <" << arg2 << ">");
+ /**
+ * Exception
+ */
+ DeclException0 (ExcAlreadyAtTopLevel);
+ /**
+ * Exception
+ */
+ DeclException1 (ExcEntryUndeclared,
+ String,
+ << "You cant ask for entry <" << arg1 << "> you have not yet declared");
+ /**
+ * Exception
+ */
+ DeclException1 (ExcConversionError,
+ String,
+ << "Error when trying to convert the following string: " << arg1);
+ /**
+ * Exception
+ */
+ DeclException0 (ExcNotImplemented);
+
+
+
+ private:
+ /**
+ * ok bit
+ */
+ bool status;
+
+ /**
+ * Whatever is in a section:
+ * map of entry names together with
+ * entry content and regexp, and
+ * list of subsections.
+ */
+ struct Section {
+ ~Section ();
+
+ map<String, pair<String,String>, less<String> > entries;
+ map<String, Section*, less<String> > subsections;
+ };
+
+ /**
+ * Path of presently selected subsections;
+ * empty list means top level
+ */
+ vector<String> subsection_path;
+
+ /**
+ * List of default values organized as a
+ * tree of subsections
+ */
+ Section defaults;
+
+ /**
+ * Analogue list of changed entries. The
+ * tree of subsections is there even if there
+ * are no changed entry values in a
+ * subsection; therefore #enter_subsection#
+ * has to create the tree in both #Defaults#
+ * and #changed_entries.
+ */
+ Section changed_entries;
+
+ /**
+ * Scan one line of input.
+ * #lineno# is the number of the line presently
+ * scanned (for the logs if there are messages).
+ * @return #false# if line contained stuff
+ * that could not be understood, the uppermost
+ * subsection was to be left by an #END# or
+ * #end# statement, a value for a non-declared
+ * entry was given or teh entry value did not
+ * match the regular expression. #true#
+ * otherwise
+ */
+ bool scan_line (String line, const unsigned int lineno);
+
+ /**
+ * Get a pointer to the #Section# structure
+ * in the #Defaults# tree
+ * for the subsection we are presently in.
+ */
+ Section* get_present_defaults_subsection ();
+
+ /**
+ * Same, #const# version.
+ */
+ const Section* get_present_defaults_subsection () const;
+
+ /**
+ * Get a pointer to the #Section# structure
+ * in the #changed_entries# tree
+ * for the subsection we are presently in.
+ */
+ Section* get_present_changed_subsection ();
+
+ /**
+ * Same, #const# version.
+ */
+ const Section* get_present_changed_subsection () const;
+
+ friend class MultipleParameterLoop;
+};
+
+
+
+
+
+/**
+ The class #MultipleParameterLoop# offers an easy possibility to test several
+ parameter sets during one run of the program. For this it uses the
+ #ParameterHandler# class to read in data in a standardized form, searches for
+ variant entry values and performs a loop over all combinations of parameters.
+
+ Variant entry values are given like this:
+ \begin{verbatim}
+ set Time step size = { 0.1 | 0.2 | 0.3 }
+ \end{verbatim}
+ The loop will then perform three runs of the program, one for each value
+ of #Time step size#, while all other parameters are as specified or with their
+ default value. If there are several variant entry values in the input a loop is
+ performed for each combination of variant values:
+ \begin{verbatim}
+ set Time step size = { 0.1 | 0.2 }
+ set Solver = { CG | GMRES }
+ \end{verbatim}
+ will result in four runs of the programs, with time step 0.1 and 0.2 for each
+ of the two solvers.
+
+ Opposite to a variant entry, an array entry looks like this:
+ \begin{verabtim}
+ set Output file = ofile.{{ 1 | 2 | 3 | 4 }}
+ \end{verbatim}
+ This indicates that if there are variant entries producing a total of four
+ different runs will write their results to the files #ofile.1#, #ofile.2#,
+ #ofile.3# and #ofile.4#, respectively. Array entries do not generate multiple
+ runs of the main loop themselves, but if there are variant entries, then in
+ the #n#th run of the main loop, also the #n#th value of an array is returned.
+
+ Since the different variants are constructed in the order of declaration, not in
+ the order in which the variat entries appear in the input file, it may be
+ difficult to guess the mapping between the different variants and the appropriate
+ entry in an array. You will have to check the order of declaration, or use
+ only one variant entry.
+
+ It is guaranteed that only selections which match the regular expression given
+ upon declaration of an entry are given back to the program. If a variant value
+ does not match the regular expression, the default value is stored and an error
+ is issued. Before the first run of the loop, all possible values are checked
+ for their conformance, so that the error is issued at the very beginning of the
+ program.
+
+
+ {\bf Usage}
+
+ The usage of this class is similar to the #ParameterHandler# class. First the
+ entries and subsections have to be declared, then a loop is performed in which
+ the different parameter sets are set, a new instance of a user class is created
+ which is then called. Taking the classes of the example for the
+ #ParameterHandler# class, the extended program would look like this:
+ \begin{verbatim}
+ class HelperClass : public MultipleParameterLoop::UserClass {
+ public:
+ HelperClass ();
+
+ virtual void create_new (unsigned int runNo);
+ virtual void declare_parameters (ParameterHandler &prm);
+ virtual void run (ParameterHandler &prm);
+ private:
+ Problem *p;
+ };
+
+
+ HelperClass::HelperClass () : p(0) {};
+
+
+ void HelperClass::create_new (unsigned int runNo) {
+ if (p) delete p;
+ p = new Problem;
+ };
+
+
+ void HelperClass::declare_parameters (ParameterHandler &prm) {
+ // entries of the problem class
+ // note: must be static member!
+ Problem::declare_parameters (prm);
+ };
+
+
+ void HelperClass::run (ParameterHandler &prm) {
+ p->get_parameters (prm);
+ };
+
+
+
+ void main () {
+ // don't know why we have to write
+ // "class" here, but it won't work
+ // otherwise
+ class MultipleParameterLoop prm;
+ HelperClass h;
+
+ h.declare_parameters (prm);
+ prm.read_input ("prmtest.prm");
+ prm.loop (h);
+ };
+ \end{verbatim}
+
+ As can be seen, first a new helper class has to be set up. This must contain
+ a virtual constructor for a problem class. You can also derive your problem
+ class from #MultipleParameterLoop::UserClass# and let #create_new# clear all
+ member variables. If you have access to all inherited member variables in
+ some way this is the recommended procedure. A third possibility is to use
+ multiple inheritance and derive a helper class from both the
+ #MultipleParameterLoop::UserClass# and the problem class. In any case,
+ #create_new# has to provide a clean problem object which is the problem in
+ the second and third possibility. However, if possible, the second way should
+ be chosen.
+
+ The derived class also
+ has to provide for member functions which declare the entries and which run
+ the program. Running the program includes getting the parameters out of the
+ #ParameterHandler# object.
+
+ After defining an object of this helper class and an object of the
+ #MultipleParameterLoop# class, the entries have to be declared in the same way
+ as for the #ParameterHandler# class. Then the input has to be read. Finally
+ the loop is called. This executes the following steps:
+ \begin{verbatim}
+ for each combination
+ {
+ UserObject.create_new (runNo);
+
+ set parameters for this run
+
+ UserObject.run (*this);
+ };
+ \end{verbatim}
+ #UserObject# is the parameter to the #loop# function. #create_new# is given the number
+ of the run (starting from one) to enable naming output files differently for each
+ run.
+
+
+ {\bf Syntax for variant and array entry values}
+
+ Variant values are specified like #prefix{ v1 | v2 | v3 | ... }postfix#. Whitespace
+ to the right of the opening brace #{# is ignored as well as to the left of the
+ closing brace #}# while whitespace on the respectively other side is not ignored.
+ Whitespace around the mid symbols #|# is also ignored. The empty selection
+ #prefix{ v1 | }postfix# is also allowed and produces the strings #prefixv1postfix# and
+ #prefixpostfix#.
+
+ The syntax for array values is equal, apart from the double braces:
+ #prefix{{ v1 | v2 | v3 }}postfix#.
+
+
+ {\bf Worked example}
+
+ Given the above extensions to the example program for the #ParameterHandler# and the
+ following input file
+ \begin{verbatim}
+ set Equation 1 = Poisson
+ set Equation 2 = Navier-Stokes
+ set Output file= results.{{ 1 | 2 | 3 | 4 | 5 | 6 }}
+
+ subsection Equation 1
+ set Matrix type = Sparse
+ subsection Linear solver
+ set Solver = CG
+ set Maximum number of iterations = { 10 | 20 | 30 }
+ end
+ end
+
+ subsection Equation 2
+ set Matrix type = Full
+ subsection Linear solver
+ set Solver = { BiCGStab | GMRES }
+ set Maximum number of iterations = 100
+ end
+ end
+ \end{verbatim}
+ this is the output:
+ \begin{verbatim}
+ LinEq: Method=CG, MaxIterations=10
+ LinEq: Method=BiCGStab, MaxIterations=100
+ Problem: outfile=results.1
+ eq1=Poisson, eq2=Navier-Stokes
+ Matrix1=Sparse, Matrix2=Full
+ LinEq: Method=CG, MaxIterations=20
+ LinEq: Method=BiCGStab, MaxIterations=100
+ Problem: outfile=results.2
+ eq1=Poisson, eq2=Navier-Stokes
+ Matrix1=Sparse, Matrix2=Full
+ LinEq: Method=CG, MaxIterations=30
+ LinEq: Method=BiCGStab, MaxIterations=100
+ Problem: outfile=results.3
+ eq1=Poisson, eq2=Navier-Stokes
+ Matrix1=Sparse, Matrix2=Full
+ LinEq: Method=CG, MaxIterations=10
+ LinEq: Method=GMRES, MaxIterations=100
+ Problem: outfile=results.4
+ eq1=Poisson, eq2=Navier-Stokes
+ Matrix1=Sparse, Matrix2=Full
+ LinEq: Method=CG, MaxIterations=20
+ LinEq: Method=GMRES, MaxIterations=100
+ Problem: outfile=results.5
+ eq1=Poisson, eq2=Navier-Stokes
+ Matrix1=Sparse, Matrix2=Full
+ LinEq: Method=CG, MaxIterations=30
+ LinEq: Method=GMRES, MaxIterations=100
+ Problem: outfile=results.6
+ eq1=Poisson, eq2=Navier-Stokes
+ Matrix1=Sparse, Matrix2=Full
+ \end{verbatim}
+ Since #create_new# gets the number of the run it would also be possible to output
+ the number of the run.
+
+
+ {\bf References}
+ This class is inspired by the #Multipleloop# class of #DiffPack#.
+
+ @memo This class provides an interface to an input file which provides at
+ run-time for multiple program parameters sets. The class performs a loop over
+ all combinations of parameter sets.
+
+ @author Wolfgang Bangerth, October 1997
+ @version 1.0
+ @see ParameterHandler
+ */
+class MultipleParameterLoop : public ParameterHandler {
+ public:
+ /**
+ * This is the class the helper class or the
+ * problem class has to be derived of.
+ */
+ class UserClass {
+ public:
+ /**
+ * #create_new# must provide a clean
+ * object, either by creating a new one
+ * or by cleaning an old one.
+ */
+ virtual void create_new (const unsigned int runNo) = 0;
+
+ /**
+ * This should declare parameters and call
+ * the #declare_parameters# function of the
+ * problem class.
+ */
+ virtual void declare_parameters (ParameterHandler &prm) = 0;
+
+ /**
+ * Get the parameters and run any
+ * necessary action.
+ */
+ virtual void run (ParameterHandler &prm) = 0;
+ };
+
+ /**
+ * Constructor
+ */
+ MultipleParameterLoop ();
+
+ /**
+ * Read input from a stream until stream
+ * returns #eof# condition or error.
+ */
+ virtual bool read_input (istream &Input);
+
+ /**
+ * Read input from a file the name of which
+ * is given.
+ */
+ virtual bool read_input (const String &FileName);
+
+ /**
+ * Read input from a string in memory. The
+ * lines in memory have to be separated by
+ * #\n# characters.
+ */
+ virtual bool read_input_from_string (const char *s);
+
+ /**
+ * run the central loop.
+ */
+ void loop (UserClass &uc);
+
+ private:
+ /**
+ * An object in the list of entries with
+ * multiple values.
+ */
+ class Entry {
+ public:
+ /**
+ * Constructor
+ */
+ Entry () {};
+
+ /**
+ * Construct an object with given subsection
+ * path, name and value. The splitting up
+ * into the different variants is done
+ * later by #split_different_values.
+ */
+ Entry (const vector<String> &Path, const String &Name, const String &Value);
+
+ /**
+ * Split the entry value into the different
+ * branches.
+ */
+ void split_different_values ();
+
+ /**
+ * Path to variant entry.
+ */
+ vector<String> subsection_path;
+
+ /**
+ * Name of entry.
+ */
+ String entry_name;
+
+ /**
+ * Original variant value.
+ */
+ String entry_value;
+
+ /**
+ * List of entry values constructed out of
+ * what was given in the input file (that
+ * is stored in #EntryValue#.
+ */
+ vector<String> different_values;
+
+ /**
+ * Store whether this entry is a variant
+ * entry or an array.
+ */
+ MultipleEntryType type;
+ };
+
+ /**
+ * List of variant entry values.
+ */
+ vector<Entry> multiple_choices;
+
+ /**
+ * Number of branches constructed from the
+ * different combinations of the variants.
+ * This obviously equals the number of runs
+ * to be performed.
+ */
+ int n_branches;
+
+ /**
+ * Initialize the different branches, i.e.
+ * construct the combinations.
+ */
+ void init_branches ();
+
+ /**
+ * Initialize the branches in the given
+ * section.
+ */
+ void init_branches_section (const ParameterHandler::Section &sec);
+
+ /**
+ * Transfer the entry values for one run
+ * to the entry tree.
+ */
+ void fill_entry_values (const unsigned int run_no);
+};
+
+
+
+
+/********************** parameter-handler.h ****************************/
+/* end of #ifndef __parameter_handler_H */
+#endif
+/********************** parameter-handler.h ****************************/
--- /dev/null
+/*---------------------------- quadrature.h ---------------------------*/
+/* <Id:> */
+#ifndef __quadrature_H
+#define __quadrature_H
+/*---------------------------- quadrature.h ---------------------------*/
+
+
+#include <grid/point.h>
+#include <vector.h>
+
+
+
+/**
+ Base class for quadrature formulae in arbitrary dimensions.
+ */
+template <int dim>
+class Quadrature {
+ public:
+ /**
+ * Number of quadrature points.
+ */
+ const unsigned int n_quad_points;
+
+ /**
+ * Constructor.
+ */
+ Quadrature (const unsigned int n_quad_points);
+
+ /**
+ * Return the #i#th quadrature point.
+ */
+ const Point<dim> & quad_point (const unsigned int i) const;
+
+ /**
+ * Return the weight of the #i#th
+ * quadrature point.
+ */
+ double weight (const unsigned int i) const;
+
+ protected:
+ /**
+ * List of quadrature points. To be filled
+ * by the constructors of derived classes.
+ */
+ vector<Point<dim> > quadrature_points;
+
+ /**
+ * List of weights of the quadrature points.
+ * To be filled by the constructors of
+ * derived classes.
+ */
+ vector<double> weights;
+};
+
+
+
+
+
+/*---------------------------- quadrature.h ---------------------------*/
+/* end of #ifndef __quadrature_H */
+#endif
+/*---------------------------- quadrature.h ---------------------------*/
--- /dev/null
+/*---------------------------- quadrature_lib.h ---------------------------*/
+/* <Id:> */
+#ifndef __quadrature_lib_H
+#define __quadrature_lib_H
+/*---------------------------- quadrature_lib.h ---------------------------*/
+
+
+#include <fe/quadrature.h>
+
+
+template <int dim>
+class QGauss2 : public Quadrature<dim> {
+ public:
+ QGauss2 ();
+};
+
+
+
+template <int dim>
+class QGauss2x4 : public Quadrature<dim> {
+ public:
+ QGauss2x4 ();
+};
+
+
+
+template <int dim>
+class QGauss4 : public Quadrature<dim> {
+ public:
+ QGauss4 ();
+};
+
+
+
+template <int dim>
+class QGauss8 : public Quadrature<dim> {
+ public:
+ QGauss8 ();
+};
+
+
+
+template <int dim>
+class QMidpoint : public Quadrature<dim> {
+ public:
+ QMidpoint ();
+};
+
+
+
+template <int dim>
+class QSimpson : public Quadrature<dim> {
+ public:
+ QSimpson ();
+};
+
+
+
+template <int dim>
+class QTrapez : public Quadrature<dim> {
+ public:
+ QTrapez ();
+};
+
+
+
+
+/*---------------------------- quadrature_lib.h ---------------------------*/
+/* end of #ifndef __quadrature_lib_H */
+#endif
+/*---------------------------- quadrature_lib.h ---------------------------*/
--- /dev/null
+/* $Id$ */
+
+#include <basic/parameter_handler.h>
+#include <fstream.h>
+#include <iomanip.h>
+
+extern "C" {
+#include <stdlib.h>
+}
+
+
+
+const String ParameterHandler::RegularExpressions::WhiteSpace = "[ \n\t]+",
+ ParameterHandler::RegularExpressions::Integer = "\\(-?[0-9]+[ \n\t]*\\)",
+ ParameterHandler::RegularExpressions::Double = "\\("
+ "-?"
+ "\\("
+ "\\([0-9]+\\.[0-9]*\\)"
+ "\\|"
+ "\\([0-9]+\\)"
+ "\\|"
+ "\\(\\.[0-9]+\\)"
+ "\\)"
+ "\\([eE][---+]?[0-9]+\\)?"
+ "[ \n\t]*"
+ "\\)",
+ ParameterHandler::RegularExpressions::AlphaNum = "\\([0-9A-Za-z]+[ \n\t]*\\)";
+
+
+
+ParameterHandler::ParameterHandler () :
+ status(true) {};
+
+
+bool ParameterHandler::read_input (istream &input) {
+ String line;
+ int lineno=0;
+ while (input)
+ {
+ ++lineno;
+ // get one line; limit of 10000
+ // chars is arbitrary but should
+ // be enough
+ char c[10000];
+ input.getline ((char *)&c, 10000);
+ line = c;
+ if (!scan_line (line, lineno))
+ status = false;
+ };
+
+ return status;
+};
+
+
+bool ParameterHandler::read_input (const String &filename) {
+ ifstream input (filename);
+ if (!input)
+ {
+ cerr << "ParameterHandler::read_input: could not open file <"
+ << filename << ">. Aborting." << endl;
+ return false;
+ };
+
+ return read_input (input);
+};
+
+
+
+bool ParameterHandler::read_input_from_string (const char *s) {
+ // if empty string then exit
+ // with success
+ if ((s == 0) || ((*s) == 0)) return true;
+
+ String line;
+ String input (s);
+ int lineno=0;
+
+ // if necessary append a newline char
+ // to make all lines equal
+ if (input[input.length()-1] != '\n')
+ input += '\n';
+
+ while (input)
+ {
+ // get one line from Input (=s)
+ line = input.before ('\n');
+ // delete this part including
+ // the backspace
+ input.del (line);
+ input.del (input[0]);
+ ++lineno;
+
+ if (!scan_line (line, lineno))
+ status = false;
+ };
+
+ return status;
+};
+
+
+
+
+void ParameterHandler::clear () {
+ status = true;
+
+ subsection_path.erase (subsection_path.begin(), subsection_path.end());
+
+ defaults.entries.erase (defaults.entries.begin(), defaults.entries.end());
+ changed_entries.entries.erase (changed_entries.entries.begin(),
+ changed_entries.entries.end());
+
+ map<String, Section*, less<String> >::iterator p;
+
+ for (p=defaults.subsections.begin(); p!=defaults.subsections.end(); ++p)
+ delete (*p).second;
+ for (p=changed_entries.subsections.begin(); p!=changed_entries.subsections.end(); ++p)
+ delete (*p).second;
+
+ defaults.subsections.erase (defaults.subsections.begin(), defaults.subsections.end());
+ changed_entries.subsections.erase (changed_entries.subsections.begin(),
+ changed_entries.subsections.end());
+};
+
+
+
+bool ParameterHandler::declare_entry (const String &entry,
+ const String &default_value,
+ const String &pattern) {
+ Section* p = get_present_defaults_subsection ();
+
+ // assertions:
+ // entry must not already exist
+ Assert (p->entries.find (entry) == p->entries.end(),
+ ExcEntryAlreadyExists (entry));
+ // Default must match Pattern
+ Assert (default_value.matches (Regex(pattern)),
+ ExcDefaultDoesNotMatchRegex(default_value, pattern));
+
+ // does entry already exist?
+ if (p->entries.find (entry) != p->entries.end())
+ return false;
+
+ p->entries[entry] = make_pair(default_value, pattern);
+
+ // check whether default answer matches
+ // the pattern
+ if (!default_value.matches (Regex(pattern)))
+ return false;
+
+ return true;
+};
+
+
+
+
+void ParameterHandler::enter_subsection (const String &subsection) {
+ Section* pd = get_present_defaults_subsection ();
+
+ // does subsection already exist?
+ if (pd->subsections.find (subsection) == pd->subsections.end())
+ {
+ // subsection does not yet exist:
+ // create entry in Defaults and
+ // changed_entries trees
+ pd->subsections[subsection] = new Section();
+
+ Section* pc = get_present_changed_subsection ();
+ pc->subsections[subsection] = new Section();
+ };
+
+ // finally enter subsection
+ subsection_path.push_back (subsection);
+};
+
+
+
+bool ParameterHandler::leave_subsection () {
+ // assert there is a subsection that
+ // we may leave
+ // (use assert since this is a logical
+ // error in a program. When reading input
+ // the scan_line function has to check
+ // whether there is a subsection to be left!)
+ Assert (subsection_path.size() != 0, ExcAlreadyAtTopLevel());
+
+ if (subsection_path.size() == 0)
+ return false;
+
+ subsection_path.pop_back ();
+ return true;
+};
+
+
+
+const String & ParameterHandler::get (const String &entry_string) const {
+ const Section* pd = get_present_defaults_subsection ();
+ const Section* pc = get_present_changed_subsection ();
+
+ // assert that the according entry is already
+ // declared in the defaults tree
+ Assert (pd->entries.find (entry_string) != pd->entries.end(),
+ ExcEntryUndeclared(entry_string));
+
+ if (pd->entries.find (entry_string) == pd->entries.end())
+ {
+ static const String empty_string;
+ return empty_string;
+ };
+
+
+ // entry exists; now find out whether
+ // it was changed:
+ map<String, pair<String,String>, less<String> >::const_iterator ptr;
+ ptr = pc->entries.find (entry_string);
+ if (ptr != pc->entries.end())
+ return (*ptr).second.first;
+
+ // not changed
+ ptr = pd->entries.find (entry_string);
+ return (*ptr).second.first;
+};
+
+
+
+long int ParameterHandler::get_integer (const String &entry_string) const {
+ String s = get (entry_string);
+ char *endptr;
+ long int i = strtol (s.chars(), &endptr, 10);
+ // assert there was no error
+ Assert ((s.chars()!='\0') || (*endptr == '\0'),
+ ExcConversionError(s));
+
+ return i;
+};
+
+
+
+double ParameterHandler::get_double (const String &entry_string) const {
+ String s = get (entry_string);
+ char *endptr;
+ double d = strtod (s.chars(), &endptr);
+ // assert there was no error
+ Assert ((s.chars()!='\0') || (*endptr == '\0'),
+ ExcConversionError(s));
+
+ return d;
+};
+
+
+
+
+ostream & ParameterHandler::print_parameters (ostream &out, OutputStyle style) {
+ // assert that only known formats are
+ // given as "style"
+ Assert ((style == Text) || (style == LaTeX), ExcNotImplemented());
+
+ switch (style)
+ {
+ case Text:
+ out << "Listing of Parameters" << endl
+ << "---------------------" << endl;
+ break;
+ case LaTeX:
+ out << "\\subsubsection*{Listing of parameters}";
+ out << endl << endl;
+ out << "\\begin{itemize}"
+ << endl;
+ break;
+ default:
+ Assert (false, ExcNotImplemented());
+ };
+
+ // dive recursively into the subsections
+ print_parameters_section (out, style, 1);
+
+ switch (style)
+ {
+ case Text:
+ break;
+ case LaTeX:
+ out << "\\end{itemize}" << endl;
+ break;
+ default:
+ Assert (false, ExcNotImplemented());
+ };
+
+ return out;
+};
+
+
+
+void ParameterHandler::print_parameters_section (ostream &out,
+ const OutputStyle style,
+ const unsigned int indent_level) {
+ // assert that only known formats are
+ // given as "style"
+ Assert ((style == Text) || (style == LaTeX), ExcNotImplemented());
+
+ Section *pd = get_present_defaults_subsection ();
+ Section *pc = get_present_changed_subsection ();
+
+ // traverse entry list
+ map<String, pair<String,String>, less<String> >::const_iterator ptr;
+
+ // first find out the longest entry name
+ unsigned int longest_entry = 0;
+ for (ptr = pd->entries.begin(); ptr != pd->entries.end(); ++ptr)
+ if ((*ptr).first.length() > longest_entry)
+ longest_entry = (*ptr).first.length();
+
+ // print entries one by one
+ for (ptr = pd->entries.begin(); ptr != pd->entries.end(); ++ptr)
+ {
+ // check whether this entry is listed
+ // in the Changed tree
+ if (pc->entries.find((*ptr).first) != pc->entries.end())
+ switch (style)
+ {
+ case Text:
+ out << setw(indent_level*2) << ""
+ << (*ptr).first
+ << setw(longest_entry-(*ptr).first.length()+3) << " = "
+ << pc->entries[(*ptr).first].first
+ << " <"
+ << pd->entries[(*ptr).first].first
+ << ">"
+ << endl;
+ break;
+ case LaTeX:
+ out << "\\item {\\bf " << (*ptr).first << ":} "
+ << pc->entries[(*ptr).first].first
+ << " ({\\it default:} "
+ << pd->entries[(*ptr).first].first
+ << ")"
+ << endl;
+ break;
+ default:
+ Assert (false, ExcNotImplemented());
+ }
+ // not a changed entry
+ else
+ switch (style)
+ {
+ case Text:
+ out << setw(indent_level*2) << ""
+ << (*ptr).first
+ << setw(longest_entry-(*ptr).first.length()+2) << "= "
+ << (*ptr).second.first << endl;
+ break;
+ case LaTeX:
+ out << "\\item {\\bf " << (*ptr).first << ":} "
+ << (*ptr).second.first
+ << endl;
+ break;
+ default:
+ Assert (false, ExcNotImplemented());
+ };
+ };
+
+
+ // now transverse subsections tree
+ map<String, Section*, less<String> >::const_iterator ptrss;
+ for (ptrss = pd->subsections.begin(); ptrss != pd->subsections.end(); ++ptrss)
+ {
+ switch (style)
+ {
+ case Text:
+ out << setw(indent_level*2) << ""
+ << "subsection " << (*ptrss).first << endl;
+ break;
+ case LaTeX:
+ out << endl
+ << "\\item {\\bf "
+ << "Subsection " << (*ptrss).first
+ << "}" << endl
+ << "\\begin{itemize}"
+ << endl;
+ break;
+ default:
+ Assert (false, ExcNotImplemented());
+ };
+ enter_subsection ((*ptrss).first);
+ print_parameters_section (out, style, indent_level+1);
+ leave_subsection ();
+ switch (style)
+ {
+ case Text:
+ break;
+ case LaTeX:
+ out << "\\end{itemize}"
+ << endl;
+ break;
+ default:
+ Assert (false, ExcNotImplemented());
+ };
+ };
+};
+
+
+
+
+
+bool ParameterHandler::scan_line (String line, const unsigned int lineno) {
+ // if there is a comment, delete it
+ if (line.contains ('#'))
+ line = line.before ("#");
+ // replace every whitespace sequence
+ // by ' '
+ line.gsub (Regex(RegularExpressions::WhiteSpace), ' ');
+ // now every existing whitespace
+ // should be exactly on ' ';
+ // if at end or beginning: delete
+ if ((line.length() != 0) && (line[0] == ' ')) line.del (' ');
+ // if line is now empty: leave
+ if (line.length() == 0) return true;
+
+ if (line[line.length()-1] == ' ') line.at (' ', -1) = "";
+
+ static Regex re_enter_subsection ("\\(SUBSECTION\\|subsection\\)"
+ "[ \n\t]+"
+ "\\(.*\\)");
+ static Regex re_entry ("\\(SET\\|set\\)" // "set" command
+ "[ \n\t]+"
+ "\\(.*[^ \t\n]\\)" // 2: entry name
+ "[ \n\t]*"
+ "="
+ "[ \n\t]*"
+ "\\(.*\\)"); // 3: entry value
+ static Regex re_exit_subsection ("\\(END\\|end\\)");
+
+ // enter subsection
+ if (line.matches (re_enter_subsection))
+ {
+ // first find out name of subsection
+ int start, len;
+ re_enter_subsection.match (line, line.length());
+ re_enter_subsection.match_info (start, len, 2);
+
+ String SecName = line.at (start, len);
+ Section* pc = get_present_changed_subsection ();
+ // check whether subsection exists
+ if (pc->subsections.find(SecName) == pc->subsections.end())
+ {
+ cerr << "Line " << lineno << ": There is no such subsection to be entered:" << endl;
+ for (unsigned int i=0; i<subsection_path.size(); ++i)
+ cerr << setw(i*2+4) << " "
+ << "subsection " << subsection_path[i] << endl;
+ cerr << setw(subsection_path.size()*2+4) << " "
+ << "subsection " << SecName << endl;
+ return false;
+ };
+
+ // subsection exists
+ subsection_path.push_back (SecName);
+ return true;
+ };
+
+
+ // exit subsection
+ if (line.matches (re_exit_subsection))
+ if (subsection_path.size() == 0)
+ {
+ cerr << "Line " << lineno << ": There is no subsection to leave here!" << endl;
+ return false;
+ }
+ else
+ return leave_subsection ();
+
+
+ // regular entry
+ if (line.matches (re_entry))
+ {
+ int start, end;
+ re_entry.match (line, line.length());
+
+ // extract entry name
+ re_entry.match_info (start, end, 2);
+ String entry_name = line.at (start, end);
+
+ // extract entry value
+ re_entry.match_info (start, end, 3);
+ String entry_value = line.at (start, end);
+
+ Section* pd = get_present_defaults_subsection ();
+
+ // check whether entry was declared
+ if (pd->entries.find(entry_name) == pd->entries.end())
+ {
+ cerr << "Line " << lineno
+ << ": No such entry was declared:" << endl
+ << " " << entry_name << endl
+ << " <Present subsection:" << endl;
+ for (unsigned int i=0; i<subsection_path.size(); ++i)
+ cerr << setw(i*2+8) << " "
+ << "subsection " << subsection_path[i] << endl;
+ cerr << " >" << endl;
+
+ return false;
+ };
+
+ // if entry was declared:
+ // does it match the regex? if not,
+ // don't enter it into the database
+ // exception: if it contains characters
+ // which specify it as a multiple loop
+ // entry, then ignore content
+ if (!entry_value.contains ('{'))
+ if (!entry_value.matches (Regex(pd->entries[entry_name].second)))
+ {
+ cerr << "Line " << lineno << ":" << endl
+ << " The entry value" << endl
+ << " " << entry_value << endl
+ << " for the entry named" << endl
+ << " " << entry_name << endl
+ << " does not match the given regular expression" << endl
+ << " " << pd->entries[entry_name].second << endl;
+ return false;
+ };
+
+ Section* pc = get_present_changed_subsection ();
+ // the following line declares this entry
+ // if not yet existent and overwrites it
+ // otherwise
+ pc->entries[entry_name] = make_pair(entry_value, String(""));
+
+ return true;
+ };
+
+ // this line matched nothing known
+ cerr << "Line " << lineno << ": This line matched nothing known:" << endl
+ << " " << line << endl;
+ return false;
+};
+
+
+
+ParameterHandler::Section* ParameterHandler::get_present_defaults_subsection () {
+ Section* sec = &defaults;
+ vector<String>::const_iterator SecName;
+ SecName = subsection_path.begin();
+
+ while (SecName != subsection_path.end())
+ {
+ sec = sec->subsections[*SecName];
+ ++SecName;
+ };
+
+ return sec;
+};
+
+
+
+const ParameterHandler::Section* ParameterHandler::get_present_defaults_subsection () const {
+ // simply call the non-const version
+ // of this function
+ typedef Section* (ParameterHandler::*xptr) ();
+ xptr x = &get_present_defaults_subsection;
+
+ return x();
+};
+
+
+
+ParameterHandler::Section* ParameterHandler::get_present_changed_subsection () {
+ Section* sec = &changed_entries;
+ vector<String>::iterator SecName;
+ SecName = subsection_path.begin();
+
+ while (SecName != subsection_path.end())
+ {
+ sec = sec->subsections[*SecName];
+ ++SecName;
+ };
+
+ return sec;
+};
+
+
+
+const ParameterHandler::Section* ParameterHandler::get_present_changed_subsection () const {
+ // simply call the non-const version
+ // of this function
+ typedef Section* (ParameterHandler::*xptr) ();
+ xptr x = &get_present_changed_subsection;
+
+ return x();
+};
+
+
+
+ParameterHandler::Section::~Section () {
+ entries.erase (entries.begin(), entries.end());
+
+ map<String, Section*, less<String> >::iterator p;
+
+ for (p=subsections.begin(); p!=subsections.end(); ++p)
+ delete (*p).second;
+
+
+ subsections.erase (subsections.begin(), subsections.end());
+};
+
+
+
+
+
+MultipleParameterLoop::MultipleParameterLoop() :
+ n_branches(0) {};
+
+
+bool MultipleParameterLoop::read_input (istream &input) {
+ bool x = ParameterHandler::read_input (input);
+ if (x) init_branches ();
+ return x;
+};
+
+
+bool MultipleParameterLoop::read_input (const String &filename) {
+ // I don't know why it is necessary to
+ // declare this function: simply not
+ // overloading it in MultipleParameterLoop
+ // should suffice, but then the compiler can't
+ // find the inherited version and complains that
+ // it can't find a function MultipleParameterLoop::
+ // read_input (String, ostream) instead of trying the
+ // base class (maybe wait for gcc2.8)
+ return ParameterHandler::read_input (filename);
+ // don't call init_branches, since this read_input
+ // function calls
+ // MultipleParameterLoop::Readinput(istream &, ostream &)
+ // which itself calls init_branches.
+};
+
+
+bool MultipleParameterLoop::read_input_from_string (const char *s) {
+ bool x = ParameterHandler::read_input (s);
+ init_branches ();
+ return x;
+};
+
+
+
+
+
+void MultipleParameterLoop::loop (MultipleParameterLoop::UserClass &uc) {
+ for (int run_no=0; run_no<n_branches; ++run_no)
+ {
+ // give create_new one-based numbers
+ uc.create_new (run_no+1);
+ fill_entry_values (run_no);
+ uc.run (*this);
+ };
+};
+
+
+void MultipleParameterLoop::init_branches () {
+ if (multiple_choices.size() != 0)
+ multiple_choices.erase (multiple_choices.begin(), multiple_choices.end());
+
+ ParameterHandler::Section *sec;
+ // first check the defaults entries whether it
+ // contains multiple choices
+ sec = &defaults;
+ init_branches_section (*sec);
+
+ // then check changed entries
+ sec = &changed_entries;
+ init_branches_section (*sec);
+
+ // split up different values
+ for (unsigned int i=0; i<multiple_choices.size(); ++i)
+ multiple_choices[i].split_different_values ();
+
+ // check whether we have included a multiple
+ // choice entry from the defaults section which
+ // has only one single value after reading the
+ // input
+ if (multiple_choices.size() > 0)
+ for (vector<Entry>::iterator i=multiple_choices.end()-1;
+ i >= multiple_choices.begin(); --i)
+ if ((*i).different_values.size() == 1)
+ multiple_choices.erase (i);
+
+ // finally calculate number of branches
+ n_branches = 1;
+ for (unsigned int i=0; i<multiple_choices.size(); ++i)
+ if (multiple_choices[i].type == variant)
+ n_branches *= multiple_choices[i].different_values.size();
+
+ // check whether array entries have the correct
+ // number of entries
+ for (unsigned int i=0; i<multiple_choices.size(); ++i)
+ if (multiple_choices[i].type == array)
+ if (multiple_choices[i].different_values.size() != (unsigned int)n_branches)
+ cerr << " The entry value" << endl
+ << " " << multiple_choices[i].entry_value << endl
+ << " for the entry named" << endl
+ << " " << multiple_choices[i].entry_name << endl
+ << " does not have the right number of entries for the " << endl
+ << " " << n_branches << " variant runs that will be performed." << endl;
+
+
+
+ // do a first run on filling the values to
+ // check for the conformance with the regexp
+ // (afterwards, this will be lost in the whole
+ // other output)
+ for (int i=0; i<n_branches; ++i)
+ fill_entry_values (i);
+};
+
+
+
+void MultipleParameterLoop::init_branches_section (const ParameterHandler::Section &sec) {
+ // check all entries in the present subsection
+ // whether it is a multiple entry
+ map<String, pair<String,String>, less<String> >::const_iterator e;
+ for (e = sec.entries.begin(); e != sec.entries.end(); ++e)
+ if ((*e).second.first.contains('{'))
+ multiple_choices.push_back (Entry(subsection_path,
+ (*e).first,
+ (*e).second.first));
+
+
+ // transverse subsections
+ map<String, Section*, less<String> >::const_iterator s;
+ for (s = sec.subsections.begin(); s != sec.subsections.end(); ++s)
+ {
+ enter_subsection ((*s).first);
+ init_branches_section (*(*s).second);
+ leave_subsection ();
+ };
+};
+
+
+void MultipleParameterLoop::fill_entry_values (const unsigned int run_no) {
+ int possibilities = 1;
+
+ vector<Entry>::iterator choice;
+ for (choice = multiple_choices.begin();
+ choice != multiple_choices.end();
+ ++choice)
+ {
+ // temporarily enter the subsection tree
+ // of this multiple entry
+ subsection_path.swap ((*choice).subsection_path);
+
+ // set entry
+ Section* pd = get_present_defaults_subsection ();
+ int selection = (run_no/possibilities) % (*choice).different_values.size();
+ String entry_value;
+ if ((*choice).type == variant)
+ entry_value = (*choice).different_values[selection];
+ else
+ {
+ if (run_no>=(*choice).different_values.size())
+ {
+ cerr << "The given array for entry "
+ << pd->entries[(*choice).entry_name].first
+ << " does not conatin enough elements! Taking empty string instead." << endl;
+ entry_value = "";
+ }
+ else
+ entry_value = (*choice).different_values[run_no];
+ };
+
+ // check conformance with regex
+ if (!entry_value.matches (Regex(pd->entries[(*choice).entry_name].second)))
+ {
+ cerr << "In run no. " << run_no+1 << ":" << endl
+ << " The entry value" << endl
+ << " " << entry_value << endl
+ << " for the entry named" << endl
+ << " " << (*choice).entry_name << endl
+ << " does not match the given regular expression" << endl
+ << " " << pd->entries[(*choice).entry_name].second << endl
+ << " Taking default value" << endl
+ << " " << pd->entries[(*choice).entry_name].first << endl;
+
+ // select default instead
+ entry_value = pd->entries[(*choice).entry_name].first;
+ };
+
+ Section* pc = get_present_changed_subsection ();
+ pc->entries[(*choice).entry_name] = make_pair(entry_value, String(""));
+
+ // get out of subsection again
+ subsection_path.swap ((*choice).subsection_path);
+
+ // move ahead if it was a variant entry
+ if ((*choice).type == variant)
+ possibilities *= (*choice).different_values.size();
+ };
+
+};
+
+
+
+MultipleParameterLoop::Entry::Entry (const vector<String> &ssp,
+ const String& Name,
+ const String& Value) :
+ subsection_path (ssp), entry_name(Name), entry_value(Value) {};
+
+
+
+void MultipleParameterLoop::Entry::split_different_values () {
+ Regex re_entry ("\\([^{]*\\){{? *\\([^}]*[^ }]\\) *}}?\\(.*\\)");
+ int start, len;
+
+ // split string into three parts:
+ // part before the opening "{",
+ // the selection itself, final
+ // part after "}"
+ String prefix, multiple, postfix;
+ re_entry.match (entry_value, entry_value.length());
+
+ re_entry.match_info (start, len, 1);
+ prefix = entry_value.at (start, len);
+
+ re_entry.match_info (start, len, 2);
+ multiple = entry_value.at (start, len);
+
+ re_entry.match_info (start, len, 3);
+ postfix = entry_value.at (start, len);
+
+
+ // delete spaces around '|'
+ multiple.gsub (" |", '|');
+ multiple.gsub ("| ", '|');
+
+ while (multiple.contains ('|'))
+ {
+ different_values.push_back (prefix+multiple.before('|')+postfix);
+ multiple.through ('|') = "";
+ };
+ // make up the last selection ("while" broke
+ // because there was no '|' any more
+ different_values.push_back (prefix+multiple+postfix);
+
+ // finally check whether this was a variant
+ // entry ({...}) or an array ({{...}})
+ if (entry_value.contains(Regex(".*{{.*}}.*")))
+ type = array;
+ else
+ type = variant;
+};
+
+
--- /dev/null
+/* $Id$ */
+
+#include <fe/quadrature_lib.h>
+
+
+
+QGauss2<1>::QGauss2 () :
+ Quadrature<1> (2)
+{
+ static const double xpts[] = { 0.288675135, 0.71132486 };
+ static const double wts[] = { 0.5, 0.5 };
+
+ for (unsigned int i=0; i<n_quad_points; ++i)
+ {
+ quadrature_points.push_back (Point<1> (xpts[i]));
+ weights.push_back (wts[i]);
+ };
+};
+
+
+
+QGauss2x4<1>::QGauss2x4 () :
+ Quadrature<1> (8)
+{
+ static const double G0=0.930568156,
+ G1=0.669990522,
+ G2=0.330009478,
+ G3=0.069431844;
+ static const double W0=0.173927423,
+ W1=0.326072577;
+
+ static const double xpts[] = { 0.5*G0, 0.5*G1, 0.5*G2, 0.5*G3,
+ 0.5*G0+0.5, 0.5*G1+0.5, 0.5*G2+0.5, 0.5*G3+0.5 };
+ static const double wts[] = { 0.5*W0, 0.5*W1, 0.5*W1, 0.5*W0,
+ 0.5*W0, 0.5*W1, 0.5*W1, 0.5*W0 };
+
+ for (unsigned int i=0; i<n_quad_points; ++i)
+ {
+ quadrature_points.push_back (Point<1> (xpts[i]));
+ weights.push_back (wts[i]);
+ };
+};
+
+
+
+QGauss4<1>::QGauss4 () :
+ Quadrature<1> (4)
+{
+ static const double G0=0.930568156,
+ G1=0.669990522,
+ G2=0.330009478,
+ G3=0.069431844;
+ static const double W0=0.173927423,
+ W1=0.326072577;
+
+ static const double xpts[] = { G0, G1, G2, G3 };
+ static const double wts[] = { W0, W1, W1, W0 };
+
+ for (unsigned int i=0; i<n_quad_points; ++i)
+ {
+ quadrature_points.push_back (Point<1> (xpts[i]));
+ weights.push_back (wts[i]);
+ };
+};
+
+
+
+QGauss8<1>::QGauss8 () :
+ Quadrature<1> (8)
+{
+ static const double G0=0.0198550717512321,
+ G1=0.1016667612931866,
+ G2=0.2372337950418355,
+ G3=0.4082826787521749,
+ G4=0.5917173212478251,
+ G5=0.7627662049581646,
+ G6=0.8983332387068134,
+ G7=0.9801449282487679;
+ static const double W0=0.0506142681451880,
+ W1=0.1111905172266870,
+ W2=0.1568533229389435,
+ W3=0.1813418916891810;
+
+ static const double xpts[] = { G0, G1, G2, G3, G4, G5, G6, G7 };
+ static const double wts[] = { W0, W1, W2, W3, W3, W2, W1, W0 };
+
+ for (unsigned int i=0; i<n_quad_points; ++i)
+ {
+ quadrature_points.push_back (Point<1> (xpts[i]));
+ weights.push_back (wts[i]);
+ };
+};
+
+
+
+QMidpoint<1>::QMidpoint () :
+ Quadrature<1>(1)
+{
+ quadrature_points.push_back (0.5);
+ weights.push_back (1.0);
+};
+
+
+
+QSimpson<1>::QSimpson () :
+ Quadrature<1> (3)
+{
+ static const double xpts[] = { 0.0, 0.5, 1.0 };
+ static const double wts[] = { 1./6., 2./3., 1./6. };
+
+ for (unsigned int i=0; i<n_quad_points; ++i)
+ {
+ quadrature_points.push_back (Point<1> (xpts[i]));
+ weights.push_back (wts[i]);
+ };
+};
+
+
+
+QTrapez<1>::QTrapez () :
+ Quadrature<1> (2)
+{
+ static const double xpts[] = { 0.0, 1.0 };
+ static const double wts[] = { 0.5, 0.5 };
+
+ for (unsigned int i=0; i<n_quad_points; ++i)
+ {
+ quadrature_points.push_back (Point<1> (xpts[i]));
+ weights.push_back (wts[i]);
+ };
+};
--- /dev/null
+# $Id$
+
+CXX=c++
+CXXFLAGS.g= -DDEBUG -g -Wall -I../include
+CXXFLAGS = -O3 -I../include
+
+LIBS.g = -L../lib -lbasic.g -lgrid.g -lfe.g -lnumerics.g -ldeal.g
+LIBS = -L../lib -lbasic -lgrid -lfe -lnumerics -ldeal
+
+ifeq ($(shell uname),SunOS)
+CXXFLAGS := -V2.7.2.3 $(CXXFLAGS)
+CXXFLAGS.g:= -V2.7.2.3 $(CXXFLAGS.g)
+endif
+
+
+cc-files = grid/grid_test.cc
+o-files = $(cc-files:.cc=.o)
+h-files = $(wildcard ../include/*.h)
+
+examples: grid/grid_test dof/dof_test
+
+
+grid/grid_test: grid/grid_test.o ../lib/libgrid.a
+ $(CXX) $(CXXFLAGS) -o $@ $< $(LIBS)
+
+dof/dof_test: dof/dof_test.o ../lib/libgrid.g.a ../lib/libdeal.g.a
+ $(CXX) $(CXXFLAGS.g) -o $@ $< $(LIBS.g) -lg++
+
+
+run: run_grid_test run_dof_test
+
+run_grid_test:
+ cd grid ; grid_test 4 ; mv grid.1 grid.4
+ cd grid ; grid_test 3 ; mv grid.1 grid.3
+ cd grid ; grid_test 2 ; mv grid.1 grid.2
+ cd grid ; grid_test 1
+ cd grid ; gnuplot make_ps
+
+run_dof_test:
+ cd dof ; dof_test dof_test.prm
+ cd dof ; gnuplot make_ps
+
+clean:
+ cd grid ; rm -f grid.[1234] *.eps *.o *~ grid_test
+ cd dof ; rm -f grid.* sparsity.* *.o *~ dof_test
+
+
+#Rule to generate the dependency file. This file is
+#automagically remade whenever needed, i.e. whenever
+#one of the cc-/h-files changed. Make detects whether
+#to remake this file upon inclusion at the bottom
+#of this file.
+Makefile.dep: $(cc-files) $(h-files)
+ $(CXX) -I../include -M $(cc-files) > Makefile.dep
+
+include Makefile.dep
--- /dev/null
+/* $Id$ */
+
+
+#include <grid/dof.h>
+#include <grid/tria.h>
+#include <fe/fe_lib.h>
+#include <grid/tria_iterator.h>
+#include <grid/tria_accessor.h>
+#include "../../deal/dsmatrix.h"
+#include <basic/parameter_handler.h>
+#include <grid/dof_constraints.h>
+
+
+#include <fstream.h>
+#include <cmath>
+extern "C" {
+# include <stdlib.h>
+}
+
+extern TriaActiveIterator<1,CellAccessor<1> > x;
+extern TriaActiveIterator<2,CellAccessor<2> > y;
+
+
+
+// 1: continuous refinement of the unit square always in the middle
+// 2: refinement of the circle at the boundary
+// 2: refinement of a wiggled area at the boundary
+// 4: random refinement
+
+
+
+
+
+
+template <int dim>
+class Ball :
+ public StraightBoundary<dim> {
+ public:
+ virtual Point<dim> in_between (const PointArray &neighbors) const {
+ Point<dim> middle = StraightBoundary<dim>::in_between(neighbors);
+
+ for (int i=0; i<dim; ++i)
+ middle(i) -= .5;
+ middle /= (sqrt(middle.square())*sqrt(2));
+ for (int i=0; i<dim; ++i)
+ middle(i) += .5;
+
+ return middle;
+ };
+};
+
+
+template <int dim>
+class CurvedLine :
+ public StraightBoundary<dim> {
+ public:
+ virtual Point<dim> in_between (const PointArray &neighbors) const {
+ Point<dim> middle = StraightBoundary<dim>::in_between(neighbors);
+ double x=middle(0),
+ y=middle(1);
+
+ if (y<x)
+ if (y<1-x)
+ middle(1) = 0.04*sin(6*3.141592*middle(0));
+ else
+ middle(0) = 1+0.04*sin(6*3.141592*middle(1));
+
+ else
+ if (y<1-x)
+ middle(0) = 0.04*sin(6*3.141592*middle(1));
+ else
+ middle(1) = 1+0.04*sin(6*3.141592*middle(0));
+
+ return middle;
+ };
+};
+
+
+
+template <int dim>
+class TestCases : public MultipleParameterLoop::UserClass{
+ public:
+ TestCases ();
+
+ virtual void create_new (const unsigned int run_no);
+ virtual void declare_parameters (ParameterHandler &prm);
+ virtual void run (ParameterHandler &prm);
+
+ private:
+ Triangulation<dim> *tria;
+ DoFHandler<dim> *dof;
+};
+
+
+
+template <int dim>
+TestCases<dim>::TestCases () :
+ tria(0), dof(0) {};
+
+
+
+template <int dim>
+void TestCases<dim>::create_new (const unsigned int) {
+ if (tria != 0) delete tria;
+ if (dof != 0) delete dof;
+
+ tria = new Triangulation<dim>();
+ tria->create_unit_hypercube();
+
+ dof = new DoFHandler<dim> (tria);
+};
+
+
+
+template <int dim>
+void TestCases<dim>::declare_parameters (ParameterHandler &prm) {
+ if (dim>=2)
+ prm.declare_entry ("Test run", "zoom in", "zoom in\\|ball\\|curved line\\|random");
+ else
+ prm.declare_entry ("Test run", "zoom in", "zoom in\\|random");
+ prm.declare_entry ("Grid file", "grid.1");
+ prm.declare_entry ("Sparsity file", "sparsity.1");
+ prm.declare_entry ("Condensed sparsity file", "sparsity.c.1");
+};
+
+
+
+template <int dim>
+void TestCases<dim>::run (ParameterHandler &prm) {
+ cout << "Test case = " << prm.get ("Test run") << endl
+ << endl;
+
+ cout << " Making grid..." << endl;
+
+ String test = prm.get ("Test run");
+ unsigned int test_case;
+ if (test=="zoom in") test_case = 1;
+ else
+ if (test=="ball") test_case = 2;
+ else
+ if (test=="curved line") test_case = 3;
+ else
+ if (test=="random") test_case = 4;
+ else
+ cerr << "This test seems not to be implemented!" << endl;
+
+
+ switch (test_case)
+ {
+ case 1:
+ {
+ // refine first cell
+ tria->begin_active()->set_refine_flag();
+ tria->execute_refinement ();
+ // refine first active cell
+ // on coarsest level
+ tria->begin_active()->set_refine_flag ();
+ tria->execute_refinement ();
+
+ Triangulation<dim>::active_cell_iterator cell;
+ for (int i=0; i<17; ++i)
+ {
+ // refine the presently
+ // second last cell 17
+ // times
+ cell = tria->last_active(tria->n_levels()-1);
+ --cell;
+ cell->set_refine_flag ();
+ tria->execute_refinement ();
+ };
+
+// tria->refine_global (5);
+
+ break;
+ }
+
+ case 2:
+ case 3:
+ {
+ // set the boundary function
+ Boundary<dim> *boundary = (test_case==2 ?
+ new Ball<dim>() :
+ new CurvedLine<dim>());
+ tria->set_boundary (boundary);
+
+ // refine once
+ tria->begin_active()->set_refine_flag();
+ tria->execute_refinement ();
+
+ Triangulation<dim>::active_cell_iterator cell, endc;
+ for (int i=0; i<4; ++i)
+ {
+ cell = tria->begin_active();
+ endc = tria->end();
+
+ // refine all
+ // boundary cells
+ for (; cell!=endc; ++cell)
+ if (cell->at_boundary())
+ cell->set_refine_flag();
+
+ tria->execute_refinement();
+ };
+
+ break;
+ }
+
+ case 4:
+ {
+ // refine once
+ tria->begin_active()->set_refine_flag();
+ tria->execute_refinement ();
+
+ Triangulation<dim>::active_cell_iterator cell, endc;
+ for (int i=0; i<(dim==2 ? 12 : 20); ++i)
+ {
+ int n_levels = tria->n_levels();
+ cell = tria->begin_active();
+ endc = tria->end();
+
+ for (; cell!=endc; ++cell)
+ {
+ double r = rand()*1.0/RAND_MAX,
+ weight = 1.*
+ (cell->level()*cell->level()) /
+ (n_levels*n_levels);
+
+ if (r <= 0.5*weight)
+ cell->set_refine_flag ();
+ };
+
+ tria->execute_refinement ();
+ };
+ break;
+ }
+ };
+
+ // output the grid
+ cout << " Writing grid..." << endl;
+ ofstream out(prm.get("Grid file"));
+ tria->print_gnuplot (out);
+
+
+
+
+ cout << " Distributing degrees of freedom..." << endl;
+ FEQuadratic<dim> fe;
+ dof->distribute_dofs (fe);
+
+ cout << " Renumbering degrees of freedom..." << endl;
+ dof->renumber_dofs (Cuthill_McKee, false);
+
+ dSMatrixStruct sparsity (dof->n_dofs(),
+ dof->max_couplings_between_dofs());
+
+
+ dof->make_sparsity_pattern (sparsity);
+ int unconstrained_bandwidth = sparsity.bandwidth();
+
+ cout << " Writing sparsity pattern... (This may take a while)" << endl;
+ ofstream sparsity_out (prm.get("Sparsity file"));
+ sparsity.print_gnuplot (sparsity_out);
+
+
+
+ // computing constraints
+ cout << " Computing constraints..." << endl;
+ ConstraintMatrix constraints;
+ dof->make_constraint_matrix (constraints);
+ constraints.condense (sparsity);
+
+ cout << " Writing condensed sparsity pattern... (This may take a while)" << endl;
+ ofstream c_sparsity_out (prm.get("Condensed sparsity file"));
+ sparsity.print_gnuplot (c_sparsity_out);
+
+
+// DataOut<dim> dataout;
+// dataout.attach_dof_handler (*dof);
+// ofstream o("o.inp");
+// dataout.write_ucd (o);
+
+ cout << endl
+ << " Total number of cells = " << tria->n_cells() << endl
+ << " Total number of active cells = " << tria->n_active_cells() << endl
+ << " Number of DoFs = " << dof->n_dofs() << endl
+ << " Number of constraints = " << constraints.n_constraints() << endl
+ << " Unconstrained matrix bandwidth= " << unconstrained_bandwidth << endl
+ << " Constrained matrix bandwidth = " << sparsity.bandwidth()
+ << endl << endl;
+};
+
+
+
+int main (int argc, char **argv) {
+ if (argc!=2)
+ {
+ cout << "Usage: grid_test parameterfile" << endl << endl;
+ return 1;
+ };
+
+ TestCases<2> tests;
+ class MultipleParameterLoop input_data; //gcc2.7 does nonsense, wait for gcc2.8
+
+ tests.declare_parameters(input_data);
+ input_data.read_input (argv[1]);
+ input_data.loop (tests);
+
+ return 0;
+};
+
--- /dev/null
+set Test run = { zoom in | ball | curved line | random }
+set Grid file = grid.{{ zoom_in | ball | curved_line | random }}
+set Sparsity file = sparsity.{{ zoom_in | ball | curved_line | random }}
+set Condensed sparsity file = sparsity.c.{{ zoom_in | ball | curved_line | random }}
\ No newline at end of file
--- /dev/null
+set size 0.721,1
+set data style lines
+set noxtics
+set noytics
+set noxzeroaxis
+set noyzeroaxis
+set nokey
+set term postscript eps
+
+!echo " Making <grid.zoom_in.eps>"
+set output "grid.zoom_in.eps"
+plot "grid.zoom_in"
+
+!echo " Making <grid.ball.eps>"
+set output "grid.ball.eps"
+plot "grid.ball"
+
+!echo " Making <grid.curved_line.eps>"
+set output "grid.curved_line.eps"
+plot "grid.curved_line"
+
+!echo " Making <grid.random.eps>"
+set output "grid.random.eps"
+plot "grid.random"
+
+
+
+set data style dots
+
+!echo " Making <sparsity.zoom_in.eps>"
+set output "sparsity.zoom_in.eps"
+plot "sparsity.zoom_in"
+
+!echo " Making <sparsity.ball.eps>"
+set output "sparsity.ball.eps"
+plot "sparsity.ball"
+
+!echo " Making <sparsity.curved_line.eps>"
+set output "sparsity.curved_line.eps"
+plot "sparsity.curved_line"
+
+!echo " Making <sparsity.random.eps>"
+set output "sparsity.random.eps"
+plot "sparsity.random"
+
+
+
+!echo " Making <sparsity.c.zoom_in.eps>"
+set output "sparsity.c.zoom_in.eps"
+plot "sparsity.c.zoom_in"
+
+!echo " Making <sparsity.c.ball.eps>"
+set output "sparsity.c.ball.eps"
+plot "sparsity.c.ball"
+
+!echo " Making <sparsity.c.curved_line.eps>"
+set output "sparsity.c.curved_line.eps"
+plot "sparsity.c.curved_line"
+
+!echo " Making <sparsity.c.random.eps>"
+set output "sparsity.c.random.eps"
+plot "sparsity.c.random"
--- /dev/null
+/* $Id$ */
+
+#include <grid/tria_iterator.h>
+#include <grid/tria.h>
+#include <cmath>
+#include <fstream.h>
+extern "C" {
+# include <stdlib.h>
+}
+
+
+// 1: continuous refinement of the unit square always in the middle
+// 2: refinement of the circle at the boundary
+// 2: refinement of a wiggled area at the boundary
+// 4: random refinement
+
+
+
+
+
+
+template <int dim>
+class Ball :
+ public StraightBoundary<dim> {
+ public:
+ virtual Point<dim> in_between (const PointArray &neighbors) const {
+ Point<dim> middle = StraightBoundary<dim>::in_between(neighbors);
+
+ for (int i=0; i<dim; ++i)
+ middle(i) -= .5;
+ middle /= (sqrt(middle.square())*sqrt(2));
+ for (int i=0; i<dim; ++i)
+ middle(i) += .5;
+
+ return middle;
+ };
+};
+
+
+template <int dim>
+class CurvedLine :
+ public StraightBoundary<dim> {
+ public:
+ virtual Point<dim> in_between (const PointArray &neighbors) const {
+ Point<dim> middle = StraightBoundary<dim>::in_between(neighbors);
+ double x=middle(0),
+ y=middle(1);
+
+ if (y<x)
+ if (y<1-x)
+ middle(1) = 0.04*sin(6*3.141592*middle(0));
+ else
+ middle(0) = 1+0.04*sin(6*3.141592*middle(1));
+
+ else
+ if (y<1-x)
+ middle(0) = 0.04*sin(6*3.141592*middle(1));
+ else
+ middle(1) = 1+0.04*sin(6*3.141592*middle(0));
+
+ return middle;
+ };
+};
+
+
+
+// since gcc can't resolve "test<2>()", do template parameter
+// passing this way...
+template <int dim>
+void test (const int test_case, const Point<dim> &) {
+ Triangulation<dim> tria;
+ tria.create_unit_hypercube();
+
+ if ((dim==1) && ((test_case==2) || (test_case==3)))
+ {
+ cout << "Impossible for this dimension." << endl;
+ return;
+ };
+
+
+ switch (test_case)
+ {
+ case 1:
+ {
+ // we want to log the
+ // refinement history
+// ofstream history ("mesh.history");
+
+ // refine first cell
+ tria.begin_active()->set_refine_flag();
+// tria.save_refine_flags (history);
+ tria.execute_refinement ();
+
+ // refine first active cell
+ // on coarsest level
+ tria.begin_active()->set_refine_flag ();
+// tria.save_refine_flags (history);
+ tria.execute_refinement ();
+
+ Triangulation<dim>::active_cell_iterator cell;
+ for (int i=0; i<17; ++i)
+ {
+ // refine the presently
+ // second last cell 17
+ // times
+ cell = tria.last_active(tria.n_levels()-1);
+ --cell;
+ cell->set_refine_flag ();
+// tria.save_refine_flags (history);
+ tria.execute_refinement ();
+ };
+
+// tria.refine_global (5);
+
+ break;
+ }
+
+ case 2:
+ case 3:
+ {
+ // set the boundary function
+ Ball<dim> ball;
+ CurvedLine<dim> curved_line;
+ if (test_case==2)
+ tria.set_boundary (&ball);
+ else
+ tria.set_boundary (&curved_line);
+
+ // refine once
+ tria.begin_active()->set_refine_flag();
+ tria.execute_refinement ();
+
+ Triangulation<dim>::active_cell_iterator cell, endc;
+ for (int i=0; i<7; ++i)
+ {
+ cell = tria.begin_active();
+ endc = tria.end();
+
+ // refine all
+ // boundary cells
+ for (; cell!=endc; ++cell)
+ if (cell->at_boundary())
+ cell->set_refine_flag();
+
+ tria.execute_refinement();
+ };
+
+ break;
+ }
+
+ case 4:
+ {
+ // refine once
+ tria.begin_active()->set_refine_flag();
+ tria.execute_refinement ();
+
+ Triangulation<dim>::active_cell_iterator cell, endc;
+ for (int i=0; i<(dim==2 ? 13 : 30); ++i)
+ {
+ int n_levels = tria.n_levels();
+ cell = tria.begin_active();
+ endc = tria.end();
+
+ for (; cell!=endc; ++cell)
+ {
+ double r = rand()*1.0/RAND_MAX,
+ weight = 1.*
+ (cell->level()*cell->level()) /
+ (n_levels*n_levels);
+
+ if (r <= 0.5*weight)
+ cell->set_refine_flag ();
+ };
+
+ tria.execute_refinement ();
+ };
+ break;
+ }
+ };
+
+
+
+ // output the grid
+ ofstream out("grid.1");
+ tria.print_gnuplot (out);
+
+ cout << " Total number of cells = " << tria.n_cells() << endl
+ << " Total number of active cells = " << tria.n_active_cells() << endl;
+};
+
+
+
+int main (int argc, char **argv) {
+ if (argc!=2)
+ {
+ cout << "Usage: grid_test testcase" << endl << endl
+ << "Testcases:" << endl
+ << " 1: continuous refinement of the unit square always in the middle" << endl
+ << " 2: refinement of the circle at the boundary" << endl
+ << " 3: refinement of a wiggled area at the boundary" << endl
+ << " 4: random refinement" << endl << endl;
+ return 1;
+ };
+
+ test (argv[1][0]-'0', Point<2>());
+
+ return 0;
+};
--- /dev/null
+set size 0.721,1
+set data style lines
+set term postscript eps
+
+set output "grid.1.eps"
+plot "grid.1"
+
+set output "grid.2.eps"
+plot "grid.2"
+
+set output "grid.3.eps"
+plot "grid.3"
+
+set output "grid.4.eps"
+plot "grid.4"
+
--- /dev/null
+/* $Id$ */
+
+
+#include <grid/dof.h>
+#include <grid/tria.h>
+#include <fe/fe_lib.h>
+#include <grid/tria_iterator.h>
+#include <grid/tria_accessor.h>
+#include "../../deal/dsmatrix.h>
+#include <grid/dof_constraints.h>
+#include <basic/data_io.h>
+#include <numerics/problem_base.h>
+#include <numerics/problem_assembler.h>
+
+#include <fstream.h>
+#include <cmath>
+extern "C" {
+# include <stdlib.h>
+}
+
+extern TriaActiveIterator<1,CellAccessor<1> > x;
+extern TriaActiveIterator<2,CellAccessor<2> > y;
+
+
+void main () {
+ Triangulation<1> tria;
+ DoFHandler<1> dof(tria);
+ FELinear<1> fe;
+ ProblemBase<1> problem(&tria, &dof);
+ Quadrature<1> q;
+
+ tria.create_hypercube();
+ dof.distribute_dofs (fe);
+ problem.assemble (q);
+};
--- /dev/null
+Here are some conventions for source code of the deal.II library:
+=================================================================
+
+1./ Functions which return the number of something (number of cells,
+ degrees of freedom, etc) should start with n_*
+
+2./ Function which set a bit or flag should start with set_* (an
+ unfortunate relict is the flag_refine function); functions which
+ clear bits of flags should be named clear_*
+
+3./ After each function, at least three empty lines are expected to
+ enable better readability. One empty line occurs in functions to
+ group blocks of code, two empty lines are not enough to distinguish
+ visibly enough.
+
+4./ Whenever an integer variable can only assume nonnegative values,
+ it has to be marked as unsigned int.
+
+5./ Whenever an argument will not be changed, it should be marked
+ const, even if it passed by value. This makes programs more readable
+ and lets the compiler issue warnings if such a parameter variable is
+ changed, which is often either involuntarily or poor style.
+
+6./ Whenever a function does not change any of the member variable of
+ the embedding class/object, it should be marked as const.
+
+7./ Each class has to have at least 200 pages of documentation ;-)
--- /dev/null
+# $Id$
+
+
+all: deal.II deal doc examples
+
+clean: lib-clean doc-clean examples-clean
+
+
+deal.II:
+ cd source ; make
+
+deal:
+ cd deal ; make
+
+doc:
+ cd doc ; make
+
+examples:
+ cd examples ; make
+
+
+lib-clean:
+ cd lib ; rm lib*
+
+doc-clean:
+ cd doc ; make clean
+
+examples-clean:
+ cd examples ; make clean
+
+
+
+.PHONY: all deal.II deal doc examples
+.PHONY: clean lib-clean doc-clean examples-clean
--- /dev/null
+Replace the declaration of vector<bool> in tria.h by something real
+ when gcc2.8 is available
+
+Make some functions in the iterators inlined, if the compiler
+ accepts them in gcc2.8
+
+Make the iterator functions (begin_*, end) templated with gcc2.8,
+ let the dimension then be templated (gcc2.8 chokes ober the return
+ type)
+
+Rewrite code like
+ int flagged_cells = 0;
+ for (; cell!=endc; ++cell)
+ if (cell->refine_flag_set())
+ ++flagged_cells;
+ using the STL count() operation with a member function predicate if
+ available.
+
+Change function args of DoFHandler::transfer_cell to
+ cell_iterators when "typename" keyword is available (i.e.
+ if gcc2.8 is available)
+
+Write monitors to control whether enough memory was allocated for
+ the vectors (i.e. after a process, whether size()==capacity()).
+ (for DoF)
+
+Write Triangulation::mesh_function.
+
+Unify CellAccessor<1> and <2> by renaming
+ LineAccessor<dim> -> SubstructAccessor<dim,1>
+ QuadAccessor<dim> -> SubstructAccessor<dim,2>
+ and deriving CellAccessor<dim> from SubstructAccessor<dim,dim>
+ Do the same with DoFLineAccessor and DoFQuadAccessor
+
+Add support for fast assemblage of mass matrices.
+
+
+
+
+DEAL:
+make dSMatrixStruct warn if max # of entries per row is overrun!
+
+why do loops in dFMatrix run backwards?
+
+Let an empty dfmatrix assume it has dimensions zero rather than one!
--- /dev/null
+/*---------------------------- dof_iterator.h ---------------------------*/
+/* $Id$ */
+#ifndef __dof_iterator_H
+#define __dof_iterator_H
+/*---------------------------- dof_iterator.h ---------------------------*/
+
+
+template <int dim> class Triangulation;
+template <int dim> class DoFHandler;
+template <class T> class vector;
+
+
+#include <grid/tria_accessor.h>
+
+
+
+
+/**
+ Define the basis for accessors to the degrees of freedom.
+ */
+template <int dim>
+class DoFAccessor {
+ public:
+ /**
+ * Constructor
+ */
+ DoFAccessor () : dof_handler(0) {
+ Assert (false, ExcInvalidObject());
+ };
+
+ /**
+ * This should be the default constructor.
+ */
+ DoFAccessor (DoFHandler<dim> *dof_handler) :
+ dof_handler(dof_handler) {};
+
+ /**
+ * Reset the DoF handler pointer.
+ */
+ void set_dof_handler (DoFHandler<dim> *dh) {
+ dof_handler = dh;
+ };
+
+ /**
+ * Exception for child classes
+ */
+ DeclException0 (ExcInvalidObject);
+
+ protected:
+ /**
+ * Store the address of the #DoFHandler# object
+ * to be accessed.
+ */
+ DoFHandler<dim> *dof_handler;
+};
+
+
+
+
+
+
+/**
+ Grant access to the degrees of freedom located on lines.
+ This class follows mainly the route laid out by the accessor library
+ declared in the triangulation library (\Ref{TriaAccessor}). It enables
+ the user to access the degrees of freedom on the lines (there are similar
+ versions for the DoFs on quads, etc), where the dimension of the underlying
+ triangulation does not really matter (i.e. this accessor works with the
+ lines in 1D-, 2D-, etc dimensions).
+
+
+ {\bf Usage}
+
+ The \Ref{DoFDimensionInfo} classes inherited by the \Ref{DoFHandler} classes
+ declare typedefs to iterators using the accessors declared in this class
+ hierarchy tree. Usage is best to happens through these typedefs, since they
+ are more secure to changes in the class naming and template interface as well
+ as they provide easier typing (much less complicated names!).
+
+
+ {\bf Notes about the class hierarchy structure}
+
+ The class hierarchy seems to be a bit confused here. The reason for this is
+ that we would really like to derive a #DoFLineAccessor# from a #LineAccessor#.
+ Unfortunately, we would run into problems, if we wanted a #DoFLineAccessor#
+ in one spatial dimension, in which case a line is also a cell. The traditional
+ solution would be to declare a #DoFCellAccessor<1># which is derived from
+ #DoFLineAccessor<1># and #CellAccessor<1># (the #DoFLineAccessor<dim># cannot
+ itself be derived from #CellAccessor<dim># since a line is not a cell
+ unless in one space dimension), but since a #DoFLineAccessor# and a
+ #CellAccessor# are both derived from #TriaAccessor#, we would have to make
+ the last derivation virtual.
+
+ Since we want to avoid virtual inheritance since this involves another
+ indirection in every member variable access, we chose another way: we
+ pass a second template parameter to a #DoFLineAccessor# which tells it
+ which class to be derived from: if we are in one spatial dimension, the
+ base class is to be #CellAccessor<1>#, in two or more dimensions it
+ is a #LineAccessor<dim>#, i.e. am accessor to lines without the missing
+ functionality needed for cells (neighbors, etc.).
+
+ This way we can declare a #DoFCellAccessor# in one dimension by deriving
+ from #DoFLineAccessor<1,CellAccessor<1> >#, thus getting the cell
+ functionality through the #DoFLineAccessor# instead of through a virtual
+ multiple inheritance of #DoFLineAccessor# and #CellAccessor<1>#.
+
+ The same concept is used with #DoFQuadAccessor# classes etc.
+ */
+template <int dim, class BaseClass>
+class DoFLineAccessor : public BaseClass, public DoFAccessor<dim> {
+ public:
+ /**
+ * Default constructor, unused thus
+ * not implemented.
+ */
+ DoFLineAccessor ();
+
+ /**
+ * Constructor. The #local_data#
+ * argument is assumed to be a pointer
+ * to a #DoFHandler<dim># object.
+ */
+ DoFLineAccessor (Triangulation<dim> *tria,
+ const int level,
+ const int index,
+ const void *local_data) :
+ BaseClass(tria,level,index),
+ DoFAccessor<dim> ((DoFHandler<dim>*)local_data) {};
+
+ /**
+ * Return the index of the #i#th degree
+ * of freedom of this line.
+ */
+ int dof_index (const unsigned int i) const;
+
+ /**
+ * Set the index of the #i#th degree
+ * of freedom of this line to #index#.
+ */
+ void set_dof_index (const unsigned int i, const int index) const;
+
+ /**
+ * Return the index of the #i#th degree
+ * on the #vertex#th vertex.
+ */
+ int vertex_dof_index (const unsigned int vertex,
+ const unsigned int i) const;
+
+ /**
+ * Set the index of the #i#th degree
+ * on the #vertex#th vertex to #index#.
+ */
+ void set_vertex_dof_index (const unsigned int vertex,
+ const unsigned int i,
+ const int index) const;
+
+ /**
+ * Return the #i#th child as a DoF line
+ * iterator. This function is needed since
+ * the child function of the base
+ * class returns a line accessor without
+ * access to the DoF data.
+ */
+ TriaIterator<dim,DoFLineAccessor<dim,BaseClass> > child (const unsigned int) const;
+
+ /**
+ * Implement the copy operator needed
+ * for the iterator classes.
+ */
+ void copy_from (const DoFLineAccessor<dim,BaseClass> &a);
+};
+
+
+
+
+
+
+/**
+ Grant access to the degrees of freedom located on quads.
+ @see DoFLineAccessor
+ */
+template <int dim, class BaseClass>
+class DoFQuadAccessor : public BaseClass, public DoFAccessor<dim> {
+ public:
+ /**
+ * Default constructor, unused thus
+ * not implemented.
+ */
+ DoFQuadAccessor ();
+
+ /**
+ * Constructor. The #local_data#
+ * argument is assumed to be a pointer
+ * to a #DoFHandler<dim># object.
+ */
+ DoFQuadAccessor (Triangulation<dim> *tria,
+ const int level,
+ const int index,
+ const void *local_data) :
+ BaseClass (tria,level,index),
+ DoFAccessor<dim> ((DoFHandler<dim>*)local_data) {};
+
+ /**
+ * Return the index of the #i#th degree
+ * of freedom of this quad.
+ */
+ int dof_index (const unsigned int i) const;
+
+ /**
+ * Set the index of the #i#th degree
+ * of freedom of this quad to #index#.
+ */
+ void set_dof_index (const unsigned int i, const int index) const;
+
+ /**
+ * Return the index of the #i#th degree
+ * on the #vertex#th vertex.
+ */
+ int vertex_dof_index (const unsigned int vertex,
+ const unsigned int i) const;
+
+ /**
+ * Set the index of the #i#th degree
+ * on the #vertex#th vertex to #index#.
+ */
+ void set_vertex_dof_index (const unsigned int vertex,
+ const unsigned int i,
+ const int index) const;
+
+ /**
+ * Return a pointer to the #i#th line
+ * bounding this #Quad#.
+ */
+ TriaIterator<dim,DoFLineAccessor<dim,LineAccessor<dim> > > line (const unsigned int i) const;
+
+ /**
+ * Return the #i#th child as a DoF quad
+ * iterator. This function is needed since
+ * the child function of the base
+ * class returns a quad accessor without
+ * access to the DoF data.
+ */
+ TriaIterator<dim,DoFQuadAccessor<dim,BaseClass> > child (const unsigned int) const;
+
+ /**
+ * Implement the copy operator needed
+ * for the iterator classes.
+ */
+ void copy_from (const DoFQuadAccessor<dim,BaseClass> &a);
+};
+
+
+
+
+extern DoFLineAccessor<1,LineAccessor<1> > __dummy215; // for gcc2.7
+extern DoFLineAccessor<1,CellAccessor<1> > __dummy216;
+extern DoFLineAccessor<2,LineAccessor<2> > __dummy217;
+extern DoFQuadAccessor<2,QuadAccessor<2> > __dummy218;
+extern DoFQuadAccessor<2,CellAccessor<2> > __dummy219;
+
+
+
+
+/**
+ Intermediate, "typedef"-class, not for public use.
+ */
+template <int dim>
+class DoFSubstructAccessor;
+
+
+
+/**
+ Intermediate, "typedef"-class, not for public use.
+
+ {\bf Rationale}
+
+ This class is only a wrapper class used to do kind of a typedef
+ with template parameters. This class and #DoFSubstructAccessor<2>#
+ wrap the following names:
+ \begin{verbatim}
+ DoFSubstructAccessor<1> := DoFLineAccessor<1,CellAccessor<1> >;
+ DoFSubstructAccessor<2> := DoFQuadAccessor<2,CellAccessor<2> >;
+ \end{verbatim}
+ We do this rather complex (and needless, provided C++ the needed constructs!)
+ class hierarchy manipulation, since this way we can declare and implement
+ the \Ref{DoFCellAccessor} dimension independent as an inheritance from
+ #DoFSubstructAccessor<dim>#. If we had not declared these
+ types, we would have to write two class declarations, one for
+ #DoFCellAccessor<1>#, derived from #DoFLineAccessor<1,CellAccessor<1> >#
+ and one for #DoFCellAccessor<2>#, derived from
+ #DoFQuadAccessor<2,CellAccessor<2> >#.
+ */
+class DoFSubstructAccessor<1> : public DoFLineAccessor<1,CellAccessor<1> > {
+ public:
+ /**
+ * Constructor
+ */
+ DoFSubstructAccessor (Triangulation<1> *tria,
+ const int level,
+ const int index,
+ const void *local_data) :
+ DoFLineAccessor<1,CellAccessor<1> > (tria,level,index,local_data) {};
+};
+
+
+
+/**
+ Intermediate, "typedef"-class, not for public use.
+ @see DoFSubstructAccessor<1>
+ */
+class DoFSubstructAccessor<2> : public DoFQuadAccessor<2,CellAccessor<2> > {
+ public:
+ /**
+ * Constructor
+ */
+ DoFSubstructAccessor (Triangulation<2> *tria,
+ const int level,
+ const int index,
+ const void *local_data) :
+ DoFQuadAccessor<2,CellAccessor<2> > (tria,level,index,local_data) {};
+};
+
+
+
+
+
+
+/**
+ Grant access to the degrees of freedom on a cell. In fact, since all
+ access to the degrees of freedom has been enabled by the classes
+ #DoFLineAccessor<1># and #DoFQuadAccessor<2># for the space dimension
+ one and two, respectively, this class only collects the pieces
+ together by deriving from the appropriate #DoF*Accessor# and the
+ right #CellAccessor<dim># and finally adding two functions which give
+ access to the neighbors and children as #DoFCellAccessor# objects
+ rather than #CellAccessor# objects (the latter function was inherited
+ from the #CellAccessor<dim># class).
+ */
+template <int dim>
+class DoFCellAccessor : public DoFSubstructAccessor<dim> {
+ public:
+ /**
+ * Constructor
+ */
+ DoFCellAccessor (Triangulation<dim> *tria,
+ const int level,
+ const int index,
+ const void *local_data) :
+ DoFSubstructAccessor<dim> (tria,level,index,local_data) {};
+
+ /**
+ * Return the #i#th neighbor as a DoF cell
+ * iterator. This function is needed since
+ * the neighbor function of the base
+ * class returns a cell accessor without
+ * access to the DoF data.
+ */
+ TriaIterator<dim,DoFCellAccessor<dim> > neighbor (const unsigned int) const;
+
+ /**
+ * Return the #i#th child as a DoF cell
+ * iterator. This function is needed since
+ * the child function of the base
+ * class returns a cell accessor without
+ * access to the DoF data.
+ */
+ TriaIterator<dim,DoFCellAccessor<dim> > child (const unsigned int) const;
+
+ /**
+ * Return the indices of the dofs of this
+ * cell in the standard ordering: dofs
+ * on vertex 0, dofs on vertex 1, etc,
+ * dofs on line 0, dofs on line 1, etc,
+ * dofs on quad 0, etc.
+ *
+ * The dof indices are appended to the end
+ * of the vector. It is not assumed that
+ * the vector be empty beforehand.
+ */
+ void dof_indices (vector<int> &dof_indices) const;
+};
+
+
+
+
+
+
+
+extern DoFCellAccessor<1> __dummy17; //do this to calm down gcc2.7.. wait for gcc2.8
+extern DoFCellAccessor<2> __dummy18;
+
+
+
+/*---------------------------- dof_iterator.h ---------------------------*/
+/* end of #ifndef __dof_iterator_H */
+#endif
+/*---------------------------- dof_iterator.h ---------------------------*/
--- /dev/null
+/*---------------------------- dof_constraints.h ---------------------------*/
+/* $Id$ */
+#ifndef __dof_constraints_H
+#define __dof_constraints_H
+/*---------------------------- dof_constraints.h ---------------------------*/
+
+
+#include <vector.h>
+#include <pair.h>
+#include <basic/exceptions.h>
+
+
+
+class ostream;
+class dSMatrixStruct;
+
+
+/**
+ This class represents the matrix denoting the distribution of the degrees
+ of freedom of hanging nodes.
+
+ The matrix is organized in lines (rows), but only those lines are stored
+ where constraints are present. Lines where only one entry (identity) is
+ present are not stored if not explicitely inserted.
+
+ Constraint matrices are used to handle hanging nodes and other constrained
+ degrees of freedom. When building the global system matrix and the right
+ hand sides, you normally build them without taking care of the constraints,
+ purely on a topological base, i.e. by a loop over cells. In order to do
+ actual calculations, you have to 'condense' these matrices: eliminate
+ constrained degrees of freedom and distribute the appropriate values to
+ the unconstrained dofs. This changes the sparsity pattern of the sparse
+ matrices used in finite element calculations und is thus a quite expensive
+ operation.
+
+ Condensation is done in four steps: first the large matrix sparsity pattern
+ is created (e.g. using #DoFHandler::create_sparsity_pattern#), then the
+ sparsity pattern of the condensed matrix is made out of the large sparsity
+ pattern and the constraints. After that the global matrix is assembled and
+ finally condensed. To do these steps, you have (at least) two possibilities:
+ \begin{itemize}
+ \item Use two different sparsity patterns and two different matrices: you
+ may eliminate the lines and rows connected with a constraint and create
+ a totally new sparsity pattern and a new system matrix. This has the
+ advantage that the resulting system of equations is free from artifacts
+ of the condensation process and is therefore faster in the solution process
+ since no unnecessary multiplications occur (see below). However, there are
+ two major drawbacks: keeping two matrices at the same time can be quite
+ unacceptable in many cases, since these matrices may be several 10 or even
+ 100 MB large. Secondly, the condensation process is quite expensive, since
+ {\it all} entries of the matrix have to be copied, not only those which are
+ subject to constraints.
+
+ \item Use only one sparsity pattern and one matrix: doing it this way, the
+ condense functions add nonzero entries to the sparsity pattern of the
+ large matrix (with constrained nodes in it) where the condensation process
+ of the matrix will create additional nonzero elements. In the condensation
+ process itself, lines and rows subject to constraints are distributed to
+ the lines and rows of unconstrained nodes. The constrained lines remain in
+ place, however, unlike in the first possibility described above. In order
+ not to disturb the solution process, these lines and rows are filled with
+ zeros and identity on the main diagonal; the appropriate value in the right
+ hand sides is set to zero. This way, the constrained node will always get
+ the value zero upon solution of the equation system and will not couple to
+ other nodes any more.
+
+ This method has the advantage that only one matrix and sparsity pattern is
+ needed thus using less memory. Additionally, the condensation process is
+ less expensive, since not all but only constrained values in the matrix
+ have to be copied. On the other hand, the solution process will take a bit
+ longer, since matrix vector multiplications will incur multiplications
+ with zeroes in the lines subject to constraints. Additionally, the vector
+ size is larger than in the first possibility, resulting in more memory
+ consumption for those iterative solution methods using a larger number of
+ auxiliary vectors (e.g. methods using explicite orthogonalization
+ procedures).
+ \end{verbatim}
+
+ Usually, the second way is chosen since memory consumption upon construction
+ of a second matrix rules out the first possibility.
+
+ This class provides two sets of #condense# functions: those taking two
+ arguments refer to the first possibility above, those taking only one do
+ their job in-place and refer to the second possibility.
+ */
+class ConstraintMatrix {
+ public:
+ /**
+ * Constructor
+ */
+ ConstraintMatrix ();
+
+
+ /**
+ * Add a new line to the matrix.
+ */
+ void add_line (const unsigned int line);
+
+ /**
+ * Add an entry to a given line. The list
+ * of lines is searched from the back to
+ * the front, so clever programming would
+ * add a new line (which is pushed to the
+ * back) and immediately afterwards fill
+ * the entries of that line. This way, no
+ * expensive searching is needed.
+ */
+ void add_entry (const unsigned int line,
+ const unsigned int column,
+ const double value);
+
+ /**
+ * Close the filling of entries. Since the
+ * lines of a matrix of this type are
+ * usually filled in an arbitrary order and
+ * since we do not want to use associative
+ * constainers to store the lines, we need
+ * to sort the lines and within the lines
+ * the columns before usage of the matrix.
+ * This is done through this function.
+ *
+ * After closing, no more entries are
+ * accepted.
+ */
+ void close ();
+
+ /**
+ * Clear all entries of this matrix. Reset
+ * the flag determining whether new entries
+ * are accepted or not.
+ *
+ * This function may be called also on
+ * objects which are empty or already
+ * cleared.
+ */
+ void clear ();
+
+ /**
+ * Return number of constraints stored in
+ * this matrix.
+ */
+ unsigned int n_constraints () const;
+
+ /**
+ * Condense a given sparsity pattern. This
+ * function assumes the uncondensed
+ * matrix struct to be compressed and the
+ * to be filled one to be empty. The
+ * condensed structure is compressed
+ * afterwards.
+ *
+ * The constraint matrix object must be
+ * closed to call this function.
+ */
+ void condense (const dSMatrixStruct &uncondensed,
+ dSMatrixStruct &condensed) const;
+
+
+ /**
+ * This function does much the same as
+ * the above one, except that it condenses
+ * the matrix struct 'in-place'. It does
+ * not remove nonzero entries from the
+ * matrix but adds those needed for the
+ * process of distribution of the
+ * constrained degrees of freedom.
+ *
+ * Since this function adds new nonzero
+ * entries to the sparsity pattern, the
+ * argument must not be compressed. However
+ * the constraint matrix must be closed.
+ * The matrix struct is compressed at the
+ * end of the function.
+ */
+ void condense (dSMatrixStruct &sparsity) const;
+
+ /**
+ * Print the constraint lines. Mainly for
+ * debugging purposes.
+ *
+ * This function writes out all entries
+ * in the constraint matrix lines with
+ * their value in the form
+ * #row col : value#. Unconstrained lines
+ * containing only one identity entry are
+ * not stored in this object and are not
+ * printed.
+ */
+ void print (ostream &) const;
+
+
+ /**
+ * Exception
+ */
+ DeclException1 (ExcLineExists,
+ unsigned int,
+ << "The lines " << arg1
+ << " which is to be created already exists.");
+ /**
+ * Exception
+ */
+ DeclException0 (ExcMatrixIsClosed);
+ /**
+ * Exception
+ */
+ DeclException0 (ExcMatrixNotClosed);
+ /**
+ * Exception
+ */
+ DeclException1 (ExcLineInexistant,
+ unsigned int,
+ << "The specified line " << arg1
+ << " does not exist.");
+ /**
+ * Exception
+ */
+ DeclException0 (ExcMatrixNotSquare);
+
+
+ private:
+
+ /**
+ * This class represents one line of a
+ * constraint matrix.
+ */
+ struct ConstraintLine {
+ /**
+ * Number of this line. Since only very
+ * few lines are stored, we can not
+ * assume a specific order and have
+ * to store the line number explicitely.
+ */
+ unsigned int line;
+
+ /**
+ * Row numbers and values of the entries
+ * in this line.
+ *
+ * For the reason why we use a vector
+ * instead of a map and the consequences
+ * thereof, the same applies as what is
+ * said for #ConstraintMatrix::lines#.
+ */
+ vector<pair<unsigned int,double> > entries;
+
+ /**
+ * This operator is a bit weird and
+ * unintuitive: it compares the line
+ * numbers of two lines. We need this
+ * to sort the lines; in fact we could
+ * do this using a comparison predicate.
+ * However, gcc2.7 has problems with
+ * type unification for the #ptr_fun#
+ * function, so that the creation of a
+ * predicate is a bit complicated. This
+ * way, it is easier, albeit unintuitive
+ * since two lines really have no
+ * god-given order relation.
+ */
+ bool operator < (const ConstraintLine &) const;
+ };
+
+ /**
+ * Store the lines of the matrix.
+ * Entries are usually
+ * appended in an arbitrary order and
+ * insertion into a vector is done best
+ * at the end, so the order is
+ * unspecified after all entries are
+ * inserted. Sorting of the entries takes
+ * place when calling the #close()# function.
+ *
+ * We could, instead of using a vector, use
+ * an associative array, like a map to
+ * store the lines. This, however, would
+ * mean a much more fractioned heap since it
+ * allocates many small objects, ans would
+ * additionally make usage of this matrix
+ * much slower.
+ */
+ vector<ConstraintLine> lines;
+
+ /**
+ * Store whether the arrays are sorted.
+ * If so, no new entries can be added.
+ */
+ bool sorted;
+};
+
+
+
+
+/*---------------------------- dof_constraints.h ---------------------------*/
+/* end of #ifndef __dof_constraints_H */
+#endif
+/*---------------------------- dof_constraints.h ---------------------------*/
--- /dev/null
+/*---------------------------- dof.h ---------------------------*/
+/* $Id$ */
+#ifndef __dof_H
+#define __dof_H
+/*---------------------------- dof.h ---------------------------*/
+
+#include <vector.h>
+#include <fe/fe.h>
+#include <basic/exceptions.h>
+
+
+
+
+template <int dim> class TriaAccessor;
+template <int dim> class LineAccessor;
+template <int dim> class QuadAccessor;
+template <int dim> class CellAccessor;
+
+template <int dim, class BaseClass> class DoFLineAccessor;
+template <int dim, class BaseClass> class DoFQuadAccessor;
+template <int dim> class DoFCellAccessor;
+
+
+template <int dim, class Accessor> class TriaRawIterator;
+template <int dim, class Accessor> class TriaIterator;
+template <int dim, class Accessor> class TriaActiveIterator;
+
+template <int dim> class Triangulation;
+
+class dSMatrix;
+class dSMatrixStruct;
+class ConstraintMatrix;
+
+
+
+
+/**
+ Store the indices of the degrees of freedom which are located on the lines.
+ Declare it to have a template parameter, but do not actually declare
+ other types than those explicitely instantiated.
+ */
+template <int N>
+class DoFLevel;
+
+
+
+
+
+/**
+ Store the indices of the degrees of freedom which are located on the lines.
+
+ {\bf Information for all #DoFLevel# classes}
+
+ The #DoFLevel<N># classes
+ store the global indices of the degrees of freedom for each cell on a
+ certain level. The index or number of a degree of freedom is the zero-based
+ index of the according value in the solution vector and the row and column
+ index in the global matrix or the multigrid matrix for this level. These
+ indices refer to the unconstrained vectors and matrices, where we have not
+ taken account of the constraints introduced by hanging nodes. If more than
+ one value corresponds to one basis function, for example for vector equations
+ where the solution is vector valued and thus has several degrees of freedom
+ for each basis function, we nonetheless store only one index. This can then
+ be viewed as the index into a block vector, where each block contains the
+ different values according to a degree of freedom. It is left to the derived
+ classes, whether the values in a block are stored consecutively or distributed
+ (e.g. if the solution function is $u=(u_1, u_2)$, we could store the values
+ in the solution vector like
+ $\ldots, u_1^m, u_2^m, u_1^{m+1}, u_2^{m+1},\ldots$ with $m$ denoting the
+ $m$th basis function, or $\ldots, u_1^m, u_1^{m+1}, u_1^{m+2}, \ldots,
+ u_2^m, u_2^{m+1}, u_2^{m+2}, \ldots$, respectively). Likewise, the
+ constraint matrix returned by #DoFHandler::make_constraint_matrix ()# is then
+ to be understood as a block matrix.
+
+ The storage format of the degrees of freedom indices (short: DoF indices) is
+ somewhat like a mirror of the data structures of the triangulation classes.
+ There is a hierarchy of #DoFLevel<dim># classes for the different dimensions
+ which have objects named #line_dofs#, #quad_dofs# and so on, in which the
+ indices of DoFs located on lines and quads, respectively, are stored. The
+ indices are stored levelwise. The layout in
+ these arrays is as follows: if for a selected finite element (use
+ #DoFHandler::distribute_dofs()# to select a finite element) the number of
+ DoFs on each line (without those in the vertices) is #N#, then the length
+ of the #line_dofs# array is #N# times the number of lines on this level. The
+ DoF indices for the #i#th line are at the positions #N*i...(N+1)*i-1#.
+
+ The DoF indices for vertices are not stored this way, since they need
+ different treatment in multigrid environments. If no multigrid is used, the
+ indices are stored in the #vertex_dofs# array of the #DoFHandler# class.
+ */
+class DoFLevel<1> {
+ public:
+ /**
+ * Store the global indices of the degrees
+ * of freedom. See \Ref{DoFLevel} for
+ * detailed information.
+ */
+ vector<int> line_dofs;
+};
+
+
+
+
+/**
+ Store the indices of the degrees of freedom which are located on quads.
+ See \Ref{DoFLevel<1>} for more information.
+ */
+class DoFLevel<2> : public DoFLevel<1> {
+ public:
+ /**
+ * Store the global indices of the degrees
+ * of freedom. See \Ref{DoFLevel} for
+ * detailed information.
+ */
+ vector<int> quad_dofs;
+};
+
+
+
+
+
+
+/**
+ Define some types which differ between the dimensions. This class
+ is analogous to the \Ref{TriaDimensionInfo} class hierarchy.
+
+ @see DoFDimensionInfo<1>
+ @see DoFDimensionInfo<2>
+ */
+template <int dim>
+class DoFDimensionInfo;
+
+
+
+
+
+/**
+ Define some types for the DoF handling in one dimension.
+
+ The types have the same meaning as those declared in \Ref{TriaDimensionInfo<2>}.
+ */
+class DoFDimensionInfo<1> {
+ public:
+ typedef TriaRawIterator<1,DoFCellAccessor<1> > raw_line_iterator;
+ typedef TriaIterator<1,DoFCellAccessor<1> > line_iterator;
+ typedef TriaActiveIterator<1,DoFCellAccessor<1> > active_line_iterator;
+
+ typedef void * raw_quad_iterator;
+ typedef void * quad_iterator;
+ typedef void * active_quad_iterator;
+
+ typedef raw_line_iterator raw_cell_iterator;
+ typedef line_iterator cell_iterator;
+ typedef active_line_iterator active_cell_iterator;
+};
+
+
+
+
+
+
+/**
+ Define some types for the DoF handling in two dimensions.
+
+ The types have the same meaning as those declared in \Ref{TriaDimensionInfo<2>}.
+ */
+class DoFDimensionInfo<2> {
+ public:
+ typedef TriaRawIterator<2,DoFLineAccessor<2,LineAccessor<2> > > raw_line_iterator;
+ typedef TriaIterator<2,DoFLineAccessor<2,LineAccessor<2> > > line_iterator;
+ typedef TriaActiveIterator<2,DoFLineAccessor<2,LineAccessor<2> > > active_line_iterator;
+
+ typedef TriaRawIterator<2,DoFCellAccessor<2> > raw_quad_iterator;
+ typedef TriaIterator<2,DoFCellAccessor<2> > quad_iterator;
+ typedef TriaActiveIterator<2,DoFCellAccessor<2> > active_quad_iterator;
+
+ typedef raw_quad_iterator raw_cell_iterator;
+ typedef quad_iterator cell_iterator;
+ typedef active_quad_iterator active_cell_iterator;
+};
+
+
+
+
+
+
+/**
+ Give names to the different possibilities of renumbering the degrees
+ of freedom.
+
+ \begin{itemize}
+ \item #Cuthill_McKee# and #reverse_Cuthill_McKee# traverse the triangulation
+ in a diagonal, advancing front like method and produce matrices with an
+ almost minimal bandwidth.
+ \item #reverse_Cuthill_McKey# does the same thing, but numbers the dofs in
+ the reverse order.
+ \end{itemize}
+
+ For a description of the algorithms see the book of Schwarz (H.R.Scharz:
+ Methode der finiten Elemente).
+ */
+enum RenumberingMethod {
+ Cuthill_McKee,
+ reverse_Cuthill_McKee
+};
+
+
+
+
+
+/**
+ Manage the distribution and numbering of the degrees of freedom for
+ non-multigrid algorithms.
+
+ We store a list of numbers for each cells
+ denoting the mapping between the degrees of freedom on this cell
+ and the global number of this degree of freedom; the number of a
+ degree of freedom lying on the interface of two cells is thus stored
+ twice, but is the same. The numbers refer to the unconstrained
+ matrices and vectors. The layout of storage of these indices is
+ described in the \Ref{DoFLevel} class documentation.
+
+ Additionally, the DoFHandler is able to generate the condensation
+ matrix which connects constrained and unconstrained matrices and
+ vectors.
+
+ Finally it offers a starting point for the assemblage of the matrices
+ by offering #begin()# and #end()# functions which return iterators
+ to walk on the DoF structures as well as the triangulation data.
+
+
+ {\bf Distribution of degrees of freedom}
+
+ The degrees of freedom (`dofs') are distributed on the given triangulation
+ by the function #distribute_dofs()#. It gets passed a finite element object
+ describing how many degrees of freedom are located on vertices, lines, etc.
+ It traverses the triangulation cell by cell and numbers the dofs of that
+ cell if not yet numbered. For non-multigrid algorithms, only active cells
+ are considered.
+
+ Since the triangulation is traversed starting with the cells of the coarsest
+ active level and going to more refined levels, the lowest numbers for dofs
+ are given to the largest cells as well as their bounding lines and vertices,
+ with the dofs of more refined cells getting higher numbers.
+
+ This numbering implies very large bandwiths of the resulting matrices and
+ is thus vastly suboptimal for some solution algorithms. For this reason,
+ the #DoFHandler# class offers the function #renumber_dofs# which reorders
+ the dof numbering according to some scheme. Presently available are the
+ Cuthill-McKey (CM) and the Reverse Cuthill-McKey algorithm. These algorithms
+ have one major drawback: they require a good starting point, i.e. the degree
+ of freedom index afterwards to be numbered zero. This can thus be given by
+ the user, e.g. by exploiting knowledge of the actual topology of the
+ domain. It is also possible to given several starting indices, which may
+ be used to simulate a simple upstream numbering (by giving the inflow
+ dofs as starting values) or to make preconditioning faster (by letting
+ the dirichlet boundary indices be starting points).
+
+ If no starting index is given, one is chosen by the program, namely one
+ with the smallest coordination number (the coordination number is the
+ number of other dofs this dof couples with). This dof is usually located
+ on the boundary of the domain. There is, however, large ambiguity in this
+ when using the hierarchical meshes used in this library, since in most
+ cases the computational domain is not approximated by tilting and deforming
+ elements and by plugging together variable numbers of elements at vertices,
+ but rather by hierarchical refinement. There is therefore a large number
+ of dofs with equal coordination numbers. The renumbering algorithms will
+ therefore not give optimal results.
+
+ In the book of Schwarz (H.R.Schwarz: Methode der finiten Elemente), it is
+ advised to test many starting points, if possible all with the smallest
+ coordination number and also those with slightly higher numbers. However,
+ this seems only possible for meshes with at most several dozen or a few
+ hundred elements found in small engineering problems of the early 1980s
+ (the second edition was published in 1984), but certainly not with those
+ used in this library, featuring several 10,000 to a few 100,000 elements.
+
+ On the other hand, the need to reduce the bandwidth has decreased since
+ with the mentioned number of cells, only iterative solution methods are
+ able to solve the resulting matrix systems. These, however, are not so
+ demanding with respect to the bandwidth as direct solvers used for
+ smaller problems. Things like upstream numbering become much more important
+ in recent times, so the suboptimality of the renumbering algorithms is
+ not that important any more.
+
+
+ {\bf Implementation of renumbering schemes}
+
+ The renumbering algorithms need quite a lot of memory, since they have
+ to store for each dof with which other dofs it couples. This is done
+ using a #dSMatrixStruct# object used to store the sparsity pattern. It
+ is not useful for the user to do anything between distributing the dofs
+ and renumbering, i.e. the calls to #DoFHandler::distribute_dofs# and
+ #DoFHandler::renumber_dofs# should follow each other immediately. If
+ you try to create a sparsity pattern or anything else in between, these
+ will be invalid afterwards.
+
+ The renumbering may take care of dof-to-dof couplings only induced by
+ eliminating constraints. In addition to the memory consumption mentioned
+ above, this also takes quite some computational time, but it may be
+ switched of upon calling the #renumber_dofs# function. This will then
+ give inferior results, since knots in the graph (representing dofs)
+ are not found to be neighbors even if they would be after condensation.
+
+ The renumbering algorithms work on a purely algebraic basis, due to the
+ isomorphism between the graph theoretical groundwork underlying the
+ algorithms and binary matrices (matrices of which the entries are binary
+ values) represented by the sparsity patterns. In special, the algorithms
+ do not try to exploit topological knowledge (e.g. corner detection) to
+ find appropriate starting points. This way, however, they work in
+ arbitrary space dimension.
+
+ If you want to give starting points, you may give a list of dof indices
+ which will form the first step of the renumbering. The dofs of the list
+ will be consecutively numbered starting with zero, i.e. this list is not
+ renumbered according to the coordination number of the nodes. Indices not
+ in the allowed range are deleted. If no index is allowed, the algorithm
+ will search for its own starting point.
+
+
+ {\bf Results of renumbering}
+
+ The renumbering schemes mentioned above do not lead to optimal results.
+ However, after all there is no algorithm that accomplishes this within
+ reasonable time. There are situations where the lack of optimality even
+ leads to worse results than with the original, crude, levelwise numering
+ scheme; one of these examples is a mesh of four cells of which always
+ those cells are refined which are neighbors to the center (you may call
+ this mesh a `zoom in' mesh). In one such example the bandwidth was
+ increased by about 50 per cent.
+
+ In most other cases, the bandwith is reduced significantly. The reduction
+ is the better the less structured the grid is. With one grid where the
+ cells were refined according to a random driven algorithm, the bandwidth
+ was reduced by a factor of six.
+
+ Using the constraint information usually leads to reductions in bandwidth
+ of 10 or 20 per cent, but may for some very unstructured grids also lead
+ to an increase. You have to weigh the decrease in your case with the time
+ spent to use the constraint information, which usually is several times
+ longer than the `pure' renumbering algorithm.
+
+ In almost all cases, the renumbering scheme finds a corner to start with.
+ Since there is more than one corner in most grids and since even an
+ interior degree of freedom may be a better starting point, giving the
+ starting point by the user may be a viable way if you have a simple
+ scheme to derive a suitable point (e.g. by successively taking the
+ third child of the cell top left of the coarsest level, taking its
+ third vertex and the dof index thereof, if you want the top left corner
+ vertex). If you do not know beforehand what your grid will look like
+ (e.g. when using adaptive algorithms), searching a best starting point
+ may be difficult, however, and in many cases will not justify the effort.
+
+ {\bf Data transfer between grids}
+
+ The #DoFHandler# class offers two functions #make_transfer_matrix# which create
+ a matrix to transform the data of one grid to another. The functions assumes the
+ coarsest mesh of the two grids to be the same. However there are few ways to
+ check this (only the number of cells on the coarsest grid is compared). Also,
+ the selected finite element type of the two degree of freedom handler objects
+ must be the same.
+
+ The algorithm goes recursively from the coarse mesh cells to their children
+ until the grids differ at this level. It then tries to prolong or restrict the
+ old cell(s) to the new cell(s) and makes up a matrix of these prolongations and
+ restrictions. This matrix multiplied with a vector on the old grid yields an
+ approximation of the projection of the function on the old grid to the new one.
+
+ Building and using the transfer matrix is usually a quite expensive operation,
+ since we have to perform two runs over all cells (one for building the sparsity
+ structure, one to build the entries) and because of the memory consumption.
+ It may, however, pay if you have many
+ equations, since then the entries in the matrix can be considered as block
+ entries which are then applied to all function values at a given degree of
+ freedom.
+
+ To build the matrix, you have to call first
+ #make_transfer_matrix (old_dof_object, sparsity_pattern);#, then create a
+ sparse matrix out of this pattern, e.g. by #dSMatrix m(sparsity_pattern);#
+ and finally give this to the second run:
+ #make_transfer_matrix (old_dof_object, m);#. The spasity pattern created
+ by the first run is automatically compressed.
+
+ When creating the #dSMatrixStruct# sparsity pattern, you have to give the
+ dimension and the maximum number of entries per row. Obviously the image
+ dimension is the number of dofs on the new grid (you can get this using the
+ #n_dofs()# function), while the range dimension is the number of dofs on the
+ old grid. The maximum number of entries per row is determined by the maximum
+ number of levels $d$ which we have to cross upon transferring from one cell to
+ another (presently, transfer of one cell is only possible for #d=0,1#, i.e.
+ the two cells match or one is refined once more than the other, the
+ number of degrees of freedom per per vertex $d_v$, those on lines $d_l$, those
+ on quads $d_q$ and the number of subcells a cell is
+ refined to, which is $2**dim$. The maximum number of entries per row in one
+ dimension is then given by $(2*d_l+d_v)*2+1$ if $d=1$. For example, a one
+ dimensional linear element would need two entries per row.
+ In two dimensions, the maxmimum number is $(4*d_q+12*d_l+5*d_v)*4+1$ if $d=1$.
+ You can get these numbers by drawing little pictures and counting, there is
+ no mystique behind this. You can also get the right number by calling the
+ #max_transfer_entries (max_level_difference)# function. The actual number
+ depends on the finite element selected and may be much less, especially in
+ higher dimensions.
+
+ If you do not have multiple equations and do not really use the matrix but still
+ have to transfer an arbitrary number of vectors to transfer, you can use the
+ #transfer()# function, which is able to transfer any number of vectors in only
+ one loop over all cells and without the memory consumption of the matrix. The
+ matrix seems only useful when trying to transfer whole matrices instead of
+ rebuilding them on the new grid.
+
+ @author Wolfgang Bangerth, February 1998
+ */
+template <int dim>
+class DoFHandler : public DoFDimensionInfo<dim> {
+ public:
+ /**
+ * Constructor. Take #tria# as the
+ * triangulation to work on.
+ */
+ DoFHandler (Triangulation<dim> *tria);
+
+ /**
+ * Destructor
+ */
+ ~DoFHandler ();
+
+ /**
+ * Go through the triangulation and
+ * distribute the degrees of freedoms
+ * needed for the given finite element
+ * according to the given distribution
+ * method.
+ *
+ * A copy of the transferred finite
+ * element is stored.
+ *
+ * This function uses the user flags of the
+ * triangulation object, so make sure you
+ * don't need them after calling this
+ * function, or if so store them.
+ */
+ void distribute_dofs (const FiniteElement<dim> &);
+
+ /**
+ * Renumber the degrees of freedom according
+ * to the given scheme, eventually using
+ * constraint information and the given
+ * starting points. The starting points
+ * default to an empty list, the use of
+ * constraint information defaults to
+ * false.
+ *
+ * See the general documentation of this
+ * class for more details.
+ */
+ void renumber_dofs (const RenumberingMethod method,
+ bool use_constraints = false,
+ const vector<int> &starting_points = vector<int>());
+
+ /**
+ * Make up the constraint matrix which
+ * is used to condensate the global
+ * system matrices and to prolong
+ * the solution vectors from the true
+ * degrees of freedom also to the
+ * constraint nodes.
+ *
+ * Since this method does not make sense in
+ * one dimension, the functions returns
+ * immediately after clearing the
+ * constraint matrix.
+ *
+ * For more than one dimension, the matrix
+ * is cleared before usage.
+ *
+ * To condense a given sparsity pattern,
+ * use #ConstraintMatrix::condense#.
+ */
+ void make_constraint_matrix (ConstraintMatrix &) const;
+
+
+ /**
+ * Write the sparsity structure of the
+ * full matrix (including constrained
+ * degrees of freedom) into the
+ * matrix structure. The sparsity
+ * pattern is not compressed, since if
+ * you want to call
+ * #ConstraintMatrix::condense(1)#
+ * afterwards, new entries have to be
+ * added. However, if you want to call
+ * #ConstraintMatrix::condense(1)#, you
+ * have to compress the matrix yourself,
+ * using #dSMatrixStruct::compress()#.
+ */
+ void make_sparsity_pattern (dSMatrixStruct &) const;
+
+ /**
+ * Make up the transfer matrix which
+ * transforms the data vectors from one
+ * triangulation to the present one.
+ * You have to pass references to the old
+ * dof handler object and to a matrix
+ * sparsity object. This function therefore
+ * only makes up the sparsity pattern.
+ *
+ * The matrix given sparsity pattern is
+ * compressed at the end.
+ *
+ * In the matrix, row indices belong to
+ * new dof numbers, column indices to the
+ * ones on the old grid. Therefore,
+ * multiplying this matrix by a vector
+ * of the old grid yields the vector on
+ * the new one.
+ *
+ * For more details see the general
+ * documentation for this class.
+ */
+ void make_transfer_matrix (const DoFHandler<dim> &transfer_from,
+ dSMatrixStruct &transfer_pattern) const;
+
+ /**
+ * Make up the transfer matrix which
+ * transforms the data vectors from one
+ * triangulation to the present one.
+ * You have to pass references to the old
+ * dof handler object and to a matrix
+ * object. This function therefore
+ * builds the matrix itself
+ *
+ * The matrix object should be
+ * associated with the sparsity pattern
+ * constructed by the other
+ * #make_transfer_matrix# object.
+ *
+ * For more details see the general
+ * documentation for this class.
+ */
+ void make_transfer_matrix (const DoFHandler<dim> &transfer_from,
+ dSMatrix &transfer_matrix) const;
+
+ /**
+ * Return the maximum number of
+ * degrees of freedom a degree of freedom
+ * in the given triangulation with the
+ * given finite element may couple with.
+ * This is the maximum number of entries
+ * per line in the system matrix; this
+ * information can therefore be used upon
+ * construction of the #dSMatrixStruct#
+ * object.
+ *
+ * The returned number is not really the
+ * maximum number but an estimate based
+ * on the finite element and the maximum
+ * number of cells meeting at a vertex.
+ * The number holds for the constrained
+ * matrix also.
+ */
+ unsigned int max_couplings_between_dofs () const;
+
+ /**
+ * Return the maximum number of entries
+ * a row in a transfer matrix may contain
+ * if any two cells of which the dofs are
+ * to be transferred differ in refinement
+ * level at most by #max_level_diff#.
+ * It is assumed that the finite element
+ * selected by the last call to
+ * #distribute_dofs# is used also for
+ * the transfer process.
+ */
+ unsigned int max_transfer_entries (const unsigned int max_level_diff) const;
+
+ /**
+ * @name Cell iterator functions
+ */
+ /*@{*/
+ /**
+ * Return iterator to the first cell, used
+ * or not, on level #level#. If a level
+ * has no cells, a past-the-end iterator
+ * is returned.
+ *
+ * This function calls #begin_raw_line#
+ * in 1D and #begin_raw_quad# in 2D.
+ */
+ raw_cell_iterator begin_raw (const unsigned int level = 0) const;
+
+ /**
+ * Return iterator to the first used cell
+ * on level #level#.
+ *
+ * This function calls #begin_line#
+ * in 1D and #begin_quad# in 2D.
+ */
+ cell_iterator begin (const unsigned int level = 0) const;
+
+ /**
+ * Return iterator to the first active
+ * cell on level #level#.
+ *
+ * This function calls #begin_active_line#
+ * in 1D and #begin_active_quad# in 2D.
+ */
+ active_cell_iterator begin_active(const unsigned int level = 0) const;
+
+ /**
+ * Return iterator past the end; this
+ * iterator serves for comparisons of
+ * iterators with past-the-end or
+ * before-the-beginning states.
+ *
+ * This function calls #end_line#
+ * in 1D and #end_quad# in 2D.
+ */
+ raw_cell_iterator end () const;
+
+ /**
+ * Return an iterator pointing to the
+ * last cell, used or not.
+ *
+ * This function calls #last_raw_line#
+ * in 1D and #last_raw_quad# in 2D.
+ */
+ raw_cell_iterator last_raw () const;
+
+ /**
+ * Return an iterator pointing to the last
+ * cell of the level #level#, used or not.
+ *
+ * This function calls #last_raw_line#
+ * in 1D and #last_raw_quad# in 2D.
+ */
+ raw_cell_iterator last_raw (const unsigned int level) const;
+
+ /**
+ * Return an iterator pointing to the last
+ * used cell.
+ *
+ * This function calls #last_line#
+ * in 1D and #last_quad# in 2D.
+ */
+ cell_iterator last () const;
+
+ /**
+ * Return an iterator pointing to the last
+ * used cell on level #level#.
+ *
+ * This function calls #last_line#
+ * in 1D and #last_quad# in 2D.
+ */
+ cell_iterator last (const unsigned int level) const;
+
+ /**
+ * Return an iterator pointing to the last
+ * active cell.
+ *
+ * This function calls #last_active_line#
+ * in 1D and #last_active_quad# in 2D.
+ */
+ active_cell_iterator last_active () const;
+
+ /**
+ * Return an iterator pointing to the last
+ * active cell on level #level#.
+ *
+ * This function calls #last_active_line#
+ * in 1D and #last_active_quad# in 2D.
+ */
+ active_cell_iterator last_active (const unsigned int level) const;
+ //@}
+
+ /*---------------------------------------*/
+
+ /**
+ * @name Line iterator functions
+ */
+ /*@{*/
+ /**
+ * Return iterator to the first line, used
+ * or not, on level #level#. If a level
+ * has no lines, a past-the-end iterator
+ * is returned.
+ */
+ raw_line_iterator
+ begin_raw_line (const unsigned int level = 0) const;
+
+ /**
+ * Return iterator to the first used line
+ * on level #level#.
+ */
+ line_iterator
+ begin_line (const unsigned int level = 0) const;
+
+ /**
+ * Return iterator to the first active
+ * line on level #level#.
+ */
+ active_line_iterator
+ begin_active_line(const unsigned int level = 0) const;
+
+ /**
+ * Return iterator past the end; this
+ * iterator serves for comparisons of
+ * iterators with past-the-end or
+ * before-the-beginning states.
+ */
+ raw_line_iterator
+ end_line () const;
+
+ /**
+ * Return an iterator pointing to the
+ * last line, used or not.
+ */
+ raw_line_iterator
+ last_raw_line () const;
+
+ /**
+ * Return an iterator pointing to the last
+ * line of the level #level#, used or not.
+
+ */
+ raw_line_iterator
+ last_raw_line (const unsigned int level) const;
+
+ /**
+ * Return an iterator pointing to the last
+ * used line.
+ */
+ line_iterator
+ last_line () const;
+
+ /**
+ * Return an iterator pointing to the last
+ * used line on level #level#.
+ */
+ line_iterator
+ last_line (const unsigned int level) const;
+
+ /**
+ * Return an iterator pointing to the last
+ * active line.
+ */
+ active_line_iterator
+ last_active_line () const;
+
+ /**
+ * Return an iterator pointing to the last
+ * active line on level #level#.
+ */
+ active_line_iterator
+ last_active_line (const unsigned int level) const;
+ /*@}*/
+
+ /*---------------------------------------*/
+
+ /**
+ * @name Quad iterator functions*/
+ /*@{
+ */
+ /**
+ * Return iterator to the first quad, used
+ * or not, on level #level#. If a level
+ * has no quads, a past-the-end iterator
+ * is returned.
+ */
+ raw_quad_iterator
+ begin_raw_quad (const unsigned int level = 0) const;
+
+ /**
+ * Return iterator to the first used quad
+ * on level #level#.
+ */
+ quad_iterator
+ begin_quad (const unsigned int level = 0) const;
+
+ /**
+ * Return iterator to the first active
+ * quad on level #level#.
+ */
+ active_quad_iterator
+ begin_active_quad(const unsigned int level = 0) const;
+
+ /**
+ * Return iterator past the end; this
+ * iterator serves for comparisons of
+ * iterators with past-the-end or
+ * before-the-beginning states.
+ */
+ raw_quad_iterator
+ end_quad () const;
+
+ /**
+ * Return an iterator pointing to the
+ * last quad, used or not.
+ */
+ raw_quad_iterator
+ last_raw_quad () const;
+
+ /**
+ * Return an iterator pointing to the last
+ * quad of the level #level#, used or not.
+
+ */
+ raw_quad_iterator
+ last_raw_quad (const unsigned int level) const;
+
+ /**
+ * Return an iterator pointing to the last
+ * used quad.
+ */
+ quad_iterator
+ last_quad () const;
+
+ /**
+ * Return an iterator pointing to the last
+ * used quad on level #level#.
+ */
+ quad_iterator
+ last_quad (const unsigned int level) const;
+
+ /**
+ * Return an iterator pointing to the last
+ * active quad.
+ */
+ active_quad_iterator
+ last_active_quad () const;
+
+ /**
+ * Return an iterator pointing to the last
+ * active quad on level #level#.
+ */
+ active_quad_iterator
+ last_active_quad (const unsigned int level) const;
+ /*@}*/
+
+ /*---------------------------------------*/
+
+ /**
+ * Return number of degrees of freedom.
+ * Included in this number are those
+ * DoFs which are constrained by
+ * hanging nodes.
+ */
+ unsigned int n_dofs () const;
+
+ /**
+ * Return a constant reference to the
+ * selected finite element object.
+ */
+ const FiniteElement<dim> & get_selected_fe () const;
+
+ /**
+ * Return a constant reference to the
+ * triangulation underlying this object.
+ */
+ const Triangulation<dim> & get_tria () const;
+
+ /**
+ * Exception
+ */
+ DeclException0 (ExcNotImplemented);
+ /**
+ * Exception
+ */
+ DeclException0 (ExcInvalidTriangulation);
+ /**
+ * Exception
+ */
+ DeclException2 (ExcDifferentDimensions,
+ int, int,
+ << "One dimension of the matrices is differing: "
+ << arg1 << " vs. " << arg2);
+ /**
+ * Exception
+ */
+ DeclException0 (ExcNoFESelected);
+ /**
+ * Exception
+ */
+ DeclException0 (ExcRenumberingIncomplete);
+ /**
+ * Exception
+ */
+ DeclException0 (ExcGridsDoNotMatch);
+ /**
+ * Exception
+ */
+ DeclException0 (ExcOnlyOnelevelTransferImplemented);
+ /**
+ * Exception
+ */
+ DeclException0 (ExcInternalError);
+ /**
+ * Exception
+ */
+ DeclException1 (ExcMatrixHasWrongSize,
+ int,
+ << "The matrix has the wrong dimension " << arg1);
+
+ protected:
+ /**
+ * Reserve enough space in the
+ * #levels[]# objects to store the
+ * numbers of the degrees of freedom
+ * needed for the given element.
+ */
+ void reserve_space (const FiniteElement<dim> &);
+
+ /**
+ * Distribute dofs on the given cell,
+ * with new dofs starting with index
+ * #next_free_dof#. Return the next
+ * unused index number.
+ */
+ int distribute_dofs_on_cell (active_cell_iterator &cell,
+ const FiniteElement<dim> &fe,
+ unsigned int next_free_dof);
+
+ /**
+ * Actually do the renumbering prepared
+ * by the #renumber_dofs# function. Since
+ * this is dimension specific, we
+ * need to have another function.
+ */
+ void do_renumbering (const vector<int> &);
+
+ /**
+ * Make up part of the sparsity pattern of
+ * the transfer matrix by looking at the
+ * two cells given.
+ */
+ void transfer_cell (const cell_iterator &old_cell,
+ const cell_iterator &new_cell,
+ dSMatrixStruct &transfer_pattern) const;
+
+ /**
+ * Make up part of the transfer matrix by
+ * looking at the two cells given.
+ */
+ void transfer_cell (const cell_iterator &old_cell,
+ const cell_iterator &new_cell,
+ dSMatrix &transfer_matrix) const;
+
+ /**
+ * Address of the triangulation to
+ * work on.
+ */
+ Triangulation<dim> *tria;
+
+ /**
+ * Space to store the DoF numbers for the
+ * different levels. Analogous to the
+ * #levels[]# tree of the \Ref{Triangulation}
+ * objects.
+ */
+ vector<DoFLevel<dim>*> levels;
+
+ /**
+ * Store a copy of the finite element given
+ * latest for the distribution of dofs.
+ */
+ FiniteElement<dim> *selected_fe;
+
+ /**
+ * Store the number of dofs created last
+ * time.
+ */
+ unsigned int used_dofs;
+
+ /**
+ * Array to store the indices for degrees
+ * of freedom located at vertices.
+ */
+ vector<int> vertex_dofs;
+
+
+ friend class DoFLineAccessor<dim, LineAccessor<dim> >;
+ friend class DoFLineAccessor<dim, CellAccessor<dim> >;
+ friend class DoFQuadAccessor<dim, QuadAccessor<dim> >;
+ friend class DoFQuadAccessor<dim, CellAccessor<dim> >;
+};
+
+
+extern DoFHandler<1> __dummy10123; // do this to calm down gcc2.7; wait for gcc2.8
+extern DoFHandler<2> __dummy10124;
+
+
+
+
+/*---------------------------- dof.h ---------------------------*/
+/* end of #ifndef __dof_H */
+#endif
+/*---------------------------- dof.h ---------------------------*/
--- /dev/null
+/*---------------------------- fe.h ---------------------------*/
+/* $Id$ */
+#ifndef __fe_H
+#define __fe_H
+/*---------------------------- fe.h ---------------------------*/
+
+#include "../deal/dfmatrix.h"
+#include <grid/point.h>
+#include <basic/exceptions.h>
+#include <grid/tria.h>
+
+
+
+// forward declarations
+template <int dim> class FiniteElement;
+template <int dim> class Quadrature;
+
+
+/**
+ Represent a finite element evaluated with a specific quadrature rule.
+ This class is an optimization which avoids evaluating the shape functions
+ at the quadrature points each time a quadrature takes place. Rather, the
+ values and gradients (and possibly higher oder derivatives in future
+ versions of this library) are evaluated once and for all before doing the
+ quadrature itself.
+ */
+template <int dim>
+class FEValues {
+ public:
+ /**
+ * Constructor. Fill all arrays with the
+ * values of the shape functions of the
+ * specified finite element using the
+ * quadrature points of the given
+ * quadrature rule.
+ */
+ FEValues (const FiniteElement<dim> &,
+ const Quadrature<dim> &);
+
+ /**
+ * Return the value of the #i#th shape
+ * function at the #j# quadrature point.
+ */
+ double shape_value (const unsigned int i,
+ const unsigned int j) const;
+
+ /**
+ * Return the gradient of the #i#th shape
+ * function at the #j# quadrature point.
+ * If you want to get the derivative in
+ * one of the coordinate directions, use
+ * the appropriate function of the #Point#
+ * class to extract one component. Since
+ * only a reference to the gradient's value
+ * is returned, there should be no major
+ * performance drawback.
+ * The function returns the gradient on the
+ * real element, not the reference element.
+ */
+ const Point<dim> & shape_grad (const unsigned int i,
+ const unsigned int j) const;
+
+ /**
+ * Reinitialize the gradients, Jacobi
+ * determinants, etc for the given cell
+ * and the given finite element.
+ */
+ void reinit (const Triangulation<dim>::cell_iterator &,
+ const FiniteElement<dim> &);
+
+ /**
+ * Exception
+ */
+ DeclException2 (ExcInvalidIndex,
+ int, int,
+ << "The index " << arg1
+ << " is out of range, it should be less than " << arg2);
+
+ private:
+ /**
+ * Store the values of the shape functions
+ * at the quadrature points. Rows in this
+ * matrix denote the values of a single
+ * shape function at the different points,
+ * columns are for a single point with the
+ * different shape functions.
+ */
+ dFMatrix shape_values;
+
+ /**
+ * Store the gradients of the shape
+ * functions at the quadrature points.
+ * Since unfortunately the full matrix
+ * classes of DEAL are not templated,
+ * we have to store them in an
+ * archetypic style.
+ *
+ * This field is reset each time
+ * #reinit# is called and contains the
+ * gradients on the real element, rather
+ * than on the reference element.
+ */
+ vector<vector<Point<dim> > > shape_gradients;
+
+ /**
+ * Store the gradients of the shape
+ * functions at the quadrature points on
+ * the unit cell.
+ * This field is set up upon construction
+ * of the object and contains the gradients
+ * on the reference element.
+ */
+ vector<vector<Point<dim> > > unit_shape_gradients;
+
+ /**
+ * Store an array of the weights of the
+ * quadrature points. This array is
+ * set up upon construction.
+ */
+ vector<double> weights;
+
+ /**
+ * Store an array of weights times the
+ * Jacobi determinant at the quadrature
+ * points. This function is reset each time
+ * #reinit# is called.
+ */
+ vector<double> JxW_values;
+
+ /**
+ * Array of quadrature points. This array
+ * is set up upon calling #reinit# and
+ * contains the quadrature points on the
+ * real element, rather than on the
+ * reference element.
+ */
+ vector<Point<dim> > quadrature_points;
+
+ /**
+ * Array of quadrature points in the unit
+ * cell. This array is set up upon
+ * construction and contains the quadrature
+ * points on the reference element.
+ */
+ vector<Point<dim> > unit_quadrature_points;
+
+ /**
+ * Store the jacobi matrices at the
+ * different quadrature points. This field
+ * is set each time #reinit# is called.
+ */
+ vector<dFMatrix> jacobi_matrices;
+};
+
+
+
+
+/**
+ Base class for finite elements in arbitrary dimensions.
+ */
+template <int dim>
+class FiniteElementBase {
+ public:
+ /**
+ * Total number of degrees of freedom
+ * on a cell. This information is
+ * redundant to some fields in the
+ * derived classes but makes
+ * writing dimension independant
+ * programs easier.
+ */
+ const unsigned int total_dofs;
+
+ /**
+ * Default constructor. Constructs an element
+ * which is not so useful. Checking
+ * #total_dofs# is therefore a good way to
+ * check if something went wrong.
+ */
+ FiniteElementBase () :
+ total_dofs(0) {};
+
+ /**
+ * Constructor. You have to set the
+ * matrices explicitely after calling
+ * this base class' constructor.
+ */
+ FiniteElementBase (const unsigned int total_dofs) :
+ total_dofs(total_dofs) {};
+
+ /**
+ * Copy constructor.
+ */
+ FiniteElementBase (const FiniteElementBase &f);
+
+// /**
+// * Destructor. Only declared to have a
+// * virtual destructor which the compiler
+// * wants to have.
+// */
+// virtual ~FiniteElementBase () {};
+
+
+ /**
+ * Return the value of the #i#th shape
+ * function at the point #p#. This function
+ * should really be pure, but then we could
+ * not make copies of a finite element
+ * object even if we did not intend to use
+ * this function. Therefore, we ommit the
+ * #=0# signature and implement this function
+ * by throwing an exception.
+ * #p# is a point on the reference element.
+ */
+ virtual double shape_value (const unsigned int i,
+ const Point<dim>& p) const;
+
+ /**
+ * Return the gradient of the #i#th shape
+ * function at the point #p#. This function
+ * should really be pure, but then we could
+ * not make copies of a finite element
+ * object even if we did not intend to use
+ * this function. Therefore, we ommit the
+ * #=0# signature and implement this function
+ * by throwing an exception.
+ * #p# is a point on the reference element,
+ */
+ virtual Point<dim> shape_grad (const unsigned int i,
+ const Point<dim>& p) const;
+
+ /**
+ * Return a readonly reference to the
+ * matrix which describes the transfer of a
+ * child with the given number to the
+ * mother cell.
+ */
+ const dFMatrix & restrict (const unsigned int child) const;
+
+ /**
+ * Return a readonly reference to the
+ * matrix which describes the transfer of a
+ * mother cell to the child with the given
+ * number.
+ */
+ const dFMatrix & prolongate (const unsigned int child) const;
+
+ /**
+ * Return a readinly reference to the
+ * matrix which describes the constraints
+ * at the interface between a refined and
+ * an unrefined cell.
+ *
+ * The matrix is obviously empty in only
+ * one space dimension, since there are no
+ * constraints then.
+ */
+ const dFMatrix & constraints () const;
+
+ /**
+ * Compute the jacobian matrix and the
+ * quadrature points from the given cell
+ * and the given quadrature points on the
+ * unit cell. The jacobian matrix is to
+ * be computed at every quadrature point.
+ * This function has to be in the finite
+ * element class, since different finite
+ * elements need different transformations
+ * of the unit cell to a real cell.
+ */
+ virtual void fill_fe_values (const Triangulation<dim>::cell_iterator &cell,
+ const vector<Point<dim> > &unit_points,
+ vector<dFMatrix> &jacobians,
+ vector<Point<dim> > &points) const;
+
+ /**
+ * Comparison operator. We also check for
+ * equality of the constraint matrix,
+ * which is quite an expensive operation.
+ * Do therefore
+ * use this function with care, if possible
+ * only for debugging purposes.
+ *
+ * Since this function is not that important,
+ * we avoid an implementational question
+ * about comparing arrays and do not compare
+ * the matrix arrays #restriction# and
+ * #prolongation#.
+ */
+ bool operator == (const FiniteElementBase<dim> &) const;
+
+ /**
+ * Exception
+ */
+ DeclException1 (ExcInvalidIndex,
+ int,
+ << "Invalid index " << arg1);
+ /**
+ * Exception
+ */
+ DeclException0 (ExcPureFunctionCalled);
+
+ protected:
+ /**
+ * Have #N=2^dim# matrices keeping the
+ * restriction constants for the transfer
+ * of the #i#th child to the mother cell.
+ * The numbering conventions for the
+ * degree of freedom indices are descibed
+ * in the derived classes.
+ * In this matrix, the row indices belong
+ * to the destination cell, i.e. the
+ * unrefined one, while the column indices
+ * are for the refined cell's degrees of
+ * freedom.
+ *
+ * Upon assembling the transfer matrix
+ * between cells using this matrix array,
+ * zero elements in the restriction
+ * matrix are discarded and will not fill
+ * up the transfer matrix.
+ */
+ dFMatrix restriction[(1<<dim)];
+
+ /**
+ * Have #N=2^dim# matrices keeping the
+ * prolongation constants for the transfer
+ * of the mother cell to the #i#th child.
+ * The numbering conventions for the
+ * degree of freedom indices are descibed
+ * in the derived classes.
+ * In this matrix, the row indices belong
+ * to the destination cell, i.e. the
+ * refined one, while the column indices
+ * are for the unrefined cell's degrees of
+ * freedom.
+ *
+ * Upon assembling the transfer matrix
+ * between cells using this matrix array,
+ * zero elements in the prolongation
+ * matrix are discarded and will not fill
+ * up the transfer matrix.
+ */
+ dFMatrix prolongation[(1<<dim)];
+
+ /**
+ * Specify the constraints which the
+ * dofs on the two sides of a cell interface
+ * underly if the line connects two
+ * cells of which one is refined once.
+ *
+ * For further details see the general
+ * description of the derived class.
+ *
+ * This field is obviously useless in one
+ * space dimension.
+ */
+ dFMatrix interface_constraints;
+};
+
+
+
+
+
+
+/**
+ Define a finite element type.
+ */
+template <int dim>
+class FiniteElement;
+
+
+
+/**
+ Finite Element in one dimension.
+
+ {\bf Note on extending the finite element class}
+
+ If you want to extend this class (not by derivation, but by adding new
+ elements), you should be aware that it may be copied at places where you
+ don't expect that (e.g. the #DoFHandler# class keeps a copy). You must
+ thus make sure that the copy operator works correctly, in special if
+ pointers are involved, copying by the default copy constructor supplied
+ by the compiler will result in double deletion and maybe access to data
+ elements which are no more valid.
+
+ Consequence: make sure the copy constructor is correct.
+ */
+class FiniteElement<1> : public FiniteElementBase<1> {
+ public:
+ /**
+ * Number of degrees of freedom on
+ * a vertex.
+ */
+ const unsigned int dofs_per_vertex;
+
+ /** Number of degrees of freedom
+ * on a line.
+ */
+ const unsigned int dofs_per_line;
+
+
+ /**
+ * Default constructor. The base class
+ * produces an invalid element.
+ */
+ FiniteElement () :
+ dofs_per_vertex(0),
+ dofs_per_line(0) {};
+
+ /**
+ * Constructor
+ */
+ FiniteElement (const unsigned int dofs_per_vertex,
+ const unsigned int dofs_per_line) :
+ FiniteElementBase<1> (2*dofs_per_vertex +
+ dofs_per_line),
+ dofs_per_vertex(dofs_per_vertex),
+ dofs_per_line (dofs_per_line) {};
+
+ /**
+ * Copy constructor
+ */
+ FiniteElement (const FiniteElement<1> &fe) :
+ FiniteElementBase<1> (fe),
+ dofs_per_vertex(fe.dofs_per_vertex),
+ dofs_per_line (fe.dofs_per_line) {};
+
+ /**
+ * Same pseudo-comparison operator
+ * as for the base class.
+ */
+ bool operator == (const FiniteElement<1> &f) const;
+};
+
+
+
+
+
+/**
+ Finite Element in two dimensions.
+
+ In addition to the fields already present in 1D, a constraint matrix
+ is needed in case two quads meet at a common line of which one is refined
+ once more than the other one. Then there are constraints referring to the
+ hanging nodes on that side of the line which is refined. These constraints
+ are represented by a $n\times m$-matrix #line_constraints#, where $n$ is the
+ number of degrees of freedom on the refined side (those dofs on the three
+ vertices plus those on the two lines), and $m$ is that of the unrefined side
+ (those dofs on the two vertices plus those on the line). The matrix is thus
+ a rectangular one, being higher than wide.
+
+ The mapping of the dofs onto the indices of the matrix is as follows:
+ let $d_v$ be the number of dofs on a vertex, $d_l$ that on a line, then
+ $m=0...d_v-1$ refers to the dofs on vertex zero of the unrefined line,
+ $m=d_v...2d_v-1$ to those on vertex one,
+ $m=2d_v...2d_v+d_l-1$ to those on the line.
+
+ Similarly, $n=0...d_v-1$ refers to the dofs on the middle vertex
+ (vertex one of child line zero, vertex zero of child line one),
+ $n=d_v...d_v+d_l-1$ refers to the dofs on child line zero,
+ $n=d_v+d_l...d_v+2d_l-1$ refers to the dofs on child line one.
+ Please note that we do not need to reserve space for the dofs on the
+ end vertices of the refined lines, since these must be mapped one-to-one
+ to the appropriate dofs of the vertices of the unrefined line.
+
+ It should be noted that it is not possible to distribute a constrained
+ degree of freedom to other degrees of freedom which are themselves
+ constrained. Only one level of indirection is allowed. It is not known
+ at the time of this writing whether this is a constraint itself.
+
+ If you want to extend this class (not by derivation, but by adding new
+ elements), see \Ref{FiniteElement<1>}
+ */
+class FiniteElement<2> : public FiniteElementBase<2> {
+ public:
+ /**
+ * Number of degrees of freedom on
+ * a vertex.
+ */
+ const unsigned int dofs_per_vertex;
+
+ /** Number of degrees of freedom
+ * on a line.
+ */
+ const unsigned int dofs_per_line;
+
+ /** Number of degrees of freedom
+ * on a quad.
+ */
+ const unsigned int dofs_per_quad;
+
+ /**
+ * Default constructor. The base class
+ * produces an invalid element.
+ */
+ FiniteElement () :
+ dofs_per_vertex(0),
+ dofs_per_line(0),
+ dofs_per_quad(0) {};
+
+ /**
+ * Constructor
+ */
+ FiniteElement (const unsigned int dofs_per_vertex,
+ const unsigned int dofs_per_line,
+ const unsigned int dofs_per_quad) :
+ FiniteElementBase<2> (4*dofs_per_vertex +
+ 4*dofs_per_line +
+ dofs_per_quad),
+ dofs_per_vertex(dofs_per_vertex),
+ dofs_per_line (dofs_per_line),
+ dofs_per_quad (dofs_per_quad) {};
+
+ /**
+ * Copy constructor
+ */
+ FiniteElement (const FiniteElement<2> &fe) :
+ FiniteElementBase<2> (fe),
+ dofs_per_vertex(fe.dofs_per_vertex),
+ dofs_per_line (fe.dofs_per_line),
+ dofs_per_quad (fe.dofs_per_quad) {};
+
+ /**
+ * Same pseudo-comparison operator
+ * as for the base class.
+ */
+ bool operator == (const FiniteElement<2> &f) const;
+};
+
+
+
+
+/*---------------------------- fe.h ---------------------------*/
+/* end of #ifndef __fe_H */
+#endif
+/*---------------------------- fe.h ---------------------------*/
--- /dev/null
+/*---------------------------- fe_lib.h ---------------------------*/
+/* $Id$ */
+#ifndef __fe_lib_H
+#define __fe_lib_H
+/*---------------------------- fe_lib.h ---------------------------*/
+
+
+#include <fe/fe.h>
+
+
+
+/**
+ Define a (bi-, tri-, etc)linear finite element in #dim# space dimensions.
+ */
+template <int dim>
+class FELinear : public FiniteElement<dim> {
+ public:
+ FELinear ();
+ virtual double shape_value(const unsigned int i,
+ const Point<dim>& p) const;
+ virtual Point<dim> shape_grad(const unsigned int i,
+ const Point<dim>& p) const;
+};
+
+
+
+
+/**
+ Define a (bi-, tri-, etc)quadratic finite element in #dim# space dimensions.
+ */
+template <int dim>
+class FEQuadratic : public FiniteElement<dim> {
+ public:
+ FEQuadratic ();
+ virtual double shape_value(const unsigned int i,
+ const Point<dim>& p) const;
+ virtual Point<dim> shape_grad(const unsigned int i,
+ const Point<dim>& p) const;
+};
+
+
+
+
+/**
+ Define a (bi-, tri-, etc)cubic finite element in #dim# space dimensions.
+ */
+template <int dim>
+class FECubic : public FiniteElement<dim> {
+ public:
+ FECubic ();
+ virtual double shape_value(const unsigned int i,
+ const Point<dim>& p) const;
+ virtual Point<dim> shape_grad(const unsigned int i,
+ const Point<dim>& p) const;
+};
+
+
+
+/*---------------------------- fe_lib.h ---------------------------*/
+/* end of #ifndef __fe_lib_H */
+#endif
+/*---------------------------- fe_lib.h ---------------------------*/
--- /dev/null
+/*---------------------------- exceptions.h ---------------------------*/
+/* $Id$ */
+#ifndef __exceptions_H
+#define __exceptions_H
+/*---------------------------- exceptions.h ---------------------------*/
+
+
+#include <iostream.h>
+
+
+
+#ifndef __GNUC__
+# define __PRETTY_FUNCTION__ "(unknown)"
+#endif
+
+ /**
+ * This class should be used as a base class for
+ * all exception classes. Do not use its methods
+ * and variables directly since the interface
+ * and mechanism may be subject to change. Rather
+ * create new exception classes using the
+ * #DeclException# macro family.
+ *
+ * @see Assert
+ * @see DeclException0
+ * @author Wolfgang Bangerth, November 1997
+ */
+class ExceptionBase {
+ public:
+ ExceptionBase () {};
+ /**
+ * The constructor takes the file in which the
+ * error happened, the line and the violated
+ * condition as well as the name of the
+ * exception class as a #char*# as arguments.
+ */
+ ExceptionBase (const char* f, const int l, const char *func,
+ const char* c, const char *e) :
+ file(f), line(l), function(func), cond(c), exc(e) {};
+
+ /**
+ * Set the file name and line of where the
+ * exception appeared as well as the violated
+ * condition and the name of the exception as
+ * a char pointer.
+ */
+ void SetFields (const char* f,
+ const int l,
+ const char *func,
+ const char *c,
+ const char *e) {
+ file = f;
+ line = l;
+ function = func;
+ cond = c;
+ exc = e;
+ };
+ /**
+ * Print out the general part of the error
+ * information.
+ */
+ void PrintExcData (ostream &out) const {
+ out << "An error occurred in line <" << line
+ << "> of file <" << file
+ << "> in function" << endl
+ << " " << function << endl
+ << "The violated condition was: "<< endl
+ << " " << cond << endl
+ << "The name and call sequence of the exception was:" << endl
+ << " " << exc << endl
+ << "Additional Information: " << endl;
+ };
+
+ /**
+ * Print more specific information about the
+ * exception which occured. Overload this
+ * function in your own exception classes.
+ * Since we use templates rather than derivation
+ * information, we need not declare this
+ * function as #virtual# and thus avoid problems
+ * with virtual functions in classes in which
+ * all functions are declared inline.
+ */
+ void PrintInfo (ostream &out) const {
+ out << "(none)" << endl;
+ };
+
+
+ const char *file;
+ int line;
+ const char *function;
+ const char *cond;
+ const char *exc;
+};
+
+
+ /**
+ * This routine does the main work for the
+ * exception generation mechanism.
+ *
+ * @see Assert
+ */
+template <class exc>
+void __IssueError (const char *file,
+ int line,
+ const char *function,
+ const char *cond,
+ const char *exc,
+ exc e) {
+ // Fill the fields of the exception object
+ e.SetFields (file, line, function, cond, exc);
+ cerr << "--------------------------------------------------------"
+ << endl;
+ // print out general data
+ e.PrintExcData (cerr);
+ // print out exception specific data
+ e.PrintInfo (cerr);
+ cerr << "--------------------------------------------------------"
+ << endl;
+
+ abort ();
+ };
+
+
+
+#ifdef DEBUG ////////////////////////////////////////
+
+/**
+ This is the main routine in the exception mechanism.
+ Use it in the following way: declare an exception
+ class using the #DeclException# macros (see there),
+ for example
+ \begin{verbatim}
+ DeclException2 (ExcDomain, int, int,
+ << "Index= " << arg1 << "Upper Bound= " << arg2);
+ \end{verbatim}
+ to declare an exception class named #ExcDomain#, which
+ has two variables as additional information (named
+ #arg1# and #arg2# by default) and which outputs the
+ given sequence (which is appended to an #ostream#
+ variable's name, thus the weird syntax). There are
+ other #DeclExceptionN# macros for exception classes
+ with more or no parameters. It is proposed to let start
+ the name of all exceptions by #Exc...#.
+
+ In your source code write lines like
+ \begin{verbatim}
+ Assert (n<dim, ExcDomain(n,dim));
+ \end{verbatim}
+ which does the following:
+ \begin{verbatim}
+ #ifdef DEBUG
+ if (!cond)
+ issue error of class ExcDomain(n,dim)
+ #else
+ do nothing
+ #endif
+ \end{verbatim}
+ i.e. it issues an error only if the preprocessor variable
+ #DEBUG# is set and if the given condition (in this case
+ #n<dim# is violated.
+
+ If the exception was declared using the #DeclException0 (...)#
+ macro, i.e. without any additional parameters, its name has
+ nonetheless to be given with parentheses:
+ #Assert (i>m, ExcSomewhat());#
+
+ {\bf How it works internally:}
+ The call #Assert (cond, exc);#
+ is converted by the preprocessor into the sequence
+ \begin{verbatim}
+ if (!(cond))
+ __IssueError (__FILE__,
+ __LINE__,
+ __PRETTY_FUNCTION__,
+ #cond,
+ #exc,
+ &exc);
+ \end{verbatim}
+ i.e. if the given condition is violated, then the file and
+ line in which the exception occured as well as
+ the condition itself and the call sequence of the
+ exception object is transferred. Additionally an object
+ of the form given by #exc# is created (this is normally an
+ unnamed object like in #ExcDomain (n, dim)# of class
+ #ExcDomain#) and transferred to the #__IssueError#
+ function.
+
+ #__PRETTY__FUNCTION__# is a macro defined only by the GNU CC
+ compiler and gives the name of the function. If another compiler
+ is used, we set #__PRETTY_FUNCTION__ = "(unknown)"#.
+
+ In #__IssueError# the given data
+ is transferred into the #exc# object by calling the
+ #SetFields# function; after that, the general error info
+ is printed onto #cerr# using the #PrintError# function of
+ #exc# and finally the exception specific data is printed
+ using the user defined function #PrintError# (which is
+ normally created using the #DeclException (...)# macro
+ family.
+
+ After printing all this information, #abort()# is called.
+ This may in future versions be replaced by calling
+ #throw exc;#.
+
+ If the preprocessor variable #DEBUG# is not set, then nothing
+ happens, i.e. the macro is expanded to #(void) 0;#.
+
+ @memo Assert that a certain condition is fulfilled, otherwise
+ issue an error and abort the program.
+
+ @see DeclException0
+ @author Wolfgang Bangerth, November 1997
+ */
+#define Assert(cond, exc) \
+ if (!(cond)) \
+ __IssueError (__FILE__, \
+ __LINE__, \
+ __PRETTY_FUNCTION__, #cond, #exc, exc)
+
+
+#else ////////////////////////////////////////
+
+#define Assert(cond, exc) \
+ (void) 0
+#endif ////////////////////////////////////////
+
+
+
+/**
+ Declare an exception class without any additional parameters.
+ There is a whole family of #DeclException?# macros
+ where #?# is to be replaced by the number of additional
+ parameters (0 to 5 presently).
+
+ The syntax is as follows:
+ \begin{verbatim}
+ DeclException2 (ExcDomain,
+ int,
+ int,
+ << " i=" << arg1 << ", m=" << arg2);
+ \end{verbatim}
+ The first is the name of the exception class to be created.
+ The next arguments are the types of the parameters (in this
+ case there are two type names needed) and finally the output
+ sequence with which you can print additional information.
+
+ The syntax of the output sequence is a bit weird but gets
+ clear once you see how this macro is defined:
+ \begin{verbatim}
+ class name : public ExceptionBase {
+ public:
+ name (const type1 a1, const type2 a2) :
+ arg1 (a1), arg2(a2) {};
+ void PrintInfo (ostream &out) const {
+ out outsequence << endl;
+ };
+ private:
+ type1 arg1;
+ type2 arg2;
+ };
+ \end{verbatim}
+ The #PrintInfo# function is not declared #virtual# since we would
+ then create a class with virtual functions and only inlined code.
+ For this kind of class at least GNU C++ does not know where to put
+ the virtual method table and the program will not be compiled.
+
+ If declared as specified, you can later use this exception class
+ in the following manner:
+ \begin{verbatim}
+ int i=5;
+ int m=3;
+ Assert (i<m, MyExc2(i,m));
+ \end{verbatim}
+ and the output if the condition fails will be
+ \begin{verbatim}
+ --------------------------------------------------------
+ An error occurred in line <301> of file <exc-test.cc>.
+ The violated condition was:
+ i<m
+ The name and call sequence of the exception was:
+ MyExc2(i,m)
+ Additional Information:
+ i=5, m=3
+ --------------------------------------------------------
+ \end{verbatim}
+
+ Obviously for the #DeclException0(name)# macro, no types and
+ also no output sequence is allowed.
+
+ @author Wolfgang Bangerth, November 1997
+ */
+#define DeclException0(Exception0) \
+class Exception0 : public ExceptionBase {};
+
+ /**
+ * Declare an exception class with
+ * one additional parameter.
+ *
+ * @see DeclException0
+ */
+#define DeclException1(Exception1, type1, outsequence) \
+class Exception1 : public ExceptionBase { \
+ public: \
+ Exception1 (const type1 a1) : arg1 (a1) {}; \
+ void PrintInfo (ostream &out) const { \
+ out outsequence << endl; \
+ }; \
+ private: \
+ const type1 arg1; \
+}
+
+ /**
+ * Declare an exception class with
+ * two additional parameters.
+ *
+ * @see DeclException0
+ */
+#define DeclException2(Exception2, type1, type2, outsequence) \
+class Exception2 : public ExceptionBase { \
+ public: \
+ Exception2 (const type1 a1, const type2 a2) : \
+ arg1 (a1), arg2(a2) {}; \
+ void PrintInfo (ostream &out) const { \
+ out outsequence << endl; \
+ }; \
+ private: \
+ const type1 arg1; \
+ const type2 arg2; \
+}
+
+ /**
+ * Declare an exception class with
+ * three additional parameters.
+ *
+ * @see DeclException0
+ */
+#define DeclException3(Exception3, type1, type2, type3, outsequence) \
+class Exception3 : public ExceptionBase { \
+ public: \
+ Exception3 (const type1 a1, const type2 a2, const type3 a3) : \
+ arg1 (a1), arg2(a2), arg3(a3) {}; \
+ void PrintInfo (ostream &out) const { \
+ out outsequence << endl; \
+ }; \
+ private: \
+ const type1 arg1; \
+ const type2 arg2; \
+ const type3 arg3; \
+}
+
+ /**
+ * Declare an exception class with
+ * four additional parameters.
+ *
+ * @see DeclException0
+ */
+#define DeclException4(Exception4, type1, type2, type3, type4, outsequence) \
+class Exception4 : public ExceptionBase { \
+ public: \
+ Exception4 (const type1 a1, const type2 a2, \
+ const type3 a3, const type4 a4) : \
+ arg1 (a1), arg2(a2), arg3(a3), arg4(a4) {}; \
+ void PrintInfo (ostream &out) const { \
+ out outsequence << endl; \
+ }; \
+ private: \
+ const type1 arg1; \
+ const type2 arg2; \
+ const type3 arg3; \
+ const type4 arg4; \
+}
+
+ /**
+ * Declare an exception class with
+ * five additional parameters.
+ *
+ * @see DeclException0
+ */
+#define DeclException5(Exception5, type1, type2, type3, type4, type5, outsequence) \
+class Exception5 : public ExceptionBase { \
+ public: \
+ Exception5 (const type1 a1, const type2 a2, const type3 a3, \
+ const type4 a4, const type5 a5) : \
+ arg1 (a1), arg2(a2), arg3(a3), arg4(a4), arg5(a5) {}; \
+ void PrintInfo (ostream &out) const { \
+ out outsequence << endl; \
+ }; \
+ private: \
+ const type1 arg1; \
+ const type2 arg2; \
+ const type3 arg3; \
+ const type4 arg4; \
+ const type5 arg5; \
+}
+
+
+
+
+
+
+/*---------------------------- exceptions.h ---------------------------*/
+/* end of #ifndef __exceptions_H */
+#endif
+/*---------------------------- exceptions.h ---------------------------*/
--- /dev/null
+/*---------------------------- magic_numbers.h ---------------------------*/
+/* $Id$ */
+#ifndef __magic_numbers_H
+#define __magic_numbers_H
+/*---------------------------- magic_numbers.h ---------------------------*/
+
+
+// This is a list of magic numbers used throughout the library.
+// They are collected in one file to avoid double usage.
+// Naming convention: all names have to start with the sequence
+// "mn_" denoting a magic number, then the library part follows
+// (e.g. "tria_" or "dof_") and finally the purpose.
+
+const unsigned int mn_tria_refine_flags_begin = 0xabcc;
+const unsigned int mn_tria_refine_flags_end = 0xabcd;
+const unsigned int mn_tria_line_user_flags_begin = 0xabce;
+const unsigned int mn_tria_line_user_flags_end = 0xabcf;
+const unsigned int mn_tria_quad_user_flags_begin = 0xabce;
+const unsigned int mn_tria_quad_user_flags_end = 0xabcf;
+
+
+
+/*---------------------------- magic_numbers.h ---------------------------*/
+/* end of #ifndef __magic_numbers_H */
+#endif
+/*---------------------------- magic_numbers.h ---------------------------*/
--- /dev/null
+/*---------------------------- point.h ---------------------------*/
+/* $Id$ */
+#ifndef __point_H
+#define __point_H
+/*---------------------------- point.h ---------------------------*/
+
+
+#include <basic/exceptions.h>
+#include <iostream.h>
+
+
+/**
+ The #Point# class provides for a point or vector in a space with arbitrary
+ dimension #dim#.
+
+ It is the preferred object to be passed to functions which
+ operate on points in spaces of a priori unknown dimension: rather than
+ using functions like #double f(double x)# and #double f(double x, double y)#,
+ you use double #f(Point<dim> &p)#.
+
+ #Point# also serves as a starting point for the implementation of the
+ geometrical primitives like #Polyhedron#, #Triangle#, etc.
+
+ #Point#s can also be thought of as vectors, i.e. points in a vector space
+ without an obvious meaning. For instance, it may be suitable to let the
+ gradient of a function be a #point# vector:
+ #Point<dim> gradient_of_f (const Point<dim> &x)#. #Point#s have all
+ functionality for this, e.g. scalar products, addition etc.
+ */
+template <int dim>
+class Point {
+ public:
+ /**
+ * Constructor.
+ */
+ Point ();
+ /**
+ * Constructor for one dimensional points. This
+ * function is only implemented for #dim==1#
+ * since the usage is considered unsafe
+ * for points with #dim!=1#.
+ */
+ Point (const double x);
+
+ /**
+ * Constructor for two dimensional points. This
+ * function is only implemented for #dim==2#
+ * since the usage is considered unsafe
+ * for points with #dim!=2#.
+ */
+ Point (const double x, const double y);
+
+ /**
+ * Constructor for three dimensional points. This
+ * function is only implemented for #dim==3#
+ * since the usage is considered unsafe
+ * for points with #dim!=3#.
+ */
+ Point (const double x, const double y, const double z);
+
+ /**
+ * Copy constructor.
+ */
+ Point (const Point<dim> &);
+
+ /**
+ * Return the dimension of the space this
+ * point is living in.
+ */
+ int dimension() const { return dim; };
+
+ /**
+ * Read access to the #index#th coordinate.
+ */
+ double operator () (const int index) const;
+ /**
+ * Read and write access to the #index#th
+ * coordinate.
+ */
+ double & operator () (const int index);
+
+ /**
+ * Assignment operator.
+ */
+ Point<dim> & operator = (const Point<dim> &);
+
+ /**
+ * Test for equality of two points.
+ */
+ bool operator ==(const Point<dim> &) const;
+ /**
+ * Test for inequality of two points.
+ */
+ bool operator !=(const Point<dim> &) const;
+
+ /**
+ * Add two point vectors. If possible, use
+ * #operator +=# instead since this does not
+ * need to copy a point at least once.
+ */
+ Point<dim> operator + (const Point<dim> &) const;
+ /**
+ * Subtract two point vectors. If possible, use
+ * #operator +=# instead since this does not
+ * need to copy a point at least once.
+ */
+ Point<dim> operator - (const Point<dim> &) const;
+
+ /**
+ * Add another vector, i.e. move this point by
+ * the given offset.
+ */
+ Point<dim> & operator += (const Point<dim> &);
+ /**
+ * Subtract another vector.
+ */
+ Point<dim> & operator -= (const Point<dim> &);
+
+ /**
+ * Scale the vector by #factor#, i.e. multiply
+ * all coordinates by #factor#.
+ */
+ Point<dim> & operator *= (const double &factor);
+ /**
+ * Scale the vector by #1/factor#.
+ */
+ Point<dim> & operator /= (const double &factor);
+
+ /**
+ * Returns the scalar product of two vectors.
+ */
+ double operator * (const Point<dim> &) const;
+
+ /**
+ * Returns the scalar product of this point
+ * vector with itself, i.e. the square, or
+ * the square of the norm.
+ */
+ double square () const;
+
+ /**
+ * Prints the coordinates of this point in the
+ * form #(x1,x2,x3,etc)#.
+ */
+// friend ostream & operator << (ostream &, const Point<dim> &p);
+
+ /**
+ * Exception
+ */
+ DeclException1 (ExcDimTooSmall,
+ int,
+ << "Given dimensions must be >= 1, but was " << arg1);
+ /**
+ * Exception
+ */
+ DeclException1 (ExcInvalidIndex,
+ int,
+ << "Invalid index " << arg1);
+ protected:
+ /**
+ * Stores the coordinate values.
+ */
+ double coordinates[dim];
+};
+
+// /**
+// * Prints the coordinates of this point in the
+// * form #(x1,x2,x3,etc)#.
+// */
+//template <int dim>
+//ostream & operator << (ostream &out, const Point<dim> &p);
+
+
+
+
+
+
+
+/*------------------------------- Inline functions: Point ---------------------------*/
+
+
+template <int dim>
+inline
+Point<dim>::Point () {
+ Assert (dim>0, ExcDimTooSmall(dim));
+
+ for (int i=0; i<dim; ++i)
+ coordinates[i] = 0;
+};
+
+
+
+inline
+Point<1>::Point (const double x) {
+ coordinates[0] = x;
+};
+
+
+
+inline
+Point<2>::Point (const double x, const double y) {
+ coordinates[0] = x;
+ coordinates[1] = y;
+};
+
+
+
+inline
+Point<3>::Point (const double x, const double y, const double z) {
+ coordinates[0] = x;
+ coordinates[1] = y;
+ coordinates[2] = z;
+};
+
+
+
+template <int dim>
+inline
+Point<dim>::Point (const Point<dim> &p) {
+ for (int i=0; i<dim; ++i)
+ coordinates[i] = p.coordinates[i];
+};
+
+
+
+template <int dim>
+inline
+double Point<dim>::operator () (const int index) const {
+ Assert ((index>=0) && (index<dim), ExcInvalidIndex (index));
+ return coordinates[index];
+};
+
+
+template <int dim>
+inline
+double & Point<dim>::operator () (const int index) {
+ Assert ((index>=0) && (index<dim), ExcInvalidIndex (index));
+ return coordinates[index];
+};
+
+
+template <int dim>
+inline
+Point<dim> & Point<dim>::operator = (const Point<dim> &p) {
+ for (int i=0; i<dim; ++i)
+ coordinates[i] = p.coordinates[i];
+ return *this;
+};
+
+
+template <int dim>
+inline
+bool Point<dim>::operator == (const Point<dim> &p) const {
+ for (int i=0; i<dim; ++i)
+ if (coordinates[i] != p.coordinates[i]) return false;
+ return true;
+};
+
+
+template <int dim>
+inline
+bool Point<dim>::operator != (const Point<dim> &p) const {
+ return !((*this) == p);
+};
+
+
+template <int dim>
+inline
+Point<dim> Point<dim>::operator + (const Point<dim> &p) const {
+ return (Point<dim>(*this) += p);
+};
+
+
+template <int dim>
+inline
+Point<dim> Point<dim>::operator - (const Point<dim> &p) const {
+ return (Point<dim>(*this) -= p);
+};
+
+
+template <int dim>
+inline
+Point<dim> & Point<dim>::operator += (const Point<dim> &p) {
+ for (int i=0; i<dim; ++i)
+ coordinates[i] += p.coordinates[i];
+ return *this;
+};
+
+
+template <int dim>
+inline
+Point<dim> & Point<dim>::operator -= (const Point<dim> &p) {
+ for (int i=0; i<dim; ++i)
+ coordinates[i] -= p.coordinates[i];
+ return *this;
+};
+
+
+template <int dim>
+inline
+Point<dim> & Point<dim>::operator *= (const double &s) {
+ for (int i=0; i<dim; ++i)
+ coordinates[i] *= s;
+ return *this;
+};
+
+
+template <int dim>
+inline
+Point<dim> & Point<dim>::operator /= (const double &s) {
+ for (int i=0; i<dim; ++i)
+ coordinates[i] /= s;
+ return *this;
+};
+
+
+template <int dim>
+inline
+double Point<dim>::operator * (const Point<dim> &p) const {
+ double q=0;
+ for (int i=0; i<dim; ++i)
+ q += coordinates[i] * p.coordinates[i];
+ return q;
+};
+
+
+template <int dim>
+inline
+double Point<dim>::square () const {
+ double q=0;
+ for (int i=0; i<dim; ++i)
+ q += coordinates[i] * coordinates[i];
+ return q;
+};
+
+
+
+inline
+ostream & operator << (ostream &out, const Point<1> &p) {
+ out << p(0);
+ return out;
+};
+
+
+inline
+ostream & operator << (ostream &out, const Point<2> &p) {
+// out << "(";
+// for (int i=0; i<1; i++)
+// out << p(i) << ",";
+// out << p(1) << ")";
+ out << p(0) << " " << p(1);
+ return out;
+};
+
+
+
+/*---------------------------- point.h ---------------------------*/
+/* end of #ifndef __point_H */
+#endif
+/*---------------------------- point.h ---------------------------*/
--- /dev/null
+/*---------------------------- tria.h ---------------------------*/
+/* $Id$ */
+#ifndef __tria_H
+#define __tria_H
+/*---------------------------- tria.h ---------------------------*/
+
+#include <vector.h>
+#include <grid/tria_line.h>
+#include <grid/tria_quad.h>
+#include <grid/point.h>
+#include "tria_boundary.h"
+
+
+//#ifdef __GNUC__
+//# include <bvector.h>
+//class vector<bool> :
+//public bit_vector {};
+//#endif
+
+
+//forward declaration needed
+
+template <int dim> class TriaAccessor;
+template <int dim> class LineAccessor;
+template <int dim> class QuadAccessor;
+template <int dim> class CellAccessor;
+
+
+template <int dim, class Accessor> class TriaRawIterator;
+template <int dim, class Accessor> class TriaIterator;
+template <int dim, class Accessor> class TriaActiveIterator;
+
+template <int dim> class DoFHandler;
+
+
+class istream;
+class ostream;
+
+
+
+/**
+ General template for information belonging to one level of a multilevel
+ hierarchy of a triangulation. This template is only declared to allow
+ specializations for different dimensions.
+
+ @see TriangulationLevel<1>
+ @see TriangulationLevel<2>
+ */
+template <int dim>
+class TriangulationLevel;
+
+
+/**
+ Store all information which belongs to one level of the multilevel hierarchy.
+
+ In #TriangulationLevel<0># all data is stored which is not
+ dependant on the dimension, e.g. a field to store the
+ refinement flag for the cells (what a cell actually is
+ is declared elsewhere), etc.
+
+ @memo Information belonging to one level of the multilevel hierarchy.
+ */
+class TriangulationLevel<0> {
+ public:
+ /**
+ * Flags for the cells whether they are
+ * to be refined or not. The meaning
+ * what a cell is, is dimension specific,
+ * therefore also the length of this
+ * vector depends on the dimension: in
+ * one dimension, the length of this
+ * vector equals the length of the
+ * #lines# vector, in two dimensions
+ * that of the #quads# vector, etc.
+ */
+ vector<bool> refine_flags;
+
+ /**
+ * Levels and indices of the neighbors
+ * of the cells. Convention is, that the
+ * neighbors of the cell with index #i#
+ * are stored in the fields following
+ * $i*(2*real_space_dimension)$, e.g. in
+ * one spatial dimension, the neighbors
+ * of cell 0 are stored in #neighbors[0]#
+ * and #neighbors[1]#, the neighbors of
+ * cell 1 are stored in #neighbors[2]#
+ * and #neighbors[3]#, and so on.
+ *
+ * In neighbors, #neighbors[i].first# is
+ * the level, while #neighbors[i].first#
+ * is the index of the neighbor.
+ *
+ * If a neighbor does not exist (cell is
+ * at the boundary), #level=index=-1#
+ * is set.
+ *
+ * {\bf Conventions:} The #i#th neighbor
+ * of a cell is the one which shares
+ * the #i#th face (#Line# in 2D, #Quad#
+ * in 3D) of this cell.
+ *
+ * The neighbor of a cell has at most the
+ * same level as this cell, i.e. it may
+ * or may not be refined.
+ *
+ * In one dimension, a neighbor may have
+ * any level less or equal the level of
+ * this cell. If it has the same level,
+ * it may be refined an arbitrary number
+ * of times, but the neighbor pointer
+ * still points to the cell on the same
+ * level, while the neighbors of the
+ * childs of the neighbor may point to
+ * this cell or its children.
+ *
+ * In two and more dimensions, the
+ * neighbor is either on the same level
+ * and refined (in which case its children
+ * have neighbor pointers to this cell or
+ * its direct children), unrefined on
+ * the same level or one level down (in
+ * which case its neighbor pointer points
+ * to the mother cell of this cell).
+ */
+ vector<pair<int,int> > neighbors;
+
+ /**
+ * Reserve enough space to accomodate
+ * #total_cells# cells on this level.
+ * Since there are no #used# flags on this
+ * level, you have to give to total number
+ * of cells, not only the number of newly
+ * to accomodate ones, like in the
+ * #TriangulationLevel<N>::reserve_space#
+ * functions, with #N>0#.
+ *
+ * Since the
+ * number of neighbors per cell depends
+ * on the dimensions, you have to pass
+ * that additionally.
+ */
+ void reserve_space (const unsigned int total_cells,
+ const unsigned int dimension);
+
+ /**
+ * Check the memory consistency of the
+ * different containers. Should only be
+ * called with the prepro flag #DEBUG#
+ * set. The function should be called from
+ * the functions of the higher
+ * #TriangulationLevel# classes.
+ */
+ void monitor_memory (const unsigned int true_dimension) const;
+
+ /**
+ * Exception
+ */
+ DeclException3 (ExcMemoryWasted,
+ char*, int, int,
+ << "The container " << arg1 << " contains "
+ << arg2 << " elements, but it`s capacity is "
+ << arg3 << ".");
+ /**
+ * Exception
+ */
+ DeclException2 (ExcMemoryInexact,
+ int, int,
+ << "The containers have sizes " << arg1 << " and "
+ << arg2 << ", which is not as expected.");
+ /**
+ * Exception
+ */
+ DeclException0 (ExcUnusedMemoryAtEnd);
+};
+
+
+
+/**
+ Store all information which belongs to one level of the multilevel hierarchy.
+
+ In one dimension, this is a list of the lines associated with this level,
+ as well as a list with the indices of the children of these lines.
+ The #TriangulationsLevel# objects of higher dimensions are derived from
+ this one.
+
+ @memo Information belonging to one level of the multilevel hierarchy.
+ */
+class TriangulationLevel<1> : public TriangulationLevel<0> {
+ private:
+
+ /**
+ * This subclass groups together all that
+ * is needed to describe the lines on one
+ * level.
+ */
+ struct LinesData {
+ /**
+ * Vector of the lines belonging to
+ * this level. The index of the line
+ * on this level equals the index in
+ * this container, while the global
+ * index of a line is stored in the
+ * line itself.
+ */
+ vector<Line> lines;
+ /**
+ * Index of the first child of a line
+ * in the list on the next level.
+ * Since when lines are refined, both
+ * children are created at the same
+ * time, they are appended to the list
+ * on the next level after each other.
+ * We therefore only store the index
+ * of the first child, the second
+ * follows immediately afterwards.
+ *
+ * If a line has no children, -1 is
+ * stored in this list. A line is
+ * called active if it has no
+ * children. The function
+ * #TriaIterator::active()#
+ * tests for this.
+ */
+ vector<int> children;
+
+ /**
+ * Vector storing whether a line is
+ * used in the #lines# vector.
+ *
+ * Since it is difficult to delete
+ * elements in a #vector#, when an
+ * element is not needed any more
+ * (e.g. after derefinement), it is
+ * not deleted from the list, but
+ * rather the according #used# flag
+ * is set to #false#.
+ */
+ vector<bool> used;
+
+ /**
+ * Make available a field for user data,
+ * one bit per line. This field is usually
+ * used when an operation runs over all
+ * cells and needs information whether
+ * another cell (e.g. a neighbor) has
+ * already been processed.
+ *
+ * You can clear all used flags using
+ * #Triangulation<>::clear_user_flags()#.
+ */
+ vector<bool> user_flags;
+ };
+
+ public:
+ /**
+ * Data about the lines.
+ */
+ LinesData lines;
+
+ /**
+ * Assert that enough space is allocated
+ * to accomodate #new_lines# new lines.
+ * This function does not only call
+ * #vector::reserve()#, but does really
+ * append the needed elements.
+ * There are pendants for higher
+ * dimensions, which you have to call
+ * explicitely (they can't hand down the
+ * call because there is no easy relation
+ * between the number of new quads and
+ * the number of new lines, etc.). Also
+ * don't forget to call the
+ * #TriangulationLevel<0>::reserve_space#
+ * function.
+ */
+ void reserve_space (const unsigned int new_lines);
+
+ /**
+ * Check the memory consistency of the
+ * different containers. Should only be
+ * called with the prepro flag #DEBUG#
+ * set. The function should be called from
+ * the functions of the higher
+ * #TriangulationLevel# classes.
+ */
+ void monitor_memory (const unsigned int true_dimension) const;
+};
+
+
+
+
+/**
+ Store all information which belongs to one level of the multilevel hierarchy.
+
+ In 2D this is a vector of the lines and one of the
+ quads on this levels, as well as a the two associated vectors holding
+ information about the children of these lines and quads.
+
+ The vector of lines and their children is derived from
+ #TriangulationLevel<1>#.
+
+ @memo Information belonging to one level of the multilevel hierarchy.
+ */
+class TriangulationLevel<2> : public TriangulationLevel<1>
+{
+ /**
+ * This subclass groups together all that
+ * is needed to describe the quads on one
+ * level.
+ *
+ * It is fully analogous to the
+ * #LinesData# structure inherited from
+ * #Triangulation<1>#.
+ */
+ struct QuadsData {
+ /**
+ * Same as for the #lines# array.
+ */
+ vector<Quad> quads;
+ /**
+ * Same as for the #LineData::chilren#
+ * array, but since there are four
+ * children, the index points to the
+ * first while the other three are
+ * following immediately afterwards.
+ */
+ vector<int> children;
+
+ /**
+ * Same as for #LineData::used#.
+ */
+ vector<bool> used;
+
+ /**
+ * Same as for #LineData::used#.
+ */
+ vector<bool> user_flags;
+ };
+
+ public:
+ /**
+ * Data about the quads.
+ */
+ QuadsData quads;
+
+ /**
+ * Assert that enough space is allocated
+ * to accomodate #new_quads# new lines.
+ */
+ void reserve_space (const unsigned int new_quads);
+
+ /**
+ * Check the memory consistency of the
+ * different containers. Should only be
+ * called with the prepro flag #DEBUG#
+ * set. The function should be called from
+ * the functions of the higher
+ * #TriangulationLevel# classes.
+ */
+ void monitor_memory (const unsigned int true_dimension) const;
+};
+
+
+
+
+
+
+
+
+/*------------------------------------------------------------------------*/
+
+
+
+
+
+
+/**
+ This class implements some types which differ between the dimensions.
+ Declare it to have a template parameter, but do not actually declare
+ other types than those explicitely instantiated.
+ */
+template <int dim>
+class TriaDimensionInfo;
+
+
+/**
+ This class implements some types which differ between the dimensions.
+
+ A #line_iterator# is typdef'd to an iterator operating on the
+ #lines# member variable of a #Triangulation<1># object. An
+ #active_line_iterator# only operates on the active lines.
+ #raw_line_iterator# objects operate on all lines, used or not.
+
+ Since we are in one dimension, the following identities are declared:
+ \begin{verbatim}
+ typedef raw_line_iterator raw_cell_iterator;
+ typedef line_iterator cell_iterator;
+ typedef active_line_iterator active_cell_iterator;
+ \end{verbatim}
+
+ To enable the declaration of #begin_quad# and the like in
+ #Triangulation<1>#, the #quad_iterator#s are declared as
+ #void *#. Thus these types exist, but are useless and will
+ certainly make any involuntary use visible.
+ */
+class TriaDimensionInfo<1> {
+ public:
+ typedef TriaRawIterator<1,CellAccessor<1> > raw_line_iterator;
+ typedef TriaIterator<1,CellAccessor<1> > line_iterator;
+ typedef TriaActiveIterator<1,CellAccessor<1> > active_line_iterator;
+
+ typedef void * raw_quad_iterator;
+ typedef void * quad_iterator;
+ typedef void * active_quad_iterator;
+
+ typedef raw_line_iterator raw_cell_iterator;
+ typedef line_iterator cell_iterator;
+ typedef active_line_iterator active_cell_iterator;
+};
+
+
+/**
+ This class implements some types which differ between the dimensions.
+
+ A #line_iterator# is typdef'd to an iterator operating on the
+ #lines# member variable of a #Triangulation<1># object. An
+ #active_line_iterator# only operates on the active lines.
+ #raw_line_iterator# objects operate on all lines, used or not.
+ Using #active_line_iterator#s may not be particularly useful since it
+ only operates on unrefined lines. However, also refined lines may bound
+ unrefined cells if the neighboring cell is refined once more than the
+ present one.
+
+ Similarly, #quad_iterator#, #raw_quad_iterator# and
+ #active_quad_iterator# are declared.
+
+ Since we are in two dimension, the following identities are declared:
+ \begin{verbatim}
+ typedef raw_quad_iterator raw_cell_iterator;
+ typedef quad_iterator cell_iterator;
+ typedef active_quad_iterator active_cell_iterator;
+ \end{verbatim}
+ */
+class TriaDimensionInfo<2> {
+ public:
+ typedef TriaRawIterator<2,LineAccessor<2> > raw_line_iterator;
+ typedef TriaIterator<2,LineAccessor<2> > line_iterator;
+ typedef TriaActiveIterator<2,LineAccessor<2> > active_line_iterator;
+
+ typedef TriaRawIterator<2,CellAccessor<2> > raw_quad_iterator;
+ typedef TriaIterator<2,CellAccessor<2> > quad_iterator;
+ typedef TriaActiveIterator<2,CellAccessor<2> > active_quad_iterator;
+
+ typedef raw_quad_iterator raw_cell_iterator;
+ typedef quad_iterator cell_iterator;
+ typedef active_quad_iterator active_cell_iterator;
+};
+
+
+
+
+
+/*------------------------------------------------------------------------*/
+
+
+
+/**
+ #Triangulation#s denote a hierarchy of levels of elements which together
+ form a region in #dim# spatial dimensions.
+
+ This class is written to be as independent of the dimension as possible
+ (thus the complex construction of the #TriangulationLevel# classes) to
+ allow code-sharing, to allow reducing the need to mirror changes in the code
+ for one dimenion to the code for other dimensions. Nonetheless, some of
+ the functions are dependent of the dimension and there only exist
+ specialized versions for distinct dimensions.
+
+
+ {\bf Structure and iterators}
+
+ The actual data structure of a #Triangulation# object is rather complex
+ and quite inconvenient if one attempted to operate on it directly, since
+ data is spread over quite a lot of arrays and other places. However,
+ there are ways powerful enough to work on these data structures
+ without knowing their exact relations. This is done through the
+ concept of iterators (see the STL documentation and \Ref{TriaRawIterator}).
+ In order to make things as easy and dimension independent as possible,
+ use of class local typedefs is made, see below.
+
+ In the base class #TriaDimensionInfo#, a #Cell# is typedef'd to be whatever
+ is reasonable for a cell in the respective dimension, i.e. a #Line# in
+ one dimension, a #Quad# in two dimensions, and so on.
+
+ The #Triangulation# class provides iterator which enable looping over all
+ lines, cells,
+ etc without knowing the exact representation used to describe them. Their
+ names are typedef's in the #TriaDimensionInfo# base class (thus making them
+ local types to this class) and are as follows:
+
+ #raw_line_iterator#: loop over all lines, used or not (declared for
+ all dimensions).
+
+ #line_iterator#: loop over all used lines (declared for all dimensions).
+
+ #active_line_iterator#: loop over all active lines (declared for all
+ dimensions).
+
+ #raw_quad_iterator#: loop over all quads, used or not (declared only
+ for #dim>=2#).
+
+ #quad_iterator#: loop over all quads (declared only for #dim#>=2).
+
+ #active_quad_iterator#: loop over all active quads (declared only for
+ #dim#>=2).
+
+ Additionaly, for #dim#==1, the following identities hold:
+ \begin{verbatim}
+ typedef raw_line_iterator raw_cell_iterator;
+ typedef line_iterator cell_iterator;
+ typedef active_line_iterator active_cell_iterator;
+ \end{verbatim}
+ while for #dim#==2
+ \begin{verbatim}
+ typedef quad_line_iterator raw_cell_iterator;
+ typedef quad_iterator cell_iterator;
+ typedef active_quad_iterator active_cell_iterator;
+ \end{verbatim}
+
+ By using the cell iterators, you can write code nearly independent of
+ the spatial dimension.
+
+ The #Triangulation# class offers functions like #begin_active# which gives
+ you an iterator to the first active cell. There are quite a lot of functions
+ returning iterators. Take a look at the class doc to get an overview.
+
+ Usage of these iterators works mostly like with the STL iterators. Some
+ examples taken from the #Triangulation# source code follow.
+ \begin{itemize}
+ \item {\it Counting the number of cells on a specific level}
+ \begin{verbatim}
+ template <int dim>
+ int Triangulation<dim>::n_cells (const int level) const {
+ cell_iterator cell = begin (level),
+ endc = (level == levels.size()-1 ?
+ cell_iterator(end()) :
+ begin (level+1));
+ int n=0;
+ for (; cell!=endc; ++cell)
+ ++n;
+ return n;
+ };
+ \end{verbatim}
+ Another way which uses the STL #distance# function would be to write
+ \begin{verbatim}
+ template <int dim>
+ int Triangulation<dim>::n_cells (const int level) const {
+ int n=0;
+ distance (begin(level),
+ (level == levels.size()-1 ?
+ cell_iterator(end()) :
+ begin (level+1)),
+ n);
+ return n;
+ };
+ \end{verbatim}
+ Unfortunately, #g++# presently (version 2.7.2) fails to find the right
+ #distance# template instantiation; it seems we have to wait for future
+ #g++# versions :-(
+
+ \item {\it Refining all cells of a triangulation}
+ \begin{verbatim}
+ template <int dim>
+ void Triangulation<dim>::refine_global () {
+ active_cell_iterator cell = begin_active(),
+ endc = end();
+
+ for (; cell != endc; ++cell)
+ cell->set_refine_flag ();
+ execute_refinement ();
+ };
+ \end{verbatim}
+ \end{itemize}
+
+
+ {\bf Usage}
+
+ Usage of a #Triangulation# is mainly done through the use of iterators.
+ An example probably shows best how to use it:
+ \begin{verbatim}
+ void main () {
+ Triangulation<2> tria;
+
+ // read in a coarse grid file
+
+ // we want to log the
+ // refinement history
+ ofstream history ("mesh.history");
+
+ // refine first cell
+ tria.begin_active()->set_refine_flag();
+ tria.save_refine_flags (history);
+ tria.execute_refinement ();
+
+ // refine first active cell
+ // on coarsest level
+ tria.begin_active()->set_refine_flag ();
+ tria.save_refine_flags (history);
+ tria.execute_refinement ();
+
+ Triangulation<2>::active_cell_iterator cell;
+ for (int i=0; i<17; ++i)
+ {
+ // refine the presently
+ // second last cell 17
+ // times
+ cell = tria.last_active(tria.n_levels()-1);
+ --cell;
+ cell->set_refine_flag ();
+ tria.save_refine_flags (history);
+ tria.execute_refinement ();
+ };
+ // output the grid
+ ofstream out("grid.1");
+ tria.print_gnuplot (out);
+ };
+ \end{verbatim}
+
+
+ {\bf History of a triangulation}
+
+ It is possible to reconstruct a grid from its refinement history, which
+ can be stored and loaded through the #save_refine_flags# and
+ #load_refine_flags# functions. Normally, the code will look like this:
+ \begin{verbatim}
+ // open output file
+ ofstream history("mesh.history");
+ // do 10 refinement steps
+ for (int step=0; step<10; ++step) {
+ ...;
+ // flag cells according to some criterion
+ ...;
+ tria.save_refine_flags (history);
+ tria.execute_refinement ();
+ };
+ \end{verbatim}
+
+ If you want to re-create the grid from the stored information, you write:
+ \begin{verbatim}
+ // open input file
+ ifstream history("mesh.history");
+ // do 10 refinement steps
+ for (int step=0; step<10; ++step) {
+ tria.load_refine_flags (history);
+ tria.execute_refinement ();
+ };
+ \end{verbatim}
+
+ You may write other information to the output file between different sets
+ of refinement information, as long as you read it upon re-creation of the
+ grid.
+
+
+ {\bf User flags}
+
+ A triangulation offers one bit per line, quad, etc for user data.
+ This field can be
+ accessed as all other data using iterators. Normally, this user flag is
+ used if an algorithm walks over all cells and needs information whether
+ another cell, e.g. a neighbor, has already been processed. It can also
+ be used to flag the lines subject to constraints in 2D, as for example the
+ functions in the #DoFHandler# classes do.
+
+ There are two functions, #save_user_flags# and #load_user_flags# which
+ write and read these flags to and from a stream. Unlike
+ #save_refine_flags# and #load_refine_flags#, these two functions store
+ and read the flags of all used lines, quads, etc, not only of the
+ active ones (well, activity is a concept which really only applies to
+ cells, not for example to lines in 2D, so the abovementioned generalisation
+ to {\it all} lines, quads, etc seems plausible).
+
+ If you want to store more specific user flags, you can use the functions
+ #save_user_flags_line# and #load_user_flags_line# and the generalizations
+ for quads, etc.
+
+
+ It is convention to clear the user flags using the
+ #Triangulation<>::clear_user_flags()# function before usage, since it is
+ often necessary to use the flags in more than one function consecutively and
+ is then error prone to dedicate one of these to clear the flags.
+
+ It is recommended that a functions using the flags states so in its
+ documentation.
+
+
+ {\bf Boundary approximation}
+
+ You can specify a boundary function: if a new vertex is created on a
+ side or face at the boundary, this function is used to compute where
+ it will be placed. See \Ref{Boundary} for the details. Usage with
+ the #Triangulation# object is then like this (let #Ball# be a class
+ derived from #Boundary<2>#):
+ \begin{verbatim}
+ void main () {
+ Triangulation<2> tria;
+ // set the boundary function
+ Ball ball;
+ tria.set_boundary (&ball);
+
+ // read some coarse grid
+
+
+ Triangulation<2>::active_cell_iterator cell, endc;
+ for (int i=0; i<8; ++i)
+ {
+ cell = tria.begin_active();
+ endc = tria.end();
+
+ // refine all
+ // boundary cells
+ for (; cell!=endc; ++cell)
+ if (cell->at_boundary())
+ cell->set_refine_flag();
+
+ tria.execute_refinement();
+ };
+ };
+ \end{verbatim}
+
+ You should take note of one caveat: if you have concave boundaries, you
+ must make sure that a new boundary vertex does not lie to much inside the
+ to be refined cell. The reason is that the center vertex is placed at the
+ point which is the arithmetic mean of the eight surrounding vertices.
+ Therefore if your new boundary vertex is too near the center of the old
+ quadrilateral or hexahedron, the distance to the midpoint vertex will become
+ too small, thus generating distorted cells. Remedy: you have to take care
+ of such situations when defining the coarse grid.
+
+
+ {\bf Implementational conventions for two spatial dimensions}
+
+ There is a convention about the direction of the bounding lines of quads in
+ 2D. The direction of a line is the direction of point 0 towards point 1. We
+ define, that allowed cells contain of lines of which the direction is
+ as follows:
+
+ 2
+ 3--->---2
+ | |
+ 3^ ^1
+ | |
+ 0--->---1
+ 0
+ The number of the vertices and lines is also indicated. This orientation of
+ lines has to be checked/generated upon construction of a grid and is
+ preserved upon refinement.
+
+ Further we define, that child lines have the same direction as their parent,
+ i.e. that #subline(0).vertex(0)==line.vertex(0)# and
+ #subline(1).vertex(1)==line.vertex(1)#. This also implies, that the
+ first subline (#subline(0)#) is the one at vertex(0) of the old line.
+
+ Similarly we define, that the four children of a quad are adjacent to the
+ vertex with the same number of the old quad.
+
+
+ {\bf Warning}
+
+ It seems impossible to preserve #const#ness of a triangulation through
+ iterator usage. Thus, if you declare pointers to a #const# triangulation
+ object, you should be well aware that you might involuntarily alter the
+ data stored in the triangulation.
+
+ @memo Implementation of a multilevel triangulation of a domain
+ @see TriaRawIterator
+ @author Wolfgang Bangerth, 1998
+ */
+template <int dim>
+class Triangulation : public TriaDimensionInfo<dim> {
+ public:
+ /**
+ * Create a triangulation and create
+ * the first level of the hierarchy.
+ * Do not create any cells.
+ */
+ Triangulation ();
+
+ /**
+ * Delete the object and all levels of
+ * the hierarchy.
+ */
+ ~Triangulation ();
+
+ /**
+ * Assign a boundary object to the
+ * triangulation, which is used to find
+ * the point where to place new vertices
+ * on the boundary. Ownership of the
+ * object remains with the caller of this
+ * function, i.e. you have to make sure
+ * that it is not destroyed before
+ * #Triangulation<>::execute_refinement()#
+ * is called the last time.
+ */
+ void set_boundary (const Boundary<dim> *boundary_object);
+
+ /**
+ * Initialize the triangulation with a
+ * unit hypercube (unit line in 1D,
+ * unit square in 2D, etc) consisting
+ * of exactly one cell.
+ *
+ * The triangulation needs to be void
+ * upon calling this function.
+ */
+ void create_unit_hypercube ();
+
+
+
+ /**
+ * @name Mesh refinement
+ */
+ /*@{*/
+ /**
+ * Flag all active cells for refinement.
+ * This will refine
+ * all cells of all levels which are not
+ * already refined (i.e. only cells are
+ * refined which do not yet have
+ * children). The cells are only flagged,
+ * not refined, thus you have the chance
+ * to save the refinement flags.
+ */
+ void set_all_refine_flags ();
+
+ /**
+ * Refine all cells #times# times, by
+ * alternatingly calling #refine_global()#
+ * and #execute_refinement()#.
+ * This function actually starts the
+ * refinement process, so you have no way
+ * to store the refinement flags.
+ */
+ void refine_global (const unsigned int times);
+
+ /**
+ * Refine all cells on all levels which
+ * were previously flagged for refinement.
+ *
+ * The function resets all refinement
+ * flags to false.
+ *
+ * This function is dimension specific.
+ */
+ void execute_refinement ();
+ /*@}*/
+
+ /**
+ * @name History of a triangulation
+ */
+ /*@{*/
+ /**
+ * Save the addresses of the cells which
+ * are flagged for refinement to #out#.
+ * The addresses are stored in a binary
+ * format: for each active cell, a #1#
+ * bit is stored if the flag is flagged
+ * for refinement, a #0# bit otherwise.
+ * The bits are stored as #unsigned char#,
+ * thus avoiding endianess. They are
+ * written to #out# in plain text, thus
+ * amounting to 3.6 bits per active cell
+ * on the overage. Other information
+ * (three numbers) is stored as plain text
+ * as well. The format should therefore be
+ * interplatform compatible.
+ *
+ * For usage, read the general
+ * documentation for this class.
+ */
+ void save_refine_flags (ostream &out) const;
+
+ /**
+ * Read the information stored by
+ * #save_refine_flags#.
+ */
+ void load_refine_flags (istream &in);
+ /*@}*/
+
+
+ /**
+ * @name User flag handling
+ */
+ /*@{*/
+ /**
+ * Clear all user flags.
+ */
+ void clear_user_flags ();
+
+ /**
+ * Save all user flags. See the general
+ * documentation for this class
+ * and the documentation for the
+ * #save_refine_flags# for more
+ * details.
+ */
+ void save_user_flags (ostream &out) const;
+
+ /**
+ * Read the information stored by
+ * #save_user_flags#.
+ */
+ void load_user_flags (istream &in);
+
+ /**
+ * Save the user flags on lines.
+ */
+ void save_user_flags_line (ostream &out) const;
+
+ /**
+ * Load the user flags located on lines.
+ */
+ void load_user_flags_line (istream &in);
+
+ /**
+ * Save the user flags on quads.
+ */
+ void save_user_flags_quad (ostream &out) const;
+
+ /**
+ * Load the user flags located on quads.
+ */
+ void load_user_flags_quad (istream &in);
+ /*@}*/
+
+
+ /**
+ * @name Cell iterator functions
+ */
+ /*@{*/
+ /**
+ * Return iterator to the first cell, used
+ * or not, on level #level#. If a level
+ * has no cells, a past-the-end iterator
+ * is returned.
+ *
+ * This function calls #begin_raw_line#
+ * in 1D and #begin_raw_quad# in 2D.
+ */
+ raw_cell_iterator begin_raw (const unsigned int level = 0) const;
+
+ /**
+ * Return iterator to the first used cell
+ * on level #level#.
+ *
+ * This function calls #begin_line#
+ * in 1D and #begin_quad# in 2D.
+ */
+ cell_iterator begin (const unsigned int level = 0) const;
+
+ /**
+ * Return iterator to the first active
+ * cell on level #level#.
+ *
+ * This function calls #begin_active_line#
+ * in 1D and #begin_active_quad# in 2D.
+ */
+ active_cell_iterator begin_active(const unsigned int level = 0) const;
+
+ /**
+ * Return iterator past the end; this
+ * iterator serves for comparisons of
+ * iterators with past-the-end or
+ * before-the-beginning states.
+ *
+ * This function calls #end_line#
+ * in 1D and #end_quad# in 2D.
+ */
+ raw_cell_iterator end () const;
+
+ /**
+ * Return an iterator pointing to the
+ * last cell, used or not.
+ *
+ * This function calls #last_raw_line#
+ * in 1D and #last_raw_quad# in 2D.
+ */
+ raw_cell_iterator last_raw () const;
+
+ /**
+ * Return an iterator pointing to the last
+ * cell of the level #level#, used or not.
+ *
+ * This function calls #last_raw_line#
+ * in 1D and #last_raw_quad# in 2D.
+ */
+ raw_cell_iterator last_raw (const unsigned int level) const;
+
+ /**
+ * Return an iterator pointing to the last
+ * used cell.
+ *
+ * This function calls #last_line#
+ * in 1D and #last_quad# in 2D.
+ */
+ cell_iterator last () const;
+
+ /**
+ * Return an iterator pointing to the last
+ * used cell on level #level#.
+ *
+ * This function calls #last_line#
+ * in 1D and #last_quad# in 2D.
+ */
+ cell_iterator last (const unsigned int level) const;
+
+ /**
+ * Return an iterator pointing to the last
+ * active cell.
+ *
+ * This function calls #last_active_line#
+ * in 1D and #last_active_quad# in 2D.
+ */
+ active_cell_iterator last_active () const;
+
+ /**
+ * Return an iterator pointing to the last
+ * active cell on level #level#.
+ *
+ * This function calls #last_active_line#
+ * in 1D and #last_active_quad# in 2D.
+ */
+ active_cell_iterator last_active (const unsigned int level) const;
+ //@}
+
+ /*---------------------------------------*/
+
+ /**
+ * @name Line iterator functions
+ */
+ /*@{*/
+ /**
+ * Return iterator to the first line, used
+ * or not, on level #level#. If a level
+ * has no lines, a past-the-end iterator
+ * is returned.
+ */
+ raw_line_iterator
+ begin_raw_line (const unsigned int level = 0) const;
+
+ /**
+ * Return iterator to the first used line
+ * on level #level#.
+ */
+ line_iterator
+ begin_line (const unsigned int level = 0) const;
+
+ /**
+ * Return iterator to the first active
+ * line on level #level#.
+ */
+ active_line_iterator
+ begin_active_line(const unsigned int level = 0) const;
+
+ /**
+ * Return iterator past the end; this
+ * iterator serves for comparisons of
+ * iterators with past-the-end or
+ * before-the-beginning states.
+ */
+ raw_line_iterator
+ end_line () const;
+
+ /**
+ * Return an iterator pointing to the
+ * last line, used or not.
+ */
+ raw_line_iterator
+ last_raw_line () const;
+
+ /**
+ * Return an iterator pointing to the last
+ * line of the level #level#, used or not.
+
+ */
+ raw_line_iterator
+ last_raw_line (const unsigned int level) const;
+
+ /**
+ * Return an iterator pointing to the last
+ * used line.
+ */
+ line_iterator
+ last_line () const;
+
+ /**
+ * Return an iterator pointing to the last
+ * used line on level #level#.
+ */
+ line_iterator
+ last_line (const unsigned int level) const;
+
+ /**
+ * Return an iterator pointing to the last
+ * active line.
+ */
+ active_line_iterator
+ last_active_line () const;
+
+ /**
+ * Return an iterator pointing to the last
+ * active line on level #level#.
+ */
+ active_line_iterator
+ last_active_line (const unsigned int level) const;
+ /*@}*/
+
+ /*---------------------------------------*/
+
+ /**
+ * @name Quad iterator functions*/
+ /*@{
+ */
+ /**
+ * Return iterator to the first quad, used
+ * or not, on level #level#. If a level
+ * has no quads, a past-the-end iterator
+ * is returned.
+ */
+ raw_quad_iterator
+ begin_raw_quad (const unsigned int level = 0) const;
+
+ /**
+ * Return iterator to the first used quad
+ * on level #level#.
+ */
+ quad_iterator
+ begin_quad (const unsigned int level = 0) const;
+
+ /**
+ * Return iterator to the first active
+ * quad on level #level#.
+ */
+ active_quad_iterator
+ begin_active_quad(const unsigned int level = 0) const;
+
+ /**
+ * Return iterator past the end; this
+ * iterator serves for comparisons of
+ * iterators with past-the-end or
+ * before-the-beginning states.
+ */
+ raw_quad_iterator
+ end_quad () const;
+
+ /**
+ * Return an iterator pointing to the
+ * last quad, used or not.
+ */
+ raw_quad_iterator
+ last_raw_quad () const;
+
+ /**
+ * Return an iterator pointing to the last
+ * quad of the level #level#, used or not.
+
+ */
+ raw_quad_iterator
+ last_raw_quad (const unsigned int level) const;
+
+ /**
+ * Return an iterator pointing to the last
+ * used quad.
+ */
+ quad_iterator
+ last_quad () const;
+
+ /**
+ * Return an iterator pointing to the last
+ * used quad on level #level#.
+ */
+ quad_iterator
+ last_quad (const unsigned int level) const;
+
+ /**
+ * Return an iterator pointing to the last
+ * active quad.
+ */
+ active_quad_iterator
+ last_active_quad () const;
+
+ /**
+ * Return an iterator pointing to the last
+ * active quad on level #level#.
+ */
+ active_quad_iterator
+ last_active_quad (const unsigned int level) const;
+ /*@}*/
+
+ /*---------------------------------------*/
+
+ /**
+ * @name Input/Output functions
+ */
+ /*@{*/
+ /**
+ * Print the triangulation in GNUPLOT
+ * format to #out#.
+ */
+ void print_gnuplot (ostream &) const;
+
+ /**
+ * Print level #level# in GNUPLOT
+ * format to #out#.
+ */
+ void print_gnuplot (ostream &, const unsigned int level) const;
+
+ /**
+ * Print cell #cell# in GNUPLOT format
+ * to #out#.
+ */
+ void print_gnuplot (ostream &, const active_cell_iterator &cell) const;
+ /*@}
+ */
+
+
+ /**
+ * @name Information about the triangulation
+ */
+ /*@{*/
+ /**
+ * Return total number of used lines,
+ * active or not.
+ */
+ unsigned int n_lines () const;
+
+ /**
+ * Return total number of used lines,
+ * active or not on level #level#.
+ */
+ unsigned int n_lines (const unsigned int level) const;
+
+ /**
+ * Return total number of active lines,
+ * active or not.
+ */
+ unsigned int n_active_lines () const;
+
+ /**
+ * Return total number of active lines,
+ * active or not on level #level#.
+ */
+ unsigned int n_active_lines (const unsigned int level) const;
+
+ /**
+ * Return total number of used quads,
+ * active or not.
+ */
+ unsigned int n_quads () const;
+
+ /**
+ * Return total number of used quads,
+ * active or not on level #level#.
+ */
+ unsigned int n_quads (const unsigned int level) const;
+
+ /**
+ * Return total number of active quads,
+ * active or not.
+ */
+ unsigned int n_active_quads () const;
+
+ /**
+ * Return total number of active quads,
+ * active or not on level #level#.
+ */
+ unsigned int n_active_quads (const unsigned int level) const;
+
+ /**
+ * Return total number of used cells,
+ * active or not.
+ * Maps to #n_lines()# in one space
+ * dimension and so on.
+ */
+ unsigned int n_cells () const;
+
+ /**
+ * Return total number of used cells,
+ * active or not, on level #level#.
+ * Maps to #n_lines(level)# in one space
+ * dimension and so on.
+ */
+ unsigned int n_cells (const unsigned int level) const;
+
+ /**
+ * Return total number of active cells.
+ * Maps to #n_active_lines()# in one space
+ * dimension and so on.
+ */
+ unsigned int n_active_cells () const;
+
+ /**
+ * Return total number of active cells
+ * on level #level#.
+ * Maps to #n_active_lines(level)# in one space
+ * dimension and so on.
+ */
+ unsigned int n_active_cells (const unsigned int level) const;
+
+ /**
+ * Return number of levels in use.
+ */
+ unsigned int n_levels () const;
+
+ /**
+ * Return the maximum number of cells meeting
+ * at a common vertex. Since this number is
+ * an invariant under refinement, only the cells
+ * on the coarsest level are considered. The
+ * operation is thus reasonably fast. The
+ * invariance is only true for sufficiently
+ * many cells in the coarsest triangulation
+ * (e.g. for a single cell one would be returned),
+ * so a minimum of four is returned in
+ * two dimensions, 8 in three dimensions, etc,
+ * which is how many cells meet if the
+ * triangulation is refined.
+ *
+ * In one space dimension, two is returned.
+ */
+ unsigned int max_adjacent_cells () const;
+ /*@}*/
+
+
+ /**
+ * @name Exceptions
+ */
+ //@{
+ /**
+ * Exception
+ */
+ DeclException1 (ExcInvalidLevel,
+ int,
+ << "The given level " << arg1
+ << " is not in the valid range!");
+ /**
+ * Exception
+ */
+ DeclException0 (ExcCellShouldBeUnused);
+ /**
+ * Exception
+ */
+ DeclException0 (ExcTooFewVerticesAllocated);
+ /**
+ * Exception
+ */
+ DeclException0 (ExcUncaughtState);
+ /**
+ * Exception
+ */
+ DeclException0 (ExcFunctionNotUseful);
+ /**
+ * Exception
+ */
+ DeclException2 (ExcGridsDoNotMatch,
+ int, int,
+ << "The present grid has " << arg1 << " active cells, "
+ << "but the one in the file had " << arg2);
+ DeclException0 (ExcGridReadError);
+ //@}
+ protected:
+ /**
+ * Prepare the refinement process by
+ * allocating enough space, fixing the
+ * closure of the refinement in #dim>=2#
+ * (make sure that no two cells are
+ * adjacent with a refinement level
+ * differing with more than one), etc.
+ * This function is mostly dimension
+ * independent.
+ */
+
+ void prepare_refinement ();
+
+ /**
+ * Array of pointers pointing to the
+ * #TriangulationLevel<dim># objects
+ * storing the data on the different
+ * levels.
+ *
+ * Usage is like #levels[3]->quads#.
+ */
+ vector<TriangulationLevel<dim>*> levels;
+
+ /**
+ * Array of the vertices of this
+ * triangulation.
+ */
+ vector<Point<dim> > vertices;
+
+ /**
+ * Array storing a bit-pattern which
+ * vertices are used.
+ */
+ vector<bool> vertices_used;
+
+ /**
+ * Pointer to a boundary object.
+ */
+ const Boundary<dim> *boundary;
+
+
+ // Friendship includes local classes.
+ friend class TriaAccessor<dim>;
+ friend class LineAccessor<dim>;
+ friend class QuadAccessor<dim>;
+
+ friend class CellAccessor<1>;
+ friend class CellAccessor<2>;
+
+ friend class TriaRawIterator<1,LineAccessor<1> >;
+ friend class TriaRawIterator<1,CellAccessor<1> >;
+ friend class TriaRawIterator<2,LineAccessor<2> >;
+ friend class TriaRawIterator<2,QuadAccessor<2> >;
+ friend class TriaRawIterator<2,CellAccessor<2> >;
+
+ friend class DoFHandler<dim>;
+};
+
+
+
+
+
+
+/*---------------------------- tria.h ---------------------------*/
+/* end of #ifndef __tria_H */
+#endif
+/*---------------------------- tria.h ---------------------------*/
+
+
+
+
--- /dev/null
+/*---------------------------- tria_accessor.h ---------------------------*/
+/* $Id$ */
+#ifndef __tria_accessor_H
+#define __tria_accessor_H
+/*---------------------------- tria_accessor.h ---------------------------*/
+
+
+#include <basic/exceptions.h>
+
+
+// forward declaration needed
+class Line;
+class Quad;
+template <int dim> class Point;
+
+
+template <int dim> class TriaAccessor;
+template <int dim> class LineAccessor;
+template <int dim> class QuadAccessor;
+template <int dim> class CellAccessor;
+
+template <int dim> class DoFCellAccessor;
+template <int dim, class BaseClass> class DoFLineAccessor;
+
+template <int dim, class Accessor> class TriaRawIterator;
+template <int dim, class Accessor> class TriaIterator;
+template <int dim, class Accessor> class TriaActiveIterator;
+
+template <int dim> class Triangulation;
+
+
+
+
+
+
+
+/**
+ The three states an iterator can be in: valid, past-the-end and
+ invalid.
+ */
+enum IteratorState { valid, past_the_end, invalid };
+
+
+
+
+
+/**
+ Implements the accessor class descibed in the documentation of
+ the iterator classes (see \Ref{TriaRawIterator}.
+
+ This class offers only the basic functionality (stores the necessary
+ data members, offers comparison operators and the like), but has no
+ functionality to actually dereference data. This is done in the derived
+ classes.
+ */
+template <int dim>
+class TriaAccessor {
+ protected:
+ /**
+ * Constructor. Protected, thus
+ * only callable from friend
+ * classes.
+ */
+ TriaAccessor (Triangulation<dim> *parent = 0,
+ const int level = -1,
+ const int index = -1,
+ const void * = 0) :
+ present_level (level),
+ present_index (index),
+ tria (parent) {};
+
+
+
+ /**
+ * Copy operator. Since this is only
+ * called from iterators, do not
+ * return anything, since the
+ * iterator will return itself.
+ *
+ * This method is protected, since it
+ * is only to be called from the
+ * iterator class.
+ */
+ void copy_from (const TriaAccessor &);
+
+ /**
+ * Copy operator. This is normally
+ * used in a context like
+ * #iterator a,b; *a=*b;#. Since
+ * the meaning is to copy the object
+ * pointed to by #b# to the object
+ * pointed to by #a# and since
+ * accessors are not real but
+ * virtual objects, this operation
+ * is not useful for iterators on
+ * triangulations. We declare this
+ * function here private, thus it may
+ * not be used from outside.
+ * Furthermore it is not implemented
+ * and will give a linker error if
+ * used anyway.
+ */
+ void operator = (const TriaAccessor *);
+
+ /**
+ * Same as above.
+ */
+ TriaAccessor &operator = (const TriaAccessor &);
+
+ public:
+ /**
+ * Compare for equality.
+ *
+ * This method should be protected,
+ * since it is only to be called from
+ * the iterator class. Due to problems
+ * with the STL, we have to make it
+ * public, so don't use it from
+ * non-friend classes!
+ */
+ bool operator == (const TriaAccessor &) const;
+
+ /**
+ * Compare for inequality.
+ *
+ * This method should be protected,
+ * since it is only to be called from
+ * the iterator class. Due to problems
+ * with the STL, we have to make it
+ * public, so don't use it from
+ * non-friend classes!
+ */
+ bool operator != (const TriaAccessor &) const;
+
+ public:
+ typedef void* LocalData;
+ /**@ name Iterator address and state
+ */
+ /*@{*/
+ /**
+ * Returns the level the element
+ * pointed to belongs to.
+ */
+ int level () const;
+
+ /**
+ * Returns the index of the element
+ * presently pointed to on the
+ * present level.
+ */
+ int index () const;
+ /**
+ * Return the state of the iterator.
+ * For the different states an accessor
+ * can be in, refer to the
+ * \Ref{TriaRawIterator} documentation.
+ */
+ IteratorState state () const;
+ /*@}*/
+
+ /**@name Exceptions for derived classes
+ */
+ /*@{*/
+ /**
+ * Exception
+ */
+ DeclException0 (ExcCellNotUsed);
+ /**
+ * Exception
+ */
+ DeclException0 (ExcRefineCellNotUsed);
+ /**
+ * Exception
+ */
+ DeclException0 (ExcRefineCellNotActive);
+ /**
+ * Exception
+ */
+ DeclException1 (ExcInvalidNeighbor,
+ int,
+ << "Neighbor indices must be between 0 and 2^dim-1, but "
+ << "yours was " << arg1);
+ /**
+ * Exception
+ */
+ DeclException0 (ExcUnusedCellAsChild);
+ /**
+ * Exception
+ */
+ DeclException0 (ExcUnusedCellAsNeighbor);
+ /**
+ * Exception
+ */
+ DeclException3 (ExcInvalidIndex,
+ int,
+ int,
+ int,
+ << "Invalid index " << arg1
+ << ", index must be between " << arg2
+ << " and " << arg3 << ".");
+ /**
+ * Exception
+ */
+ DeclException0 (ExcUncaughtCase);
+ /**
+ * Exception
+ */
+ DeclException0 (ExcDereferenceInvalidObject);
+ /*@}*/
+
+ protected:
+ /**
+ * Used to store the level presently
+ * pointed to.
+ */
+ int present_level;
+
+ /**
+ * Used to store the index of the
+ * element presently pointed to on
+ * the level presentl used.
+ */
+ int present_index;
+
+ /**
+ * Pointer to the triangulation which
+ * we act on.
+ */
+ Triangulation<dim> *tria;
+
+ friend class TriaRawIterator<1,LineAccessor<1> >;
+ friend class TriaRawIterator<1,CellAccessor<1> >;
+ friend class TriaRawIterator<2,LineAccessor<2> >;
+ friend class TriaRawIterator<2,QuadAccessor<2> >;
+ friend class TriaRawIterator<2,CellAccessor<2> >;
+
+ friend class TriaIterator<1,LineAccessor<1> >;
+ friend class TriaIterator<1,CellAccessor<1> >;
+ friend class TriaIterator<2,LineAccessor<2> >;
+ friend class TriaIterator<2,QuadAccessor<2> >;
+ friend class TriaIterator<2,CellAccessor<2> >;
+
+ friend class TriaActiveIterator<1,LineAccessor<1> >;
+ friend class TriaActiveIterator<1,CellAccessor<1> >;
+ friend class TriaActiveIterator<2,LineAccessor<2> >;
+ friend class TriaActiveIterator<2,QuadAccessor<2> >;
+ friend class TriaActiveIterator<2,CellAccessor<2> >;
+
+ friend class TriaRawIterator<1,DoFCellAccessor<1> >;
+ friend class TriaRawIterator<2,DoFCellAccessor<2> >;
+ friend class TriaRawIterator<2,DoFLineAccessor<2,LineAccessor<2> > >;
+ friend class TriaIterator<1,DoFCellAccessor<1> >;
+ friend class TriaIterator<2,DoFCellAccessor<2> >;
+ friend class TriaIterator<2,DoFLineAccessor<2,LineAccessor<2> > >;
+};
+
+
+
+
+extern TriaAccessor<1> __dummy1; // to calm down gcc2.7
+extern TriaAccessor<2> __dummy2; // to calm down gcc2.7
+
+
+
+/**
+ Accessor to dereference the data of lines. This accessor is used to
+ point to lines in #dim# space dimensions. There is a derived class
+ for lines in one space dimension, in which case a line is also a cell
+ and thus has much more functionality than in lower dimensions.
+ */
+template <int dim>
+class LineAccessor : public TriaAccessor<dim> {
+ public:
+ /**
+ * Constructor.
+ */
+ LineAccessor (Triangulation<dim> *parent = 0,
+ const int level = -1,
+ const int index = -1,
+ const void *local_data = 0) :
+ TriaAccessor<dim> (parent, level, index, local_data) {};
+
+ /**
+ * Copy the data of the given line.
+ */
+ void set (const Line &l) const;
+
+ /**
+ * Return the index of vertex #i=0,1#
+ * of a line.
+ */
+ int vertex_index (const unsigned int i) const;
+
+ /**
+ * Return a reference (not an iterator!)
+ * to the #i#th vertex.
+ */
+ Point<dim> & vertex (const unsigned int i) const;
+
+ /**
+ * Test for the element being used
+ * or not.
+ */
+ bool used () const;
+
+ /**
+ * Set the #used# flag.
+ */
+ void set_used_flag () const;
+
+ /**
+ * Clear the #used# flag.
+ */
+ void clear_used_flag () const;
+
+ /**
+ * Return whether the user flag
+ * is set or not.
+ */
+ bool user_flag_set () const;
+
+ /**
+ * Flag the user flag for this cell.
+ */
+ void set_user_flag () const;
+
+ /**
+ * Clear the user flag.
+ */
+ void clear_user_flag () const;
+
+ /**
+ * Return a pointer to the #i#th
+ * child.
+ */
+ TriaIterator<dim,LineAccessor<dim> > child (const unsigned int i) const;
+
+ /**
+ * Return the index of the #i#th child.
+ * The level of the child is one higher
+ * than that of the present cell.
+ * If the child does not exist, -1
+ * is returned.
+ */
+ int child_index (const unsigned int i) const;
+
+ /**
+ * Set the child field. Since we
+ * only store the index of the first
+ * child (the others follow directly)
+ * only one child index is to be
+ * given. The level of the child is
+ * one level up of the level of the
+ * cell to which this iterator points.
+ */
+ void set_children (const int index) const;
+
+ /**
+ * Clear the child field, i.e. set
+ * it to a value which indicates
+ * that this cell has no children.
+ */
+ void clear_children () const;
+
+ /**
+ * Test whether the line has children.
+ */
+ bool has_children () const;
+
+ private:
+ /**
+ * Copy operator. This is normally
+ * used in a context like
+ * #iterator a,b; *a=*b;#. Since
+ * the meaning is to copy the object
+ * pointed to by #b# to the object
+ * pointed to by #a# and since
+ * accessors are not real but
+ * virtual objects, this operation
+ * is not useful for iterators on
+ * triangulations. We declare this
+ * function here private, thus it may
+ * not be used from outside.
+ * Furthermore it is not implemented
+ * and will give a linker error if
+ * used anyway.
+ */
+ void operator = (const LineAccessor &);
+
+ public:
+// protected:
+ // would be better to make this private,
+ // but that would require making all
+ // TriaRawIterator<...>s friend.->wait for
+ // gcc 2.30687
+
+ /**@name Advancement of iterators*/
+ /*@{*/
+ /**
+ * This operator advances the iterator to
+ * the next element.
+ *
+ * The next element is next on this
+ * level if there are more. If the
+ * present element is the last on
+ * this level, the first on the
+ * next level is accessed.
+ */
+ void operator ++ ();
+
+ /**
+ * This operator moves the iterator to
+ * the previous element.
+ *
+ * The previous element is previous on
+ * this level if #index>0#. If the
+ * present element is the first on
+ * this level, the last on the
+ * previous level is accessed.
+ */
+ void operator -- ();
+ /*@}*/
+};
+
+
+
+/**
+ Accessor to dereference the data of quads. This accessor is used to
+ point to quads in #dim# space dimensions (only #dim>=2# seems reasonable
+ to me). There is a derived class
+ for quads in two space dimension, in which case a quad is also a cell
+ and thus has much more functionality than in lower dimensions.
+ */
+template <int dim>
+class QuadAccessor : public TriaAccessor<dim> {
+ public:
+ /**
+ * Constructor.
+ */
+ QuadAccessor (Triangulation<dim> *parent = 0,
+ const int level = -1,
+ const int index = -1,
+ const void *local_data = 0) :
+ TriaAccessor<dim> (parent, level, index, local_data) {};
+
+ /**
+ * Copy the data of the given quad.
+ */
+ void set (const Quad &q) const;
+
+ /**
+ * Return index of vertex #i=0,1,2,3# of
+ * a quad. The #i#th vertex is the common
+ * one of line #i# and #(i+3)%4#. See also
+ * the introduced convention
+ * (\Ref{Triangulation}).
+ */
+ int vertex_index (const unsigned int i) const;
+
+ /**
+ * Return a reference (not an iterator!)
+ * to the #i#th vertex.
+ */
+ Point<dim> & vertex (const unsigned int i) const;
+
+ /**
+ * Return a pointer to the #i#th line
+ * bounding this #Quad#.
+ */
+ TriaIterator<dim,LineAccessor<dim> > line (const unsigned int i) const;
+
+ /**
+ * Return the line index of the #i#th
+ * side (a line). The level is naturally
+ * the same as that of the quad.
+ */
+ unsigned int line_index (const unsigned int i) const;
+
+ /**
+ * Test for the element being used
+ * or not.
+ */
+ bool used () const;
+
+ /**
+ * Set the #used# flag.
+ */
+ void set_used_flag () const;
+
+ /**
+ * Clear the #used# flag.
+ */
+ void clear_used_flag () const;
+
+ /**
+ * Return whether the user flag
+ * is set or not.
+ */
+ bool user_flag_set () const;
+
+ /**
+ * Flag the user flag for this cell.
+ */
+ void set_user_flag () const;
+
+ /**
+ * Clear the user flag.
+ */
+ void clear_user_flag () const;
+
+ /**
+ * Return a pointer to the #i#th
+ * child.
+ */
+ TriaIterator<dim,QuadAccessor<dim> > child (const unsigned int i) const;
+
+ /**
+ * Return the index of the #i#th child.
+ * The level of the child is one higher
+ * than that of the present cell.
+ * If the child does not exist, -1
+ * is returned.
+ */
+ int child_index (const unsigned int i) const;
+
+ /**
+ * Set the child field. Since we
+ * only store the index of the first
+ * child (the others follow directly)
+ * only one child index is to be
+ * given. The level of the child is
+ * one level up of the level of the
+ * cell to which this iterator points.
+ */
+ void set_children (const int index) const;
+
+ /**
+ * Clear the child field, i.e. set
+ * it to a value which indicates
+ * that this cell has no children.
+ */
+ void clear_children () const;
+
+ /**
+ * Test whether the quad has children.
+ */
+ bool has_children () const;
+
+ private:
+ /**
+ * Copy operator. This is normally
+ * used in a context like
+ * #iterator a,b; *a=*b;#. Since
+ * the meaning is to copy the object
+ * pointed to by #b# to the object
+ * pointed to by #a# and since
+ * accessors are not real but
+ * virtual objects, this operation
+ * is not useful for iterators on
+ * triangulations. We declare this
+ * function here private, thus it may
+ * not be used from outside.
+ * Furthermore it is not implemented
+ * and will give a linker error if
+ * used anyway.
+ */
+ void operator = (const QuadAccessor &);
+
+ public:
+// protected:
+ // would be better to make this private,
+ // but that would require making all
+ // TriaRawIterator<...>s friend.->wait for
+ // gcc 2.30687
+
+ /**@name Advancement of iterators*/
+ /*@{*/
+ /**
+ * This operator advances the iterator to
+ * the next element.
+ *
+ * The next element is next on this
+ * level if there are more. If the
+ * present element is the last on
+ * this level, the first on the
+ * next level is accessed.
+ */
+ void operator ++ ();
+
+ /**
+ * This operator moves the iterator to
+ * the previous element.
+ *
+ * The previous element is previous on
+ * this level if #index>0#. If the
+ * present element is the first on
+ * this level, the last on the
+ * previous level is accessed.
+ */
+ void operator -- ();
+ /*@}*/
+};
+
+
+
+
+/**
+ This class allows access to a {\bf cell}, which is a line in 1D and a quad in
+ 2D. Declare it to have a template parameter, but do not actually declare
+ other types than those explicitely instantiated.
+ */
+template <int dim>
+class CellAccessor;
+
+
+
+
+
+/**
+ This class allows access to a cell, i.e. a line on the present dimension.
+
+ The following refers to any space dimension:
+
+ This class allows access to a {\bf cell}, which is a line in 1D and a quad in
+ 2D. Cells have more functionality than lines or quads by themselves, for
+ example they can be flagged for refinement, they have neighbors, they have
+ the possibility to check whether they are at the boundary etc. This class
+ offers access to all this data.
+
+ The are specialized versions, \Ref{CellAccessor<1>} and
+ \Ref{CellAccessor<2>}, which
+ offer access to cells and one and two dimensions respectively. They have
+ more or less the same functionality, but return different types in some
+ cases.
+ */
+class CellAccessor<1> : public LineAccessor<1> {
+ public:
+ /**
+ * Constructor.
+ */
+ CellAccessor (Triangulation<1> *parent = 0,
+ const int level = -1,
+ const int index = -1,
+ const void *local_data = 0) :
+ LineAccessor<1> (parent, level, index, local_data) {};
+
+ /**
+ * Return a pointer to the #i#th
+ * neighbor.
+ * If the neighbor does not exist, an
+ * invalid iterator is returned.
+ */
+ TriaIterator<1,CellAccessor<1> > neighbor (const unsigned int i) const;
+
+ /**
+ * Return the index of the #i#th neighbor.
+ * If the neighbor does not exist, its
+ * index is -1.
+ */
+ int neighbor_index (const unsigned int i) const;
+
+ /**
+ * Return the level of the #i#th neighbor.
+ * If the neighbor does not exist, its
+ * level is -1.
+ */
+ int neighbor_level (const unsigned int i) const;
+
+ /**
+ * Set the neighbor #i# of this cell
+ * to the cell pointed to by #pointer#.
+ * This line must be used.
+ */
+ void set_neighbor (const unsigned int i,
+ const TriaIterator<1,CellAccessor<1> > &pointer) const;
+
+ /**
+ * Return whether the #i#th vertex is
+ * part of the boundary. This is true, if
+ * the #i#th neighbor does not exist.
+ */
+ bool at_boundary (const unsigned int i) const;
+
+ /**
+ * Return whether the cell is at the
+ * boundary.
+ */
+ bool at_boundary () const;
+
+ /**
+ * Return whether the refinement flag
+ * is set or not.
+ */
+ bool refine_flag_set () const;
+
+ /**
+ * Flag the cell pointed to
+ * for refinement.
+ */
+ void set_refine_flag () const;
+
+ /**
+ * Clear the refinement flag.
+ */
+ void clear_refine_flag () const;
+
+ /**
+ * Return a pointer to the #i#th
+ * child. Overloaded version which returns
+ * a more reasonable iterator class.
+ */
+ TriaIterator<1,CellAccessor<1> > child (const unsigned int i) const;
+
+ /**
+ * Test whether the cell has children
+ * (this is the criterion for activity
+ * of a cell).
+ */
+ bool active () const;
+
+ private:
+ /**
+ * Copy operator. This is normally
+ * used in a context like
+ * #iterator a,b; *a=*b;#. Since
+ * the meaning is to copy the object
+ * pointed to by #b# to the object
+ * pointed to by #a# and since
+ * accessors are not real but
+ * virtual objects, this operation
+ * is not useful for iterators on
+ * triangulations. We declare this
+ * function here private, thus it may
+ * not be used from outside.
+ * Furthermore it is not implemented
+ * and will give a linker error if
+ * used anyway.
+ */
+ void operator = (const CellAccessor<1> &);
+};
+
+
+
+
+
+
+/**
+ Specialization of a #CellAccessor# for two space dimensions.
+ @see CellAccessor<1>
+ */
+class CellAccessor<2> : public QuadAccessor<2> {
+ public:
+ /**
+ * Constructor.
+ */
+ CellAccessor (Triangulation<2> *parent = 0,
+ const int level = -1,
+ const int index = -1,
+ const void *local_data = 0) :
+ QuadAccessor<2> (parent, level, index, local_data) {};
+
+ /**
+ * Return a pointer to the #i#th
+ * neighbor.
+ */
+ TriaIterator<2,CellAccessor<2> > neighbor (const unsigned int i) const;
+
+ /**
+ * Return the index of the #i#th neighbor.
+ * If the neighbor does not exist, its
+ * index is -1.
+ */
+ int neighbor_index (const unsigned int i) const;
+
+ /**
+ * Return the level of the #i#th neighbor.
+ * If the neighbor does not exist, its
+ * level is -1.
+ */
+ int neighbor_level (const unsigned int i) const;
+
+ /**
+ * Set the neighbor #i# of this cell
+ * to the cell pointed to by
+ * #pointer#.
+ */
+ void set_neighbor (const unsigned int i,
+ const TriaIterator<2,CellAccessor<2> > &pointer) const;
+
+ /**
+ * Return whether the #i#th side of this
+ * quad is part of the
+ * boundary. This is true, if the
+ * #i#th neighbor does not exist.
+ */
+ bool at_boundary (const unsigned int i) const;
+
+ /**
+ * Return whether the cell is at the
+ * boundary.
+ */
+ bool at_boundary () const;
+
+ /**
+ * Return whether the refinement flag
+ * is set or not.
+ */
+ bool refine_flag_set () const;
+
+ /**
+ * Flag the cell pointed to
+ * for refinement.
+ */
+ void set_refine_flag () const;
+
+ /**
+ * Clear the refinement flag.
+ */
+ void clear_refine_flag () const;
+
+ /**
+ * Return a pointer to the #i#th
+ * child. Overloaded version which returns
+ * a more reasonable iterator class.
+ */
+ TriaIterator<2,CellAccessor<2> > child (const unsigned int i) const;
+ /**
+ * Test whether the cell has children
+ * (this is the criterion for activity
+ * of a cell).
+ */
+ bool active () const;
+
+ private:
+ /**
+ * Copy operator. This is normally
+ * used in a context like
+ * #iterator a,b; *a=*b;#. Since
+ * the meaning is to copy the object
+ * pointed to by #b# to the object
+ * pointed to by #a# and since
+ * accessors are not real but
+ * virtual objects, this operation
+ * is not useful for iterators on
+ * triangulations. We declare this
+ * function here private, thus it may
+ * not be used from outside.
+ * Furthermore it is not implemented
+ * and will give a linker error if
+ * used anyway.
+ */
+ void operator = (const CellAccessor<2> &);
+};
+
+
+
+
+/*---------------------------- tria_accessor.h ---------------------------*/
+/* end of #ifndef __tria_accessor_H */
+#endif
+/*---------------------------- tria_accessor.h ---------------------------*/
--- /dev/null
+/*---------------------------- boundary-function.h ---------------------------*/
+/* $Id$ */
+#ifndef __tria_boundary_H
+#define __tria_boundary_H
+/*---------------------------- boundary-function.h ---------------------------*/
+
+#include <grid/point.h>
+
+/**
+ This class is used to represent a boundary to a triangulation.
+ When a triangulation creates a new vertex on the boundary of the
+ domain, it determines the new vertex' coordinates through the
+ following code (here in two dimensions):
+ \begin{verbatim}
+ ...
+ const Point<2> *neighbors[2] = {&neighbor1, &neighbor2};
+ Point<2> new_vertex = boundary.in_between (neighbors);
+ ...
+ \end{verbatim}
+ #neighbor1# and #neighbor2# are the two vertices bounding the old
+ line on the boundary, which is to be subdivided. #boundary# is an
+ object of type #Boundary<dim>#.
+
+ In 3D, a new vertex may be placed on the middle of a line or on
+ the middle of a side. In the both cases, an array with four points
+ has to be passed to #in_between#; in the latter case the two end
+ points of the line have to be given consecutively twice, as
+ elements 0 and 1, and 2 and 3, respectively.
+
+ There is a specialisation, #StraightBoundary<dim>#, which places
+ the new point right into the middle of the given points.
+ */
+template <int dim>
+class Boundary {
+ public:
+ /**
+ * Typedef an array of the needed number
+ * of old points.
+ */
+ typedef const Point<dim>* PointArray[1<<(dim-1)];
+
+ /**
+ * This function calculates the position
+ * of the new vertex.
+ */
+ virtual Point<dim> in_between (const PointArray &neighbors) const = 0;
+};
+
+
+
+
+
+/**
+ Specialisation of \Ref{Boundary}<dim>, which places the new point right
+ into the middle of the given points. The middle is defined as the
+ arithmetic mean of the points.
+ */
+template <int dim>
+class StraightBoundary : public Boundary<dim> {
+ public:
+ /**
+ * This function calculates the position
+ * of the new vertex.
+ */
+ virtual Point<dim> in_between (const PointArray &neighbors) const {
+ Point<dim> p;
+ for (int i=0; i<(1<<(dim-1)); ++i)
+ p += *neighbors[i];
+ p /= (1<<(dim-1))*1.0;
+ return p;
+ };
+};
+
+
+
+
+/*---------------------------- boundary-function.h ---------------------------*/
+/* end of #ifndef __tria_boundary_H */
+#endif
+/*---------------------------- boundary-function.h ---------------------------*/
--- /dev/null
+/*---------------------------- tria-iterator.h ---------------------------*/
+/* $Id$ */
+#ifndef __tria_iterator_H
+#define __tria_iterator_H
+/*---------------------------- tria-iterator.h ---------------------------*/
+
+
+
+#include <iterator.h>
+#include <iostream.h>
+#include <basic/exceptions.h>
+#include <grid/point.h>
+#include <grid/tria_accessor.h>
+
+
+
+
+
+// forward declaration needed
+template <int dim> class Triangulation;
+
+
+
+
+
+
+
+
+/**
+ This class implements an iterator, analogous to those of the standard
+ template library (STL). It fulfills the requirements of a bidirectional iterator.
+ See the C++ documentation for further details of iterator specification and
+ usage. In addition to the STL
+ iterators an iterator of this class provides a #-># operator, i.e. you can
+ write statements like #i->set_refine_flag ();#.
+
+ {\bf Note:} Please read the documentation about the prefix and the
+ postfix #++# operators in this and the derived classes!
+
+ {\bf Purpose}
+
+ #iterators# are used whenever a loop over all lines, quads, cells etc.
+ is to be performed. These loops can then be coded like this:
+ \begin{verbatim}
+ cell_iterator i = tria.begin();
+ cell_iterator end = tria.end();
+ for (; i!=end; ++i)
+ if (cell->at_boundary())
+ cell->set_refine_flag();
+ \end{verbatim}
+ Note the usage of #++i# instead of #i++# since this does not involve
+ temporaries and copying. You should also really use a fixed value
+ #end# rather than coding #for (; i!=tria.end(); ++i)#, since
+ the creation and copying of these iterators is rather expensive
+ compared to normal pointers.
+
+ The objects pointed to by iterators are #TriangulationLevel<1>::LinesData#,
+ #TriangulationLevel<2>::LinesData#
+ and #TriangulationLevel<2>::QuadsData#. To chose which of those, the
+ template parameter #Pointee# is used.
+
+ Since the names as is are quite unhandy, the #Triangulation<># class which
+ uses these iterators declares typedef'd versions. See there for more
+ information.
+
+ The objects pointed to are, as mentioned, #LinesData# etc. To be
+ more exact, when dereferencing an iterator, you do not get a #LineData#
+ object (or the like, but we will assume that you have a #line_iterator#
+ in the following), but a {\it virtual} object (called {\it accessor}) which
+ behaves as if it stored the data of a line. It does not contain any data
+ itself, but provides functions to manipulate the data of the line it
+ stands for.
+
+ Since the data of one line is splitted to
+ several arrays (#lines#, #children# and #used#) for performance reasons
+ rather than keeping all information in a #Line# struct, access through
+ an accessor is usually much simpler than handling the exact data structure
+ and also less error prone since the data structure itself can be changed
+ in an arbitrary way while the only pieces of code which access these
+ data structures are the accessors.
+
+ On the other hand, iterators are not much slower than operating directly
+ on the data structures, since they perform the loops that you had
+ to handcode yourself anyway. Most iterator and accessor functions are
+ inlined.
+
+ The main functionality of iterators, however, resides in the #++# and
+ #--# operators. These move the iterator forward or backward just as if
+ it were a pointer into an array. Here, this operation is not so easy,
+ since it may include skipping some elements and the transition between
+ the triangulation levels. This is completely hidden from the user, though
+ you can still create an iterator pointing to an arbitrary element.
+ Actually, the operation of moving iterators back and forth is not done in
+ the iterator classes, but rather in the accessor classes. Since these are
+ passed as template arguments, you can write your own versions here to add
+ more functionality.
+
+ Furthermore, the iterators decribed here satisfy the requirement of
+ input and bidirectional iterators as stated by the C++ standard and
+ the STL documentation. It is therefore possible to use the functions
+ from the {\it algorithm section} of the C++ standard, e.g. #count_if#
+ (see the documentation for \Ref{Triangulation} for an example) and
+ several others. Unfortunately, with some of them (e.g. #distance#),
+ g++2.7 has some problems and we will have to wait for g++2.8.
+
+
+ {\bf Differences between the classes in this inheritance tree}
+
+ #TriaRawIterator# objects point to lines, cells, etc in
+ the lists whether they are used or not (in the vectors, also {\it dead}
+ objects are stored, since deletion in vectors is expensive and we
+ also do not want to destroy the ordering induced by the numbering
+ in the vectors). Therefore not all raw iterators point to valid objects.
+
+ There are two derived versions of this class: \Ref{TriaIterator}
+ objects, which only loop over used (valid) cells and
+ #TriaActiveIterator# objects
+ which only loop over active cells (not refined).
+
+
+ {\bf Implementation}
+
+ In principle, the Iterator class does not have much functionality. It
+ only becomes useful when assigned an #Accessor# (the second template
+ parameter), which really does the access to data. An #Accessor# has to
+ fulfil some requirements:
+ \begin{itemize}
+ \item It must have two members named #present_level# and #present_index#
+ storing the address of the element in the triangulation presently
+ pointed to. Furthermore, the three #Tria{Raw| |Active}Iterator# classes
+ have to be friends to the accessor or these data members must be public.
+ \item It must have a constructor which takes 1. a #Triangulation<dim>*#,
+ 2. and 3. and integer, denoting the initial level and index.
+ \item For the #TriaIterator# and the #TriaActiveIterator# class, it must
+ have a member function #bool used()#, for the latter a member function
+ #bool active()#.
+ \item It should not modify the #present_level# and #present_index# fields,
+ since this is what the iterator classes do, but it should use them to
+ dereference the data it points to.
+ \item It must have void operators #++# and #--#.
+ \end{itemize}
+ Then the iterator is able to do what it is supposed to. All of the necessary
+ functions are implemented in the #Accessor# base class, but you may write
+ your own version (non-virtual, since we use templates) to add functionality.
+
+ There is a standard implementation, using classes which are derived from
+ \Ref{TriaAccessor}. These classes point to #Line#s, #Quad#s and the like.
+ For advanced use of the iterator classes, derive classes from
+ #{Line|Quad|Cell}Accessor# which also dereference data structures in other
+ objects, e.g. in a finite element context. An iterator with such an accessor
+ then simultaneously points to (for example) a cell in the triangulation and
+ the data stored on it in the finite element class.
+
+ Derived accessor classes may need additional data (e.g. the #DoFAccessor#
+ needs a pointer to the #DoFHandler# to work on). This data can be
+ set upon construction through the last argument of the constructors.
+ Ideally, its type is a local type to the accessor and must have the name
+ #Accessor::LocalData#. In the standard implementation, this type is
+ declared to be a void pointer. The iterator constructors take their
+ last argument carrying the additional data by default as zero, so unless
+ #Accessor::LocalData# is a number or a pointer you may not construct
+ such an iterator without giving the last argument. If you want to use
+ the additional data, you also have to overload the #TriaAccessor::copy_data#
+ function.
+
+ Unfortunately, the skeched way does not work, since gcc is not able to
+ recognize the type defined local to the template argument (it does not
+ suport the #typename# keyword at present), so we can only pass a voie
+ pointer. You may, however, convert this to any type, normally to another
+ pointer or to a pointer to a structure pointing to the data to be passed.
+ The mechanism may be changed if the mentioned features appear in gcc.
+
+ Another possibility would be to have a function, say #set_local_data(...)#
+ in the accessor classes which need additional data. You could then create
+ an iterator like this:
+ \begin{verbatim}
+ TriaIterator<1,MyAccesor> i;
+ i->set_local_data (1,2,3);
+ \end{verbatim}
+ But this will not always work: if the iterator #i# is not a valid one, then
+ the library will forbid you to dereference it (which normally is a good
+ idea), thus resulting in an error when you dereference it in the second
+ line.
+
+
+ {\bf Warning}
+
+ It seems impossible to preserve #const#ness of a triangulation through
+ iterator usage. Thus, if you declare pointers to a #const# triangulation
+ object, you should be well aware that you might involuntarily alter the
+ data stored in the triangulation.
+
+ {\bf Internals}
+
+ There is a representation of past-the-end-pointers, denoted by special
+ values of the member variables #present_level# and #present_index#:
+ If #present_level>=0# and #present_index>=0#, then the object is valid;
+ if #present_level==-1# and #present_index==-1#, then the iterator points
+ past the end; in all other cases, the iterator is considered invalid.
+ You can check this by calling the #state()# function.
+
+ An iterator is also invalid, if the pointer pointing to the #Triangulation#
+ object is invalid or zero.
+
+ Finally, an iterator is invalid, if the element pointed to by
+ #present_level# and #present_index# is not used, i.e. if the #used#
+ flag is set to false.
+
+ The last two checks are not made in #state()# since both cases should only
+ occur upon unitialized construction through #memcpy# and the like (the
+ parent triangulation can only be set upon construction). If
+ an iterator is constructed empty through the empty constructor,
+ #present_level==-2# and #present_index==-2#. Thus, the iterator is
+ invalid anyway, regardless of the state of the triangulation pointer
+ and the state of the element pointed to.
+
+ Past-the-end iterators may also be used to compare an iterator with the
+ {\it before-the-start} value, when running backwards. There is no
+ distiction between the iterators pointing past the two ends of a vector.
+
+ @see Triangulation
+ @see TriaDimensionInfo
+ @author Wolfgang Bangerth, 1998
+ */
+template <int dim, class Accessor>
+class TriaRawIterator : public bidirectional_iterator<Accessor,int> {
+ public:
+ /**
+ * Empty constructor. Such an object
+ * is not usable!
+ */
+ TriaRawIterator ();
+
+ /**
+ * Copy constructor.
+ */
+ TriaRawIterator (const TriaRawIterator &);
+
+ /**
+ * Proper constructor, initialized
+ * with the triangulation, the
+ * level and index of the object
+ * pointed to.
+ */
+ TriaRawIterator (Triangulation<dim> *parent,
+ const int level,
+ const int index,
+ const void *local_data=0);
+
+ /**
+ * @name Dereferencing
+ */
+ /*@{*/
+ /**
+ * Dereferencing operator, returns a
+ * reference to an accessor.
+ * Usage is thus like #(*i).index ();#
+ *
+ * This function has to be specialized
+ * explicitely for the different
+ * #Pointee#s, to allow an
+ * #iterator<1,TriangulationLevel<1>::LinesData>#
+ * to point to #tria->lines.lines[index]# while
+ * for one dimension higher it has
+ * to point to #tria->quads.quads[index]#.
+ *
+ * You must not dereference invalid or
+ * past the end iterators.
+ */
+ const Accessor & operator * () const {
+ // put this function here, since we can't
+ // inline it with gcc 2.7
+ Assert (state() == valid, ExcDereferenceInvalidObject());
+ return accessor;
+ };
+
+ /**
+ * Dereferencing operator, non-#const#
+ * version.
+ */
+ Accessor & operator * () {
+ // put this function here, since we can't
+ // inline it with gcc 2.7
+ Assert (state() == valid, ExcDereferenceInvalidObject());
+ return accessor;
+ };
+
+ /**
+ * Dereferencing operator, returns a
+ * reference of the cell pointed to.
+ * Usage is thus like #i->index ();#
+ *
+ * There is a #const# and a non-#const#
+ * version.
+ */
+ const Accessor * operator -> () const {
+ // put this function here, since we can't
+ // inline it with gcc 2.7
+ return &(this->operator* ());
+ };
+
+
+ /**
+ * Dereferencing operator, non-#const#
+ * version.
+ */
+ Accessor * operator -> () {
+ // put this function here, since we can't
+ // inline it with gcc 2.7
+ return &(this->operator* ());
+ };
+ /*@}*/
+
+ /**
+ * Assignment operator.
+ */
+ TriaRawIterator & operator = (const TriaRawIterator &);
+
+ /**
+ * Compare for equality.
+ */
+ bool operator == (const TriaRawIterator &) const;
+
+ /**
+ * Compare for inequality.
+ */
+ bool operator != (const TriaRawIterator &) const;
+
+ /**@name Advancement of iterators*/
+ /*@{*/
+ /**
+ * Prefix #++# operator: #++i#. This
+ * operator advances the iterator to
+ * the next element and returns
+ * a reference to #*this#.
+ *
+ * The next element is next on this
+ * level if there are more. If the
+ * present element is the last on
+ * this level, the first on the
+ * next level is accessed.
+ */
+ TriaRawIterator & operator ++ ();
+
+ /**
+ * Postfix #++# operator: #i++#. This
+ * operator advances the iterator to
+ * the next element, but
+ * returns an iterator to the element
+ * priviously pointed to. Since this
+ * involves a temporary and a copy
+ * operation and since an
+ * #iterator# is quite a large
+ * object for a pointer, use the
+ * prefix operator #++i# whenever
+ * possible, especially in the head
+ * of for loops
+ * (#for (; i!=end; ++i)#) since there
+ * you normally never need the
+ * returned value.
+ */
+ TriaRawIterator operator ++ (int);
+
+ /**
+ * Prefix #--# operator: #--i#. This
+ * operator advances the iterator to
+ * the previous element and returns
+ * a reference to #*this#.
+ *
+ * The previous element is previous on
+ * this level if #index>0#. If the
+ * present element is the first on
+ * this level, the last on the
+ * previous level is accessed.
+ */
+ TriaRawIterator & operator -- ();
+
+ /**
+ * Postfix #--# operator: #i--#. This
+ * operator advances the iterator to
+ * the previous element, but
+ * returns an iterator to the element
+ * priviously pointed to. Since this
+ * involves a temporary and a copy
+ * operation and since an
+ * #iterator# is quite a large
+ * object for a pointer, use the
+ * prefix operator #--i# whenever
+ * possible, especially in the head
+ * of for loops
+ * (#for (; i!=end; --i)#) since there
+ * you normally never need the
+ * returned value.
+ */
+ TriaRawIterator operator -- (int);
+ /*@}*/
+
+ /**
+ * Return the state of the iterator.
+ */
+ IteratorState state () const;
+
+ void print (ostream &out) const {
+ out << accessor.level() << "." << accessor.index();
+ };
+
+
+
+ /**@name Exceptions*/
+ /*@{*/
+ /**
+ * Exception
+ */
+ DeclException0 (ExcDereferenceInvalidObject);
+ /**
+ * Exception
+ */
+ DeclException0 (ExcAdvanceInvalidObject);
+ /*@}*/
+// protected: // don't know why we can't declare this protected (gcc2.7 chokes!?)
+ Accessor accessor;
+};
+
+
+
+
+
+
+
+/**
+ This specialization of \Ref{TriaRawIterator} provides access only to the
+ {\it used} lines, quads, cells, etc.
+ */
+template <int dim, class Accessor>
+class TriaIterator : public TriaRawIterator<dim,Accessor> {
+ public:
+ /**
+ * Empty constructor. Such an object
+ * is not usable!
+ */
+ TriaIterator ();
+
+ /**
+ * Copy constructor.
+ */
+ TriaIterator (const TriaIterator<dim,Accessor> &);
+
+ /**
+ * Cross copy constructor from
+ * iterators pointing also to
+ * non-active objects.
+ *
+ * If the object pointed to is not
+ * past-the-end and is not
+ * used, the debug version raises
+ * an error!
+ */
+ TriaIterator (const TriaRawIterator<dim,Accessor> &);
+
+ /**
+ * Proper constructor, initialized
+ * with the triangulation, the
+ * level and index of the object
+ * pointed to.
+ *
+ * If the object pointed to is not
+ * past-the-end and is not
+ * used, the debug version raises
+ * an error!
+ */
+ TriaIterator (Triangulation<dim> *parent,
+ const int level,
+ const int index,
+ const void *local_data=0);
+
+ /**
+ * Assignment operator.
+ */
+ TriaIterator<dim,Accessor> &
+ operator = (const TriaIterator<dim,Accessor> &);
+
+ /**
+ * Cross assignment operator. This
+ * assignment is only valid if the
+ * given iterator points to a used
+ * element.
+ */
+ TriaIterator<dim,Accessor> &
+ operator = (const TriaRawIterator<dim,Accessor> &);
+
+ /**@name Advancement of iterators*/
+ /*@{*/
+ /**
+ * Prefix #++# operator: #++i#. This
+ * operator advances the iterator to
+ * the next used element and returns
+ * a reference to #*this#.
+ */
+ TriaIterator<dim,Accessor> & operator ++ ();
+
+ /**
+ * Postfix #++# operator: #i++#. This
+ * operator advances the iterator to
+ * the next used element, but
+ * returns an iterator to the element
+ * previously pointed to. Since this
+ * involves a temporary and a copy
+ * operation and since an
+ * #active_iterator# is quite a large
+ * object for a pointer, use the
+ * prefix operator #++i# whenever
+ * possible, especially in the head
+ * of for loops
+ * (#for (; i!=end; ++i)#) since there
+ * you normally never need the
+ * returned value.
+ */
+ TriaIterator<dim,Accessor> operator ++ (int);
+
+ /**
+ * Prefix #--# operator: #--i#. This
+ * operator advances the iterator to
+ * the previous used element and returns
+ * a reference to #*this#.
+ */
+ TriaIterator<dim,Accessor> & operator -- ();
+
+ /**
+ * Postfix #--# operator: #i--#.
+ */
+ TriaIterator<dim,Accessor> operator -- (int);
+ /*@}*/
+
+ /**
+ * Exception
+ */
+ DeclException0 (ExcAssignmentOfUnusedObject);
+};
+
+
+
+extern TriaIterator<1,LineAccessor<1> > __dummy3; // to calm down gcc2.7
+extern TriaIterator<2,LineAccessor<2> > __dummy4; // to calm down gcc2.7
+extern TriaIterator<2,QuadAccessor<2> > __dummy5; // to calm down gcc2.7
+
+
+
+
+/**
+ This specialization of \Ref{TriaIterator} provides access only to the
+ {\it active} lines, quads, cells, etc. An active cell is a cell which is not
+ refined and thus a cell on which calculations on the finest level are done.
+ */
+template <int dim, class Accessor>
+class TriaActiveIterator : public TriaIterator<dim,Accessor> {
+ public:
+ /**
+ * Empty constructor. Such an object
+ * is not usable!
+ */
+ TriaActiveIterator ();
+
+ /**
+ * Copy constructor.
+ */
+ TriaActiveIterator (const TriaActiveIterator<dim,Accessor> &);
+
+ /**
+ * Cross copy constructor from
+ * iterators pointing also to
+ * non-active objects.
+ *
+ * If the object pointed to is not
+ * past-the-end and is not
+ * active, the debug version raises
+ * an error!
+ */
+ TriaActiveIterator (const TriaRawIterator<dim,Accessor> &);
+
+ /**
+ * Cross copy constructor from
+ * iterators pointing also to
+ * non-active objects.
+ *
+ * If the object pointed to is not
+ * past-the-end and is not
+ * active, the debug version raises
+ * an error!
+ */
+ TriaActiveIterator (const TriaIterator<dim,Accessor> &);
+
+ /**
+ * Proper constructor, initialized
+ * with the triangulation, the
+ * level and index of the object
+ * pointed to.
+ *
+ * If the object pointed to is not
+ * past-the-end and is not
+ * active, the debug version raises
+ * an error!
+ */
+ TriaActiveIterator (Triangulation<dim> *parent,
+ const int level,
+ const int index,
+ const void *local_data=0);
+
+ /**
+ * Assignment operator.
+ */
+ TriaActiveIterator<dim,Accessor> &
+ operator = (const TriaActiveIterator<dim,Accessor> &);
+
+ /**
+ * Cross assignment operator. This
+ * assignment is only valid if the
+ * given iterator points to an active
+ * element or past the end.
+ */
+ TriaActiveIterator<dim,Accessor> &
+ operator = (const TriaRawIterator<dim,Accessor> &);
+
+ /**
+ * Cross assignment operator. This
+ * assignment is only valid if the
+ * given iterator points to an active
+ * element or past the end.
+ */
+ TriaActiveIterator<dim,Accessor> &
+ operator = (const TriaIterator<dim,Accessor> &);
+
+ /**
+ * Prefix #++# operator: #++i#. This
+ * operator advances the iterator to
+ * the next active element and returns
+ * a reference to #*this#.
+ */
+ TriaActiveIterator<dim,Accessor> & operator ++ ();
+
+ /**@name Advancement of iterators*/
+ /*@{*/
+ /**
+ * Postfix #++# operator: #i++#. This
+ * operator advances the iterator to
+ * the next active element, but
+ * returns an iterator to the element
+ * previously pointed to. Since this
+ * involves a temporary and a copy
+ * operation and since an
+ * #active_iterator# is quite a large
+ * object for a pointer, use the
+ * prefix operator #++i# whenever
+ * possible, especially in the head
+ * of for loops
+ * (#for (; i!=end; ++i)#) since there
+ * you normally never need the
+ * returned value.
+ */
+ TriaActiveIterator<dim,Accessor> operator ++ (int);
+
+ /**
+ * Prefix #--# operator: #--i#. This
+ * operator advances the iterator to
+ * the previous active element and
+ * returns a reference to #*this#.
+ */
+ TriaActiveIterator<dim,Accessor> & operator -- ();
+
+ /**
+ * Postfix #--# operator: #i--#.
+ */
+ TriaActiveIterator<dim,Accessor> operator -- (int);
+ /*@}*/
+
+ /**
+ * Exception
+ */
+ DeclException0 (ExcAssignmentOfInactiveObject);
+};
+
+
+
+
+template <int dim, class Accessor>
+inline
+IteratorState TriaRawIterator<dim,Accessor>::state () const {
+ return accessor.state ();
+};
+
+
+
+template <int dim, class Accessor>
+inline
+TriaRawIterator<dim,Accessor> &
+TriaRawIterator<dim,Accessor>::operator ++ () {
+ Assert (state() == valid, ExcAdvanceInvalidObject());
+
+ ++accessor;
+ return *this;
+};
+
+
+
+template <int dim, class Accessor>
+inline
+TriaRawIterator<dim,Accessor> &
+TriaRawIterator<dim,Accessor>::operator -- () {
+ Assert (state() == valid, ExcAdvanceInvalidObject());
+
+ --accessor;
+ return *this;
+};
+
+
+
+template <int dim, class Accessor>
+inline
+ostream & operator << (ostream &out, const TriaRawIterator<dim,Accessor> &i) {
+ i.print(out);
+ return out;
+};
+
+template <int dim, class Accessor>
+inline
+ostream & operator << (ostream &out, const TriaIterator<dim,Accessor> &i) {
+ i.print(out);
+ return out;
+};
+
+template <int dim, class Accessor>
+inline
+ostream & operator << (ostream &out, const TriaActiveIterator<dim,Accessor> &i) {
+ i.print(out);
+ return out;
+};
+
+
+
+/*---------------------------- tria-iterator.h ---------------------------*/
+/* end of #ifndef __tria_iterator_H */
+#endif
+/*---------------------------- tria-iterator.h ---------------------------*/
+
+
--- /dev/null
+/* $Id$ */
+
+#include <grid/tria.h>
+#include <grid/tria_iterator.h>
+
+
+/* Note: This file only contains template definitions and will thus
+ not produce an object file. It is rather thought to be included
+ into the *_accessor.cc files.
+*/
+
+
+
+/*------------------------ Functions: TriaRawIterator ------------------*/
+
+
+template <int dim, class Accessor>
+TriaRawIterator<dim,Accessor>::TriaRawIterator () :
+ accessor (0, -2, -2, 0) {};
+
+
+
+template <int dim, class Accessor>
+TriaRawIterator<dim,Accessor>::TriaRawIterator (const TriaRawIterator<dim,Accessor> &i) :
+ accessor (i.accessor) {};
+
+
+
+template <int dim, class Accessor>
+TriaRawIterator<dim,Accessor>::TriaRawIterator (Triangulation<dim> *parent,
+ const int level,
+ const int index,
+ const void *local_data) :
+ accessor (parent, level, index, local_data) {};
+
+
+
+template <int dim, class Accessor>
+TriaRawIterator<dim,Accessor> &
+TriaRawIterator<dim,Accessor>::operator = (const TriaRawIterator<dim,Accessor> &i) {
+ accessor.copy_from (i.accessor);
+
+ return *this;
+};
+
+
+
+template <int dim, class Accessor>
+bool
+TriaRawIterator<dim,Accessor>::operator == (const TriaRawIterator<dim,Accessor> &i) const {
+ return accessor == i.accessor;
+};
+
+
+
+template <int dim, class Accessor>
+bool
+TriaRawIterator<dim,Accessor>::operator != (const TriaRawIterator<dim,Accessor> &i) const {
+ return accessor != i.accessor;
+};
+
+
+
+template <int dim, class Accessor>
+TriaRawIterator<dim,Accessor> TriaRawIterator<dim,Accessor>::operator ++ (int) {
+ TriaRawIterator<dim,Accessor> tmp(*this);
+ this->operator++ ();
+
+ return tmp;
+};
+
+
+
+template <int dim, class Accessor>
+TriaRawIterator<dim,Accessor> TriaRawIterator<dim,Accessor>::operator -- (int) {
+ TriaRawIterator<dim,Accessor> tmp(*this);
+ this->operator-- ();
+
+ return tmp;
+};
+
+
+
+
+/*----------------------- functions: TriaIterator ---------------*/
+
+
+template <int dim, class Accessor>
+TriaIterator<dim,Accessor>::TriaIterator () :
+ TriaRawIterator<dim,Accessor> () {};
+
+
+template <int dim, class Accessor>
+TriaIterator<dim,Accessor>::
+TriaIterator (const TriaIterator<dim,Accessor> &i) :
+ TriaRawIterator<dim,Accessor> ((TriaRawIterator<dim,Accessor>)i) {};
+
+
+
+template <int dim, class Accessor>
+TriaIterator<dim,Accessor>::
+TriaIterator (const TriaRawIterator<dim,Accessor> &i) :
+ TriaRawIterator<dim,Accessor> (i)
+{
+#ifdef DEBUG
+ // do this like this, because:
+ // if we write
+ // "Assert (past_the_end || used)"
+ // used() is called anyway, even if
+ // state==past_the_end, and will then
+ // throw the exception!
+ if (state() != past_the_end)
+ Assert (accessor.used(),
+ ExcAssignmentOfUnusedObject());
+#endif
+};
+
+
+
+template <int dim, class Accessor>
+TriaIterator<dim,Accessor>::TriaIterator (Triangulation<dim> *parent,
+ const int level,
+ const int index,
+ const void *local_data) :
+ TriaRawIterator<dim,Accessor> (parent, level, index, local_data)
+{
+#ifdef DEBUG
+ // do this like this, because:
+ // if we write
+ // "Assert (past_the_end || used)"
+ // used() is called anyway, even if
+ // state==past_the_end, and will then
+ // throw the exception!
+ if (state() != past_the_end)
+ Assert (accessor.used(),
+ ExcAssignmentOfUnusedObject());
+#endif
+};
+
+
+
+template <int dim, class Accessor>
+TriaIterator<dim,Accessor> &
+TriaIterator<dim,Accessor>::operator = (const TriaIterator<dim,Accessor> &i) {
+ accessor.copy_from (i.accessor);
+ return *this;
+};
+
+
+template <int dim, class Accessor>
+TriaIterator<dim,Accessor> &
+TriaIterator<dim,Accessor>::operator = (const TriaRawIterator<dim,Accessor> &i) {
+ accessor.copy_from (i.accessor);
+#ifdef DEBUG
+ // do this like this, because:
+ // if we write
+ // "Assert (past_the_end || used)"
+ // used() is called anyway, even if
+ // state==past_the_end, and will then
+ // throw the exception!
+ if (state() != past_the_end)
+ Assert (accessor.used(),
+ ExcAssignmentOfUnusedObject());
+#endif
+ return *this;
+};
+
+
+
+template <int dim, class Accessor>
+TriaIterator<dim,Accessor> & TriaIterator<dim,Accessor>::operator ++ () {
+ while (TriaRawIterator<dim,Accessor>::operator++(),
+ (state() == valid))
+ if (accessor.used() == true)
+ return *this;
+ return *this;
+};
+
+
+
+template <int dim, class Accessor>
+TriaIterator<dim,Accessor> TriaIterator<dim,Accessor>::operator ++ (int) {
+ TriaIterator<dim,Accessor> tmp(*this);
+ this->operator++ ();
+
+ return tmp;
+};
+
+
+
+template <int dim, class Accessor>
+TriaIterator<dim,Accessor> & TriaIterator<dim,Accessor>::operator -- () {
+ while (TriaRawIterator<dim,Accessor>::operator--(),
+ (state() == valid))
+ if (accessor.used() == true)
+ return *this;
+ return *this;
+};
+
+
+template <int dim, class Accessor>
+TriaIterator<dim,Accessor> TriaIterator<dim,Accessor>::operator -- (int) {
+ TriaIterator<dim,Accessor> tmp(*this);
+ this->operator-- ();
+
+ return tmp;
+};
+
+
+
+/*----------------------- functions: TriaActiveIterator ---------------*/
+
+
+template <int dim, class Accessor>
+TriaActiveIterator<dim,Accessor>::TriaActiveIterator () :
+ TriaIterator<dim,Accessor> () {};
+
+
+
+template <int dim, class Accessor>
+TriaActiveIterator<dim,Accessor>::
+TriaActiveIterator (const TriaActiveIterator<dim,Accessor> &i) :
+ TriaIterator<dim,Accessor> ((TriaIterator<dim,Accessor>) i) {};
+
+
+
+template <int dim, class Accessor>
+TriaActiveIterator<dim,Accessor>::
+TriaActiveIterator (const TriaRawIterator<dim,Accessor> &i) :
+ TriaIterator<dim,Accessor> (i)
+{
+#ifdef DEBUG
+ // do this like this, because:
+ // if we write
+ // "Assert (past_the_end || used)"
+ // has_children() is called anyway, even if
+ // state==past_the_end, and will then
+ // throw the exception!
+ if (state() != past_the_end)
+ Assert (accessor.has_children()==false,
+ ExcAssignmentOfInactiveObject());
+#endif
+};
+
+
+template <int dim, class Accessor>
+TriaActiveIterator<dim,Accessor>::
+TriaActiveIterator (const TriaIterator<dim,Accessor> &i) :
+ TriaIterator<dim,Accessor> (i)
+{
+#ifdef DEBUG
+ // do this like this, because:
+ // if we write
+ // "Assert (past_the_end || used)"
+ // has_children() is called anyway, even if
+ // state==past_the_end, and will then
+ // throw the exception!
+ if (state() != past_the_end)
+ Assert (accessor.has_children()==false,
+ ExcAssignmentOfInactiveObject());
+#endif
+};
+
+
+
+template <int dim, class Accessor>
+TriaActiveIterator<dim,Accessor>::TriaActiveIterator (Triangulation<dim> *parent,
+ const int level,
+ const int index,
+ const void *local_data) :
+ TriaIterator<dim,Accessor> (parent, level, index, local_data)
+{
+#ifdef DEBUG
+ // do this like this, because:
+ // if we write
+ // "Assert (past_the_end || used)"
+ // has_children() is called anyway, even if
+ // state==past_the_end, and will then
+ // throw the exception!
+ if (state() != past_the_end)
+ Assert (accessor.has_children()==false,
+ ExcAssignmentOfInactiveObject());
+#endif
+};
+
+
+
+template <int dim, class Accessor>
+TriaActiveIterator<dim,Accessor> &
+TriaActiveIterator<dim,Accessor>::operator = (const TriaActiveIterator<dim,Accessor> &i) {
+ accessor.copy_from (i.accessor);
+ return *this;
+};
+
+
+
+template <int dim, class Accessor>
+TriaActiveIterator<dim,Accessor> &
+TriaActiveIterator<dim,Accessor>::operator = (const TriaRawIterator<dim,Accessor> &i) {
+ accessor.copy_from (i.accessor);
+#ifdef DEBUG
+ // do this like this, because:
+ // if we write
+ // "Assert (past_the_end || used)"
+ // has_chidlren() is called anyway, even if
+ // state==past_the_end, and will then
+ // throw the exception!
+ if (state() != past_the_end)
+ Assert (accessor.used() && accessor.has_children()==false,
+ ExcAssignmentOfInactiveObject());
+#endif
+ return *this;
+};
+
+
+
+template <int dim, class Accessor>
+TriaActiveIterator<dim,Accessor> &
+TriaActiveIterator<dim,Accessor>::operator = (const TriaIterator<dim,Accessor> &i) {
+ accessor.copy_from (i.accessor);
+#ifdef DEBUG
+ // do this like this, because:
+ // if we write
+ // "Assert (past_the_end || used)"
+ // has_children() is called anyway, even if
+ // state==past_the_end, and will then
+ // throw the exception!
+ if (state() != past_the_end)
+ Assert (accessor.has_children()==false,
+ ExcAssignmentOfInactiveObject());
+#endif
+ return *this;
+};
+
+
+
+template <int dim, class Accessor>
+TriaActiveIterator<dim,Accessor> & TriaActiveIterator<dim,Accessor>::operator ++ () {
+ while (TriaIterator<dim,Accessor>::operator++(),
+ (state() == valid))
+ if (accessor.has_children() == false)
+ return *this;
+ return *this;
+};
+
+
+
+template <int dim, class Accessor>
+TriaActiveIterator<dim,Accessor> TriaActiveIterator<dim,Accessor>::operator ++ (int) {
+ TriaActiveIterator<dim,Accessor> tmp(*this);
+ this->operator++ ();
+
+ return tmp;
+};
+
+
+
+template <int dim, class Accessor>
+TriaActiveIterator<dim,Accessor> & TriaActiveIterator<dim,Accessor>::operator -- () {
+ while (TriaIterator<dim,Accessor>::operator--(),
+ (state() == valid))
+ if (accessor.has_children() == false)
+ return *this;
+ return *this;
+};
+
+
+
+template <int dim, class Accessor>
+TriaActiveIterator<dim,Accessor> TriaActiveIterator<dim,Accessor>::operator -- (int) {
+ TriaActiveIterator<dim,Accessor> tmp(*this);
+ this->operator-- ();
+
+ return tmp;
+};
+
+
+
+
+
+
+
+
+
--- /dev/null
+/*---------------------------- tria_line.h ---------------------------*/
+/* $Id$ */
+#ifndef __tria_line_H
+#define __tria_line_H
+/*---------------------------- tria_line.h ---------------------------*/
+
+#include <basic/exceptions.h>
+
+
+/**
+ Lines denote the boundaries of quads and the edges of hexaeders. They are
+ characterized by the (global) indices of the endpoints.
+
+ A line itself has one index, as far as the topological part handled in
+ the triangulation is concerned: the index in the level
+ it belongs to. The level index is implicitely given by the position
+ in the #lines.lines# list attached to the information of each level.
+ */
+class Line {
+ public:
+ /**
+ * Construct a line with end point
+ * indices #i0# and #i1#. By default,
+ * indices are set to -1, i.e. an
+ * invalid value.
+ */
+ Line (const int i0 = -1,
+ const int i1 = -1);
+
+ /**
+ * Return the index of end point #i#=0
+ * or 1.
+ */
+ int vertex (const int i) const;
+
+ /**
+ * Set the index of the #i#th vertex to
+ * #index#. #i#=0 or 1.
+ */
+ void set_vertex (const int i, const int index);
+
+ /**
+ * Exception
+ */
+ DeclException1 (ExcRange,
+ int,
+ << "Indices for the point number must be 0 or 1, "
+ << "but you gave " << arg1);
+
+ protected:
+ /**
+ * Global indices of the two end points.
+ */
+ int end_points[2];
+};
+
+
+
+
+/*----------------------------- Inline Function: Line ------------------------*/
+
+
+inline // wahrlich inline hier!
+Line::Line (const int i0, const int i1) {
+ end_points[0] = i0;
+ end_points[1] = i1;
+};
+
+
+inline
+int Line::vertex (const int i) const {
+ Assert ((i==0) || (i==1),
+ ExcRange(i));
+ return end_points[i];
+};
+
+
+inline
+void Line::set_vertex (const int i, const int index) {
+ Assert ((i==0) || (i==1),
+ ExcRange(i));
+ end_points[i] = index;
+};
+
+
+
+/*---------------------------- tria_line.h ---------------------------*/
+/* end of #ifndef __tria_line_H */
+#endif
+/*---------------------------- tria_line.h ---------------------------*/
--- /dev/null
+/*---------------------------- tria_quad.h ---------------------------*/
+/* $Id$ */
+#ifndef __tria_quad_H
+#define __tria_quad_H
+/*---------------------------- tria_quad.h ---------------------------*/
+
+
+#include <basic/exceptions.h>
+
+/**
+ #Quad#s denote the fundamental entities of triangulations in two dimensions
+ and the boundaries of hexaeders in three dimensions. They are
+ characterized by the (global) indices of the corner points.
+
+ A quad itself has one index, as far as the topological part handled in
+ the triangulation is concerned: the index in the level
+ it belongs to. The level index is implicitely given by the position
+ in the #quads.quads# list attached to the information of each level
+ of the triangulation.
+ */
+class Quad {
+ public:
+
+ /**
+ * Construct a Quad with line
+ * indices #i0# through #i3#. By default,
+ * indices are set to -1, i.e. an
+ * invalid value.
+ *
+ * By convention, the four lines must
+ * be numbered in counterclockwise sense!
+ */
+ Quad (const int i0 = -1,
+ const int i1 = -1,
+ const int i2 = -1,
+ const int i3 = -1);
+
+ /**
+ * Return the index of line #i#=0
+ * through 3.
+ */
+ int line (const int i) const;
+
+ /**
+ * Set the index of the #i#th line to
+ * #index#. #i#=0 through 3.
+ */
+ void set_line (const int i, const int index);
+
+ /**
+ * Exception
+ */
+ DeclException1 (ExcRange,
+ int,
+ << "Indices for the point number must be 0, 1, 2 or 3, "
+ << "but you gave " << arg1);
+ protected:
+ int lines[4];
+};
+
+
+
+
+/*----------------------------- Inline Function: Quad ------------------------*/
+
+
+inline
+Quad::Quad (const int i0, const int i1, const int i2, const int i3) {
+ lines[0] = i0;
+ lines[1] = i1;
+ lines[2] = i2;
+ lines[3] = i3;
+};
+
+
+
+inline
+int Quad::line (const int i) const {
+ Assert ((i>=0) && (i<4),
+ ExcRange(i));
+ return lines[i];
+};
+
+
+
+inline
+void Quad::set_line (const int i, const int index) {
+ Assert ((i>=0) && (i<4),
+ ExcRange(i));
+ lines[i] = index;
+};
+
+
+
+/*---------------------------- tria_quad.h ---------------------------*/
+/* end of #ifndef __tria_quad_H */
+#endif
+/*---------------------------- tria_quad.h ---------------------------*/
--- /dev/null
+/*---------------------------- problem_assembler.h ---------------------------*/
+/* $Id$ */
+#ifndef __problem_assembler_H
+#define __problem_assembler_H
+/*---------------------------- problem_assembler.h ---------------------------*/
+
+#include <grid/dof.h>
+#include <grid/dof_accessor.h>
+#include <fe/fe.h>
+#include <basic/exceptions.h>
+#include <vector.h>
+
+
+// forward declarations
+class dFMatrix;
+class dVector;
+template <int dim> class ProblemBase;
+
+
+
+
+/**
+ This is the base class for equation objects. Equations objects describe the
+ finite element discretisation of one or more equations.
+
+ Equation objects need only provide functions which set up the cell
+ matrices and the right hand side(s). These are then automatically inserted
+ into the global matrices and vectors.
+ */
+template <int dim>
+class Equation {
+ public:
+ /**
+ * Constructor. You have to pass the number
+ * of equations you want to discretize, which
+ * equals the number of solution functions.
+ */
+ Equation (const unsigned int n_equations);
+
+ /**
+ * Virtual function which assembles the
+ * cell matrix and a specific (user
+ * selectable) number of right hand sides
+ * on a given cell.
+ */
+ virtual void assemble (dFMatrix &cell_matrix,
+ vector<dVector> &rhs,
+ const FEValues<dim> &fe_values,
+ const Triangulation<dim>::cell_iterator &cell) const;
+
+ /**
+ * Virtual function which only assembles
+ * the cell matrix on a given cell.
+ */
+ virtual void assemble (dFMatrix &cell_matrix,
+ const FEValues<dim> &fe_values,
+ const Triangulation<dim>::cell_iterator &cell) const;
+
+ /**
+ * Virtual function which only assembles
+ * the right hand side(s) on a given cell.
+ */
+ virtual void assemble (vector<dVector> &rhs,
+ const FEValues<dim> &fe_values,
+ const Triangulation<dim>::cell_iterator &cell) const;
+
+ /**
+ * Return number of equations for this
+ * equation object. This equals the number
+ * of solution functions.
+ */
+ unsigned int n_equations () const;
+
+ /**
+ * Exception
+ */
+ DeclException0 (ExcPureVirtualFunctionCalled);
+
+ protected:
+ /**
+ * Store the number of solution functions,
+ * which is the same as the number of
+ * equations.
+ */
+ const unsigned int n_eq;
+};
+
+
+
+
+
+
+/**
+ An #Assembler# is a specialized version of a #DoFCellAccessor# which adds
+ functionality to assemble global matrices and vectors from cell base ones.
+ */
+template <int dim>
+class Assembler : public DoFCellAccessor<dim> {
+ public:
+ /**
+ * Structure to be passed upon
+ * construction of an assembler object.
+ */
+ struct AssemblerData {
+ /**
+ * Pointer to the dof handler object
+ * to be used to iterate on.
+ */
+ DoFHandler<dim> *dof;
+ /**
+ * Flags whether to assemble the matrix
+ * and right hand sides.
+ */
+ bool assemble_matrix, assemble_rhs;
+ /**
+ * How many right hand sides are there.
+ */
+ unsigned int n_rhs;
+ /**
+ * Pointer to the #ProblemBase# object
+ * of which the global matrices and
+ * vectors are to be assembled.
+ */
+ ProblemBase<dim> *problem;
+ /**
+ * Pointer to a quadrature object to be
+ * used for this assemblage process.
+ */
+ Quadrature<dim> *quadrature;
+ };
+
+ /**
+ * Default constructor, unused thus not
+ * implemented.
+ */
+ Assembler ();
+
+ /**
+ * Constructor. The #local_data#
+ * argument is assumed to be a pointer
+ * to an #AssemblerData# object. The data
+ * is copied, so the object need not live
+ * longer than the constructor call.
+ */
+ Assembler (Triangulation<dim> *tria,
+ const int level,
+ const int index,
+ const void *local_data);
+
+ /**
+ * Assemble on the present cell using
+ * the given equation object.
+ */
+ void assemble (const Equation<dim> &);
+
+ /**
+ * Exception.
+ */
+ DeclException0 (ExcNoAssemblingRequired);
+ /**
+ * Exception.
+ */
+ DeclException0 (ExcInvalidData);
+ /**
+ * Exception.
+ */
+ /**
+ * Exception.
+ */
+ private:
+ /**
+ * Store a local cell matrix.
+ */
+ dFMatrix cell_matrix;
+
+ /**
+ * Have room for a certain number of
+ * right hand sides.
+ */
+ vector<dVector> cell_vectors;
+
+ /**
+ * Store whether to assemble the
+ * global matrix.
+ */
+ bool assemble_matrix;
+
+ /**
+ * Store whether to assemble the
+ * right hand sides.
+ */
+ bool assemble_rhs;
+
+ /**
+ * Pointer to the problem class object
+ * of which we are to use the matrices
+ * and vectors.
+ */
+ ProblemBase<dim> *problem;
+
+ /**
+ * The finite element evaluated at the
+ * quadrature points.
+ */
+ FEValues<dim> fe_values;
+};
+
+
+
+
+
+/*---------------------------- problem_assembler.h ---------------------------*/
+/* end of #ifndef __problem_assembler_H */
+#endif
+/*---------------------------- problem_assembler.h ---------------------------*/
--- /dev/null
+/*---------------------------- problem_base.h ---------------------------*/
+/* $Id$ */
+#ifndef __problem_base_H
+#define __problem_base_H
+/*---------------------------- problem_base.h ---------------------------*/
+
+
+#include "../deal/dsmatrix.h"
+
+
+// forward declaration
+template <int dim> class Triangulation;
+template <int dim> class DoFHandler;
+template <int dim> class FiniteElement;
+template <int dim> class Quadrature;
+
+
+
+
+
+template <int dim>
+class ProblemBase {
+ public:
+ ProblemBase (Triangulation<dim> *tria,
+ DoFHandler<dim> *dof_handler);
+
+ virtual void assemble (const Equation<dim> &equation,
+ const Quadrature<dim> &q);
+
+ protected:
+ Triangulation<dim> *tria;
+ DoFHandler<dim> *dof_handler;
+
+ dSMatrix system_matrix;
+ dSMatrixStruct system_sparsity;
+
+ vector<dVector*> right_hand_sides;
+ dVector solution;
+
+ friend class Assembler<dim>;
+};
+
+
+
+
+/*---------------------------- problem_base.h ---------------------------*/
+/* end of #ifndef __problem_base_H */
+#endif
+/*---------------------------- problem_base.h ---------------------------*/
--- /dev/null
+/*---------------------------- io.h ---------------------------*/
+/* <Id:> */
+#ifndef __data_io_H
+#define __data_io_H
+/*---------------------------- io.h ---------------------------*/
+
+#include <basic/exceptions.h>
+#include <vector.h>
+
+#ifdef DEBUG
+# define _G_NO_NRV // don't use GNU's named return values in debug modes
+# include <String.h> // because if we did we'd harvest tons of warnings.
+# undef _G_NO_NRV
+#else
+# include <String.h>
+#endif
+
+
+template <int dim>
+class DoFHandler;
+
+class dVector;
+
+
+
+/**
+ This class implements an output mechanism for grid and simulation data
+ in several formats.
+ At present it supports output in UCD (unstructured cell data) and
+ partly in GNUPLOT format.
+
+ It allows the user to attach a degree of freedom handler object
+ (#DoFHandler#) which also gives access to the geometry data of the
+ underlying triangulation and to add data vectors of which the values
+ are to be written.
+
+
+ {\bf Limitations}
+
+ At present, no grouping of components to vectors is implemented, i.e.
+ you can only write each component independent of the others. Also, it
+ is not possible to output calculations which were performed on elements
+ with more or less than one degree of freedom per vertex.
+
+
+ {\bf UCD format}
+
+ The UCD format is described in the AVS developer's guide. Due to
+ limitations in the present format, only node based data can be output,
+ so higher order elements are only written with their node values, no
+ interior or line values are used. No use is made of the possibility
+ to give cell and model data since these are not supported by all
+ UCD aware programs.
+
+ The ASCII UCD format is used. In future versions, a binary version may
+ follow up.
+
+ Note that to enumerate the vertices, not the vertex index is used but
+ the index of the degree of freedom located on this vertex. This makes
+ the mapping between the vertices and the entries in the data vectors
+ much easier.
+
+
+ {\bg GNUPLOT format}
+
+ The gnuplot format is not able to handle data on unstructured grids, so
+ the actual data is ignored in two and three space dimension. In one
+ dimension, both mesh and data is written, in two and three dimensions
+ only the grid is printed as a sequence of lines.
+
+ For more than one dimension, the #DataOut<dim>::write_gnuplot()# somehow
+ duplicates the functionality of the #Triangulation<dim>::print_gnuplot()#
+ functions. These, however, offer more functionality.
+
+ To view the results in two or three dimensions, use #set data style lines#
+ within gnuplot and call #plot "filename"#. In one dimension call
+ #plot "filename" using 1:x#. #x# denotes the number of the data set you
+ want to see plus one. For example #using 1:4# would mean to plot the
+ third data vector.
+ */
+template <int dim>
+class DataOut {
+ public:
+ /**
+ * Constructor
+ */
+ DataOut ();
+
+ /**
+ * Designate a dof handler to be used
+ * to extract geometry data and the
+ * mapping between nodes and node values.
+ */
+ void attach_dof_handler (DoFHandler<dim> &);
+
+ /**
+ * Add a data vector together with its
+ * name and the physical unit
+ * (e.g. meter, kelvin, etc). By default,
+ * "<dimensionless>" is assumed for the
+ * units.
+ *
+ * A pointer to the vector is stored, so
+ * you have to make sure the vector
+ * exists at that address at least as
+ * long as you call the
+ * #write_*# functions.
+ *
+ * It is assumed that the vector has the
+ * same number of components as there are
+ * degrees of freedom in the dof handler.
+ * Therefore, no block vectors are allowed
+ * at present.
+ */
+ void add_data_vector (dVector &data,
+ String &name,
+ String &units="<dimensionless>");
+
+ /**
+ * Release the pointers to the data
+ * vectors. You have to set all data
+ * entries again using the
+ * #add_data_vector# function. The pointer
+ * to the dof handler remains stored,
+ * however.
+ */
+ void clear_data_vectors ();
+
+ /**
+ * Write the stored data to the given
+ * stream in UCD data. You may have
+ * written any comment to that stream
+ * before calling this function. Comments
+ * start with the \# character in the
+ * first column of a line and may only
+ * appear at the beginning of a file,
+ * without non-comment lines inbetween.
+ */
+ void write_ucd (ostream &out) const;
+
+ /**
+ * Write data and grid in one dimension,
+ * only grid in two or three dimensions.
+ */
+ void write_gnuplot (ostream &out) const;
+
+ /**
+ * Exception
+ */
+ DeclException0 (ExcIncorrectDofsPerVertex);
+ /**
+ * Exception
+ */
+ DeclException0 (ExcNotImplemented);
+ /**
+ * Exception
+ */
+ DeclException0 (ExcNoDoFHandlerSelected);
+
+ private:
+
+ /**
+ * Declare an entry in the list of
+ * data elements.
+ */
+ struct DataEntry {
+ /**
+ * Pointer to the data vector.
+ */
+ dVector *data;
+ /**
+ * Name of this component.
+ */
+ String name;
+ /**
+ * Physical unit name of this
+ * component.
+ */
+ String units;
+ };
+
+ /**
+ * Pointer to the dof handler object.
+ */
+ DoFHandler<dim> *dofs;
+
+ /**
+ * List of data elements.
+ */
+ vector<DataEntry> data;
+};
+
+
+
+
+
+/*---------------------------- io.h ---------------------------*/
+/* end of #ifndef __data_io_H */
+#endif
+/*---------------------------- io.h ---------------------------*/
--- /dev/null
+# $Id$
+
+all: lib.g.a lib.a
+
+lib.g.a:
+ @cd basic ; make lib.g.a
+ @cd grid ; make lib.g.a
+ @cd fe ; make lib.g.a
+ @cd numeric ; make lib.g.a
+
+
+lib.a:
+ @cd basic ; make lib.a
+ @cd grid ; make lib.a
+ @cd fe ; make lib.a
+ @cd numeric ; make lib.a
+
+clean:
+ @cd basic ; make clean
+ @cd grid ; make clean
+ @cd fe ; make clean
+ @cd numeric ; make clean
+
+
+
+.PHONY: all lib.g.a lib.a clean
--- /dev/null
+/* $Id$ */
+
+
+#include <grid/dof_accessor.h>
+#include <grid/dof.h>
+#include <grid/tria_iterator.h>
+#include <grid/tria_iterator.templates.h>
+#include <vector.h>
+
+
+extern TriaIterator<1,DoFCellAccessor<1> > __dummy257; //do this to calm down gcc2.7,
+extern TriaIterator<2,DoFCellAccessor<2> > __dummy258; //wait for gcc2.8
+extern TriaIterator<1,DoFLineAccessor<1,CellAccessor<1> > > __dummy259;
+extern TriaIterator<2,DoFQuadAccessor<2,QuadAccessor<2> > > __dummy260;
+extern TriaIterator<2,DoFQuadAccessor<2,CellAccessor<2> > > __dummy261;
+
+
+
+
+/*------------------------- Functions: DoFLineAccessor -----------------------*/
+
+
+template <int dim, class BaseClass>
+int DoFLineAccessor<dim,BaseClass>::dof_index (const unsigned int i) const {
+ Assert (dof_handler != 0, ExcInvalidObject());
+ // make sure a FE has been selected
+ // and enough room was reserved
+ Assert (dof_handler->selected_fe != 0, ExcInvalidObject());
+ Assert (i<dof_handler->selected_fe->dofs_per_line,
+ ExcInvalidIndex (i, 0, dof_handler->selected_fe->dofs_per_line));
+
+ return dof_handler->levels[present_level]
+ ->line_dofs[present_index*dof_handler->selected_fe->dofs_per_line+i];
+};
+
+
+
+
+
+template <int dim, class BaseClass>
+void DoFLineAccessor<dim,BaseClass>::set_dof_index (const unsigned int i,
+ const int index) const {
+ Assert (dof_handler != 0, ExcInvalidObject());
+ // make sure a FE has been selected
+ // and enough room was reserved
+ Assert (dof_handler->selected_fe != 0, ExcInvalidObject());
+ Assert (i<dof_handler->selected_fe->dofs_per_line,
+ ExcInvalidIndex (i, 0, dof_handler->selected_fe->dofs_per_line));
+
+ dof_handler->levels[present_level]
+ ->line_dofs[present_index*dof_handler->selected_fe->dofs_per_line+i] = index;
+};
+
+
+
+
+template <int dim, class BaseClass>
+int DoFLineAccessor<dim,BaseClass>::vertex_dof_index (const unsigned int vertex,
+ const unsigned int i) const {
+ Assert (dof_handler != 0, ExcInvalidObject());
+ Assert (dof_handler->selected_fe != 0, ExcInvalidObject());
+ Assert (vertex<2, ExcInvalidIndex (i,0,2));
+ Assert (i<dof_handler->selected_fe->dofs_per_vertex,
+ ExcInvalidIndex (i, 0, dof_handler->selected_fe->dofs_per_vertex));
+
+ const unsigned int dof_number = (vertex_index(vertex) *
+ dof_handler->selected_fe->dofs_per_vertex +
+ i);
+ return dof_handler->vertex_dofs[dof_number];
+};
+
+
+
+template <int dim, class BaseClass>
+void DoFLineAccessor<dim,BaseClass>::set_vertex_dof_index (const unsigned int vertex,
+ const unsigned int i,
+ const int index) const {
+ Assert (dof_handler != 0, ExcInvalidObject());
+ Assert (dof_handler->selected_fe != 0, ExcInvalidObject());
+ Assert (vertex<2, ExcInvalidIndex (i,0,2));
+ Assert (i<dof_handler->selected_fe->dofs_per_vertex,
+ ExcInvalidIndex (i, 0, dof_handler->selected_fe->dofs_per_vertex));
+
+ const unsigned int dof_number = (vertex_index(vertex) *
+ dof_handler->selected_fe->dofs_per_vertex +
+ i);
+ dof_handler->vertex_dofs[dof_number] = index;
+};
+
+
+
+template <int dim, class BaseClass>
+TriaIterator<dim,DoFLineAccessor<dim,BaseClass> >
+DoFLineAccessor<dim,BaseClass>::child (const unsigned int i) const {
+ TriaIterator<dim,DoFLineAccessor<dim,BaseClass> > q (tria,
+ present_level+1,
+ child_index (i),
+ dof_handler);
+
+#ifdef DEBUG
+ if (q.state() != past_the_end)
+ Assert (q->used(), ExcUnusedCellAsChild());
+#endif
+ return q;
+};
+
+
+
+template <int dim, class BaseClass>
+void DoFLineAccessor<dim,BaseClass>::copy_from (const DoFLineAccessor<dim,BaseClass> &a) {
+ BaseClass::copy_from (a);
+ set_dof_handler (a.dof_handler);
+};
+
+
+
+/*------------------------- Functions: DoFQuadAccessor -----------------------*/
+
+
+template <int dim, class BaseClass>
+int DoFQuadAccessor<dim,BaseClass>::dof_index (const unsigned int i) const {
+ Assert (dof_handler != 0, ExcInvalidObject());
+ // make sure a FE has been selected
+ // and enough room was reserved
+ Assert (dof_handler->selected_fe != 0, ExcInvalidObject());
+ Assert (i<dof_handler->selected_fe->dofs_per_quad,
+ ExcInvalidIndex (i, 0, dof_handler->selected_fe->dofs_per_quad));
+
+ return dof_handler->levels[present_level]
+ ->quad_dofs[present_index*dof_handler->selected_fe->dofs_per_quad+i];
+};
+
+
+
+template <int dim, class BaseClass>
+void DoFQuadAccessor<dim,BaseClass>::set_dof_index (const unsigned int i,
+ const int index) const {
+ Assert (dof_handler != 0, ExcInvalidObject());
+ // make sure a FE has been selected
+ // and enough room was reserved
+ Assert (dof_handler->selected_fe != 0, ExcInvalidObject());
+ Assert (i<dof_handler->selected_fe->dofs_per_quad,
+ ExcInvalidIndex (i, 0, dof_handler->selected_fe->dofs_per_quad));
+
+ dof_handler->levels[present_level]
+ ->quad_dofs[present_index*dof_handler->selected_fe->dofs_per_quad+i] = index;
+};
+
+
+
+template <int dim, class BaseClass>
+int DoFQuadAccessor<dim,BaseClass>::vertex_dof_index (const unsigned int vertex,
+ const unsigned int i) const {
+ Assert (dof_handler != 0, ExcInvalidObject());
+ Assert (dof_handler->selected_fe != 0, ExcInvalidObject());
+ Assert (vertex<4, ExcInvalidIndex (i,0,4));
+ Assert (i<dof_handler->selected_fe->dofs_per_vertex,
+ ExcInvalidIndex (i, 0, dof_handler->selected_fe->dofs_per_vertex));
+
+ const unsigned int dof_number = (vertex_index(vertex) *
+ dof_handler->selected_fe->dofs_per_vertex +
+ i);
+ return dof_handler->vertex_dofs[dof_number];
+};
+
+
+
+template <int dim, class BaseClass>
+void DoFQuadAccessor<dim,BaseClass>::set_vertex_dof_index (const unsigned int vertex,
+ const unsigned int i,
+ const int index) const {
+ Assert (dof_handler != 0, ExcInvalidObject());
+ Assert (dof_handler->selected_fe != 0, ExcInvalidObject());
+ Assert (vertex<4, ExcInvalidIndex (i,0,4));
+ Assert (i<dof_handler->selected_fe->dofs_per_vertex,
+ ExcInvalidIndex (i, 0, dof_handler->selected_fe->dofs_per_vertex));
+
+ const unsigned int dof_number = (vertex_index(vertex) *
+ dof_handler->selected_fe->dofs_per_vertex +
+ i);
+ dof_handler->vertex_dofs[dof_number] = index;
+};
+
+
+
+template <int dim, class BaseClass>
+TriaIterator<dim,DoFLineAccessor<dim,LineAccessor<dim> > >
+DoFQuadAccessor<dim,BaseClass>::line (const unsigned int i) const {
+ Assert (i<4, ExcInvalidIndex (i, 0, 4));
+
+ return TriaIterator<dim,DoFLineAccessor<dim,LineAccessor<dim> > >
+ (
+ tria,
+ present_level,
+ line_index (i),
+ dof_handler
+ );
+};
+
+
+
+template <int dim, class BaseClass>
+TriaIterator<dim,DoFQuadAccessor<dim,BaseClass> >
+DoFQuadAccessor<dim,BaseClass>::child (const unsigned int i) const {
+ TriaIterator<dim,DoFQuadAccessor<dim,BaseClass> > q (tria,
+ present_level+1,
+ child_index (i),
+ dof_handler);
+
+#ifdef DEBUG
+ if (q.state() != past_the_end)
+ Assert (q->used(), ExcUnusedCellAsChild());
+#endif
+ return q;
+};
+
+
+
+template <int dim, class BaseClass>
+void DoFQuadAccessor<dim,BaseClass>::copy_from (const DoFQuadAccessor<dim,BaseClass> &a) {
+ Assert (a.dof_handler != 0, ExcInvalidObject());
+
+ BaseClass::copy_from (a);
+ set_dof_handler (a.dof_handler);
+};
+
+
+
+/*------------------------- Functions: DoFCellAccessor -----------------------*/
+
+template <int dim>
+TriaIterator<dim,DoFCellAccessor<dim> >
+DoFCellAccessor<dim>::neighbor (const unsigned int i) const {
+ TriaIterator<dim,DoFCellAccessor<dim> > q (tria,
+ neighbor_level (i),
+ neighbor_index (i),
+ dof_handler);
+
+#ifdef DEBUG
+ if (q.state() != past_the_end)
+ Assert (q->used(), ExcUnusedCellAsNeighbor());
+#endif
+ return q;
+};
+
+
+
+template <int dim>
+TriaIterator<dim,DoFCellAccessor<dim> >
+DoFCellAccessor<dim>::child (const unsigned int i) const {
+ TriaIterator<dim,DoFCellAccessor<dim> > q (tria,
+ present_level+1,
+ child_index (i),
+ dof_handler);
+
+#ifdef DEBUG
+ if (q.state() != past_the_end)
+ Assert (q->used(), ExcUnusedCellAsChild());
+#endif
+ return q;
+};
+
+
+
+void
+DoFCellAccessor<1>::dof_indices (vector<int> &dof_indices) const {
+ Assert (dof_handler != 0, ExcInvalidObject());
+ Assert (&dof_handler->get_selected_fe() != 0, ExcInvalidObject());
+
+ dof_indices.reserve (dof_indices.size() +
+ dof_handler->get_selected_fe().total_dofs);
+ for (unsigned int vertex=0; vertex<2; ++vertex)
+ for (unsigned int d=0; d<dof_handler->get_selected_fe().dofs_per_vertex; ++d)
+ dof_indices.push_back (vertex_dof_index(vertex,d));
+ for (unsigned int d=0; d<dof_handler->get_selected_fe().dofs_per_line; ++d)
+ dof_indices.push_back (dof_index(d));
+};
+
+
+
+// do this to calm down gcc2.7; wait for gcc2.8
+extern TriaIterator<2,DoFLineAccessor<2,LineAccessor<2> > > __dummya;
+
+
+void
+DoFCellAccessor<2>::dof_indices (vector<int> &dof_indices) const {
+ Assert (dof_handler != 0, ExcInvalidObject());
+ Assert (&dof_handler->get_selected_fe() != 0, ExcInvalidObject());
+
+ dof_indices.reserve (dof_indices.size() +
+ dof_handler->get_selected_fe().total_dofs);
+ for (unsigned int vertex=0; vertex<4; ++vertex)
+ for (unsigned int d=0; d<dof_handler->get_selected_fe().dofs_per_vertex; ++d)
+ dof_indices.push_back (vertex_dof_index(vertex,d));
+ for (unsigned int line=0; line<4; ++line)
+ for (unsigned int d=0; d<dof_handler->get_selected_fe().dofs_per_line; ++d)
+ dof_indices.push_back (this->line(line)->dof_index(d));
+};
+
+
+// explicit instantiations
+template class DoFLineAccessor<1,CellAccessor<1> >;
+template class DoFCellAccessor<1>;
+
+template class DoFLineAccessor<2,LineAccessor<2> >;
+template class DoFQuadAccessor<2,QuadAccessor<2> >;
+template class DoFQuadAccessor<2,CellAccessor<2> >;
+template class DoFCellAccessor<2>;
+
+template class TriaRawIterator<1,DoFCellAccessor<1> >;
+template class TriaRawIterator<2,DoFLineAccessor<2,LineAccessor<2> > >;
+template class TriaRawIterator<2,DoFCellAccessor<2> >;
+
+template class TriaIterator<1,DoFCellAccessor<1> >;
+template class TriaIterator<2,DoFLineAccessor<2,LineAccessor<2> > >;
+template class TriaIterator<2,DoFCellAccessor<2> >;
+
+template class TriaActiveIterator<1,DoFCellAccessor<1> >;
+template class TriaActiveIterator<2,DoFLineAccessor<2,LineAccessor<2> > >;
+template class TriaActiveIterator<2,DoFCellAccessor<2> >;
+
--- /dev/null
+/* $Id$ */
+
+
+#include <algo.h>
+#include <grid/dof_constraints.h>
+#include "../deal/dsmatrix.h"
+#include <iostream.h>
+
+
+
+
+bool ConstraintMatrix::ConstraintLine::operator < (const ConstraintMatrix::ConstraintLine &a) const {
+ return line < a.line;
+};
+
+
+
+
+ConstraintMatrix::ConstraintMatrix () :
+ lines(), sorted(false) {};
+
+
+
+void ConstraintMatrix::add_line (const unsigned int line) {
+ // check whether line already exists
+ Assert (sorted==false, ExcMatrixIsClosed());
+#ifdef DEBUG
+ for (unsigned int i=0; i!=lines.size(); ++i)
+ Assert (lines[i].line != line, ExcLineExists(line));
+#endif
+
+ // push a new line to the end of the
+ // list
+ lines.push_back (ConstraintLine());
+ lines.back().line = line;
+};
+
+
+
+void ConstraintMatrix::add_entry (const unsigned int line,
+ const unsigned int column,
+ const double value) {
+ Assert (sorted==false, ExcMatrixIsClosed());
+
+ vector<ConstraintLine>::iterator line_ptr;
+ if (lines.back().line == line)
+ line_ptr = &lines.back();
+ else
+ {
+ for (line_ptr = &lines.back()-1; line_ptr>=lines.begin(); --line_ptr)
+ if ((*line_ptr).line == line)
+ break;
+ Assert (false, ExcLineInexistant(line));
+ };
+
+ (*line_ptr).entries.push_back (make_pair(column,value));
+};
+
+
+
+
+void ConstraintMatrix::close () {
+ Assert (sorted==false, ExcMatrixIsClosed());
+
+ // sort the entries in the different lines
+ vector<ConstraintLine>::iterator line = lines.begin(),
+ endl = lines.end();
+ for (; line!=endl; ++line)
+ sort ((*line).entries.begin(), (*line).entries.end());
+
+ // sort the lines
+ sort (lines.begin(), lines.end());
+
+ sorted = true;
+};
+
+
+
+void ConstraintMatrix::clear () {
+ lines = vector<ConstraintLine>();
+ sorted = false;
+};
+
+
+
+void ConstraintMatrix::condense (const dSMatrixStruct &uncondensed,
+ dSMatrixStruct &condensed) const {
+ Assert (sorted == true, ExcMatrixNotClosed());
+ Assert (uncondensed.compressed == true, ExcMatrixNotClosed());
+ Assert (uncondensed.n_rows() == uncondensed.n_cols(),
+ ExcMatrixNotSquare());
+
+ // store for each line of the matrix
+ // its new line number
+ // after compression. If the shift is
+ // -1, this line will be condensed away
+ vector<int> new_line;
+
+ new_line.reserve (uncondensed.n_rows());
+
+ vector<ConstraintLine>::const_iterator next_constraint = lines.begin();
+ unsigned int shift = 0;
+ unsigned int n_rows = (unsigned int)uncondensed.n_rows();
+ for (unsigned int row=0; row!=n_rows; ++row)
+ if (row == (*next_constraint).line)
+ {
+ // this line is constrained
+ new_line.push_back (-1);
+ // not that #lines# is ordered
+ ++next_constraint;
+ ++shift;
+ }
+ else
+ new_line.push_back (row-shift);
+
+
+ next_constraint = lines.begin();
+ for (int row=0; row<uncondensed.rows; ++row)
+ if (new_line[row] != -1)
+ // line not constrained
+ // copy entries if column will not
+ // be condensed away, distribute
+ // otherwise
+ for (int j=uncondensed.rowstart[row]; j<uncondensed.rowstart[row+1]; ++j)
+ if (new_line[uncondensed.colnums[j]] != -1)
+ condensed.add (new_line[row], new_line[uncondensed.colnums[j]]);
+ else
+ {
+ // let c point to the constraint
+ // of this column
+ vector<ConstraintLine>::const_iterator c = lines.begin();
+ while ((*c).line != (unsigned int)uncondensed.colnums[j]) ++c;
+
+ for (unsigned int q=0; q!=(*c).entries.size(); ++q)
+ condensed.add (new_line[row], new_line[(*c).entries[q].first]);
+ }
+ else
+ // line must be distributed
+ {
+ for (int j=uncondensed.rowstart[row]; j<uncondensed.rowstart[row+1]; ++j)
+ // for each entry: distribute
+ if (new_line[uncondensed.colnums[j]] != -1)
+ // column is not constrained
+ for (unsigned int q=0; q!=(*next_constraint).entries.size(); ++q)
+ condensed.add (new_line[(*next_constraint).entries[q].first],
+ new_line[uncondensed.colnums[j]]);
+
+ else
+ // not only this line but
+ // also this col is constrained
+ {
+ // let c point to the constraint
+ // of this column
+ vector<ConstraintLine>::const_iterator c = lines.begin();
+ while ((*c).line != (unsigned int)uncondensed.colnums[j]) ++c;
+
+ for (unsigned int p=0; p!=(*c).entries.size(); ++p)
+ for (unsigned int q=0; q!=(*next_constraint).entries.size(); ++q)
+ condensed.add (new_line[(*next_constraint).entries[q].first],
+ new_line[(*c).entries[p].first]);
+ };
+
+ ++next_constraint;
+ };
+};
+
+
+
+void ConstraintMatrix::condense (dSMatrixStruct &sparsity) const {
+ Assert (sorted == true, ExcMatrixNotClosed());
+ Assert (sparsity.compressed == false, ExcMatrixIsClosed());
+ Assert (sparsity.n_rows() == sparsity.n_cols(),
+ ExcMatrixNotSquare());
+
+ // store for each index whether it
+ // must be distributed or not. If entry
+ // is -1, no distribution is necessary.
+ // otherwise, the number states which
+ // line in the constraint matrix handles
+ // this index
+ vector<int> distribute;
+ distribute.reserve (sparsity.n_rows());
+ distribute.insert (distribute.end(), sparsity.n_rows(), -1);
+
+ for (int c=0; c<(signed int)lines.size(); ++c)
+ distribute[lines[c].line] = c;
+
+ int n_rows = sparsity.n_rows();
+ for (int row=0; row<n_rows; ++row)
+ if (distribute[row] == -1)
+ // regular line. loop over cols
+ for (int j=sparsity.rowstart[row]; j<sparsity.rowstart[row+1]; ++j)
+ // end of row reached?
+ if (sparsity.colnums[j] == -1)
+ break;
+ else
+ {
+ if (distribute[sparsity.colnums[j]] != -1)
+ // distribute entry at regular
+ // row #row# and irregular column
+ // sparsity.colnums[j]
+ for (unsigned int q=0;
+ q!=lines[distribute[sparsity.colnums[j]]].entries.size(); ++q)
+ sparsity.add (row,
+ lines[distribute[sparsity.colnums[j]]].entries[q].first);
+ }
+ else
+ // row must be distributed
+ for (int j=sparsity.rowstart[row]; j<sparsity.rowstart[row+1]; ++j)
+ // end of row reached?
+ if (sparsity.colnums[j] == -1)
+ break;
+ else
+ {
+ if (distribute[sparsity.colnums[j]] == -1)
+ // distribute entry at irregular
+ // row #row# and regular column
+ // sparsity.colnums[j]
+ for (unsigned int q=0;
+ q!=lines[distribute[row]].entries.size(); ++q)
+ sparsity.add (lines[distribute[row]].entries[q].first,
+ sparsity.colnums[j]);
+ else
+ // distribute entry at irregular
+ // row #row# and irregular column
+ // sparsity.colnums[j]
+ for (unsigned int p=0; p!=lines[distribute[row]].entries.size(); ++p)
+ for (unsigned int q=0;
+ q!=lines[distribute[sparsity.colnums[j]]].entries.size(); ++q)
+ sparsity.add (lines[distribute[row]].entries[p].first,
+ lines[distribute[sparsity.colnums[j]]].entries[q].first);
+ };
+ sparsity.compress();
+};
+
+
+
+
+
+unsigned int ConstraintMatrix::n_constraints () const {
+ return lines.size();
+};
+
+
+
+void ConstraintMatrix::print (ostream &out) const {
+ for (unsigned int i=0; i!=lines.size(); ++i)
+ for (unsigned int j=0; j!=lines[i].entries.size(); ++j)
+ out << " " << lines[i].line
+ << " " << lines[i].entries[j].first
+ << ": " << lines[i].entries[j].second << endl;
+};
--- /dev/null
+/* $Id$ */
+
+#include <grid/dof.h>
+#include <grid/dof_accessor.h>
+#include <grid/dof_constraints.h>
+#include <grid/tria_accessor.h>
+#include <grid/tria_iterator.h>
+#include <grid/tria.h>
+#include "../deal/dsmatrix.h"
+#include <multimap.h>
+#include <algo.h>
+
+
+extern TriaRawIterator<1,LineAccessor<1> > _dummy112;
+extern TriaRawIterator<2,LineAccessor<2> > _dummy113;
+extern TriaIterator<1,LineAccessor<1> > _dummy114;
+extern TriaIterator<2,LineAccessor<2> > _dummy115;
+extern TriaActiveIterator<1,LineAccessor<1> > _dummy116;
+extern TriaActiveIterator<2,LineAccessor<2> > _dummy117;
+
+extern TriaRawIterator<2,QuadAccessor<2> > _dummy118;
+extern TriaIterator<2,QuadAccessor<2> > _dummy119;
+extern TriaActiveIterator<2,QuadAccessor<2> > _dummy120;
+
+extern TriaRawIterator<1,CellAccessor<1> > _dummy121;
+extern TriaRawIterator<2,CellAccessor<2> > _dummy122;
+extern TriaIterator<1,CellAccessor<1> > _dummy123;
+extern TriaIterator<2,CellAccessor<2> > _dummy124;
+extern TriaActiveIterator<1,CellAccessor<1> > _dummy125;
+extern TriaActiveIterator<2,CellAccessor<2> > _dummy126;
+
+extern DoFCellAccessor<1> _dummy127; //do this to calm down gcc2.7
+extern TriaRawIterator<1,DoFCellAccessor<1> > _dummy128; //wait for gcc2.8
+extern TriaIterator<1,DoFCellAccessor<1> > _dummy129;
+extern TriaActiveIterator<1,DoFCellAccessor<1> > _dummy130;
+
+extern DoFCellAccessor<2> _dummy131; //do this to calm down gcc2.7
+extern TriaRawIterator<2,DoFLineAccessor<2,LineAccessor<2> > > _dummy132; //wait for gcc2.8
+extern TriaIterator<2,DoFLineAccessor<2,LineAccessor<2> > > _dummy133;
+extern TriaActiveIterator<2,DoFLineAccessor<2,LineAccessor<2> > > _dummy134;
+extern TriaRawIterator<2,DoFCellAccessor<2> > _dummy135; //wait for gcc2.8
+extern TriaIterator<2,DoFCellAccessor<2> > _dummy136;
+extern TriaActiveIterator<2,DoFCellAccessor<2> > _dummy137;
+
+extern Triangulation<1> _dummy138;
+extern Triangulation<2> _dummy139;
+
+
+
+template <int dim>
+DoFHandler<dim>::DoFHandler (Triangulation<dim> *tria) :
+ tria(tria),
+ selected_fe (0),
+ used_dofs (0) {};
+
+
+template <int dim>
+DoFHandler<dim>::~DoFHandler () {
+ if (selected_fe != 0)
+ delete selected_fe;
+};
+
+
+
+
+DoFHandler<1>::raw_cell_iterator
+DoFHandler<1>::begin_raw (const unsigned int level) const {
+ return begin_raw_line (level);
+};
+
+
+
+DoFHandler<1>::cell_iterator
+DoFHandler<1>::begin (const unsigned int level) const {
+ return begin_line (level);
+};
+
+
+
+DoFHandler<1>::active_cell_iterator
+DoFHandler<1>::begin_active (const unsigned int level) const {
+ return begin_active_line (level);
+};
+
+
+
+DoFHandler<1>::raw_cell_iterator
+DoFHandler<1>::end () const {
+ return end_line ();
+};
+
+
+
+DoFHandler<1>::raw_cell_iterator
+DoFHandler<1>::last_raw () const {
+ return last_raw_line ();
+};
+
+
+
+DoFHandler<1>::raw_cell_iterator
+DoFHandler<1>::last_raw (const unsigned int level) const {
+ return last_raw_line (level);
+};
+
+
+
+DoFHandler<1>::cell_iterator
+DoFHandler<1>::last () const {
+ return last_line ();
+};
+
+
+
+DoFHandler<1>::cell_iterator
+DoFHandler<1>::last (const unsigned int level) const {
+ return last_line (level);
+};
+
+
+
+DoFHandler<1>::active_cell_iterator
+DoFHandler<1>::last_active () const {
+ return last_active_line ();
+};
+
+
+
+DoFHandler<1>::active_cell_iterator
+DoFHandler<1>::last_active (const unsigned int level) const {
+ return last_active_line (level);
+};
+
+
+
+
+
+DoFHandler<2>::raw_cell_iterator
+DoFHandler<2>::begin_raw (const unsigned int level) const {
+ return begin_raw_quad (level);
+};
+
+
+
+DoFHandler<2>::cell_iterator
+DoFHandler<2>::begin (const unsigned int level) const {
+ return begin_quad (level);
+};
+
+
+
+DoFHandler<2>::active_cell_iterator
+DoFHandler<2>::begin_active (const unsigned int level) const {
+ return begin_active_quad (level);
+};
+
+
+
+DoFHandler<2>::raw_cell_iterator
+DoFHandler<2>::end () const {
+ return end_quad ();
+};
+
+
+
+DoFHandler<2>::raw_cell_iterator
+DoFHandler<2>::last_raw () const {
+ return last_raw_quad ();
+};
+
+
+
+DoFHandler<2>::raw_cell_iterator
+DoFHandler<2>::last_raw (const unsigned int level) const {
+ return last_raw_quad (level);
+};
+
+
+
+DoFHandler<2>::cell_iterator
+DoFHandler<2>::last () const {
+ return last_quad ();
+};
+
+
+
+DoFHandler<2>::cell_iterator
+DoFHandler<2>::last (const unsigned int level) const {
+ return last_quad (level);
+};
+
+
+
+DoFHandler<2>::active_cell_iterator
+DoFHandler<2>::last_active () const {
+ return last_active_quad ();
+};
+
+
+
+DoFHandler<2>::active_cell_iterator
+DoFHandler<2>::last_active (const unsigned int level) const {
+ return last_active_quad (level);
+};
+
+
+
+
+//------------------------------------------------------------------
+DoFHandler<1>::raw_cell_iterator
+DoFHandler<1>::begin_raw_line (const unsigned int level) const {
+ return raw_line_iterator (tria,
+ tria->begin_raw_line(level)->level(),
+ tria->begin_raw_line(level)->index(),
+ this);
+};
+
+
+
+DoFHandler<2>::raw_line_iterator
+DoFHandler<2>::begin_raw_line (const unsigned int level) const {
+ return raw_line_iterator (tria,
+ tria->begin_raw_line(level)->level(),
+ tria->begin_raw_line(level)->index(),
+ this);
+};
+
+
+
+DoFHandler<1>::line_iterator
+DoFHandler<1>::begin_line (const unsigned int level) const {
+ return line_iterator (tria,
+ tria->begin_line(level)->level(),
+ tria->begin_line(level)->index(),
+ this);
+};
+
+
+
+DoFHandler<2>::line_iterator
+DoFHandler<2>::begin_line (const unsigned int level) const {
+ return line_iterator (tria,
+ tria->begin_line(level)->level(),
+ tria->begin_line(level)->index(),
+ this);
+};
+
+
+
+DoFHandler<1>::active_line_iterator
+DoFHandler<1>::begin_active_line (const unsigned int level) const {
+ return active_line_iterator (tria,
+ tria->begin_active_line(level)->level(),
+ tria->begin_active_line(level)->index(),
+ this);
+};
+
+
+
+DoFHandler<2>::active_line_iterator
+DoFHandler<2>::begin_active_line (const unsigned int level) const {
+ return active_line_iterator (tria,
+ tria->begin_active_line(level)->level(),
+ tria->begin_active_line(level)->index(),
+ this);
+};
+
+
+
+DoFHandler<2>::raw_quad_iterator
+DoFHandler<2>::begin_raw_quad (const unsigned int level) const {
+ return raw_quad_iterator (tria,
+ tria->begin_raw_quad(level)->level(),
+ tria->begin_raw_quad(level)->index(),
+ this);
+};
+
+
+
+DoFHandler<2>::quad_iterator
+DoFHandler<2>::begin_quad (const unsigned int level) const {
+ return quad_iterator (tria,
+ tria->begin_quad(level)->level(),
+ tria->begin_quad(level)->index(),
+ this);
+};
+
+
+
+DoFHandler<2>::active_quad_iterator
+DoFHandler<2>::begin_active_quad (const unsigned int level) const {
+ return active_quad_iterator (tria,
+ tria->begin_active_quad(level)->level(),
+ tria->begin_active_quad(level)->index(),
+ this);
+};
+
+
+
+DoFHandler<1>::raw_line_iterator
+DoFHandler<1>::end_line () const {
+ return raw_line_iterator (tria, -1, -1, this);
+};
+
+
+
+DoFHandler<2>::raw_line_iterator
+DoFHandler<2>::end_line () const {
+ return raw_line_iterator (tria, -1, -1, this);
+};
+
+
+
+DoFHandler<2>::raw_quad_iterator
+DoFHandler<2>::end_quad () const {
+ return raw_quad_iterator (tria, -1, -1, this);
+};
+
+
+
+
+DoFHandler<1>::raw_line_iterator
+DoFHandler<1>::last_raw_line (const unsigned int level) const {
+ return raw_line_iterator (tria,
+ tria->last_raw_line(level)->level(),
+ tria->last_raw_line(level)->index(),
+ this);
+};
+
+
+
+DoFHandler<2>::raw_line_iterator
+DoFHandler<2>::last_raw_line (const unsigned int level) const {
+ return raw_line_iterator (tria,
+ tria->last_raw_line(level)->level(),
+ tria->last_raw_line(level)->index(),
+ this);
+};
+
+
+
+DoFHandler<1>::line_iterator
+DoFHandler<1>::last_line (const unsigned int level) const {
+ return line_iterator (tria,
+ tria->last_line(level)->level(),
+ tria->last_line(level)->index(),
+ this);
+};
+
+
+
+DoFHandler<2>::line_iterator
+DoFHandler<2>::last_line (const unsigned int level) const {
+ return line_iterator (tria,
+ tria->last_line(level)->level(),
+ tria->last_line(level)->index(),
+ this);
+};
+
+
+
+DoFHandler<1>::active_line_iterator
+DoFHandler<1>::last_active_line (const unsigned int level) const {
+ return active_line_iterator (tria,
+ tria->last_active_line(level)->level(),
+ tria->last_active_line(level)->index(),
+ this);
+};
+
+
+
+DoFHandler<2>::active_line_iterator
+DoFHandler<2>::last_active_line (const unsigned int level) const {
+ return active_line_iterator (tria,
+ tria->last_active_line(level)->level(),
+ tria->last_active_line(level)->index(),
+ this);
+};
+
+
+
+DoFHandler<2>::raw_quad_iterator
+DoFHandler<2>::last_raw_quad (const unsigned int level) const {
+ return raw_quad_iterator (tria,
+ tria->last_raw_quad(level)->level(),
+ tria->last_raw_quad(level)->index(),
+ this);
+};
+
+
+
+
+DoFHandler<2>::quad_iterator
+DoFHandler<2>::last_quad (const unsigned int level) const {
+ return quad_iterator (tria,
+ tria->last_quad(level)->level(),
+ tria->last_quad(level)->index(),
+ this);
+};
+
+
+
+
+DoFHandler<2>::active_quad_iterator
+DoFHandler<2>::last_active_quad (const unsigned int level) const {
+ return active_quad_iterator (tria,
+ tria->last_active_quad(level)->level(),
+ tria->last_active_quad(level)->index(),
+ this);
+};
+
+
+
+
+DoFHandler<1>::raw_line_iterator
+DoFHandler<1>::last_raw_line () const {
+ return last_raw_line (levels.size()-1);
+};
+
+
+
+DoFHandler<2>::raw_line_iterator
+DoFHandler<2>::last_raw_line () const {
+ return last_raw_line (levels.size()-1);
+};
+
+
+
+DoFHandler<2>::raw_quad_iterator
+DoFHandler<2>::last_raw_quad () const {
+ return last_raw_quad (levels.size()-1);
+};
+
+
+
+DoFHandler<1>::line_iterator
+DoFHandler<1>::last_line () const {
+ return last_line (levels.size()-1);
+};
+
+
+
+DoFHandler<2>::line_iterator
+DoFHandler<2>::last_line () const {
+ return last_line (levels.size()-1);
+};
+
+
+
+DoFHandler<2>::quad_iterator
+DoFHandler<2>::last_quad () const {
+ return last_quad (levels.size()-1);
+};
+
+
+
+DoFHandler<1>::active_line_iterator
+DoFHandler<1>::last_active_line () const {
+ return last_active_line (levels.size()-1);
+};
+
+
+
+DoFHandler<2>::active_line_iterator
+DoFHandler<2>::last_active_line () const {
+ return last_active_line (levels.size()-1);
+};
+
+
+
+DoFHandler<2>::active_quad_iterator
+DoFHandler<2>::last_active_quad () const {
+ return last_active_quad (levels.size()-1);
+};
+
+
+
+
+
+
+
+template <int dim>
+unsigned int DoFHandler<dim>::n_dofs () const {
+ return used_dofs;
+};
+
+
+
+template <int dim>
+const Triangulation<dim> & DoFHandler<dim>::get_tria () const {
+ return *tria;
+};
+
+
+
+template <int dim>
+const FiniteElement<dim> & DoFHandler<dim>::get_selected_fe () const {
+ return *selected_fe;
+};
+
+
+
+template <int dim>
+void DoFHandler<dim>::distribute_dofs (const FiniteElement<dim> &fe) {
+ Assert (tria->n_levels() > 0, ExcInvalidTriangulation());
+
+ reserve_space (fe);
+ if (selected_fe != 0) delete selected_fe;
+ selected_fe = new FiniteElement<dim>(fe);
+
+ // clear user flags because we will
+ // need them
+ tria->clear_user_flags ();
+
+ unsigned int next_free_dof = 0;
+ active_cell_iterator cell = begin_active(),
+ endc = end();
+ for (; cell != endc; ++cell)
+ next_free_dof = distribute_dofs_on_cell (cell, fe, next_free_dof);
+
+ used_dofs = next_free_dof;
+};
+
+
+
+int DoFHandler<1>::distribute_dofs_on_cell (active_cell_iterator &cell,
+ const FiniteElement<1> &fe,
+ unsigned int next_free_dof) {
+
+ // distribute dofs of vertices
+ for (unsigned int v=0; v<2; ++v)
+ {
+ cell_iterator neighbor = cell->neighbor(v);
+
+ if (neighbor.state() == valid)
+ {
+ // find true neighbor; may be its
+ // a child of #neighbor#
+ while (neighbor->has_children())
+ neighbor = neighbor->child(v==0 ? 1 : 0);
+
+ // has neighbor already been processed?
+ if (neighbor->user_flag_set())
+ // copy dofs
+ {
+ if (v==0)
+ for (unsigned int d=0; d<fe.dofs_per_vertex; ++d)
+ cell->set_vertex_dof_index (0, d, neighbor->vertex_dof_index (1, d));
+ else
+ for (unsigned int d=0; d<fe.dofs_per_vertex; ++d)
+ cell->set_vertex_dof_index (1, d, neighbor->vertex_dof_index (0, d));
+
+ // next neighbor
+ continue;
+ };
+ };
+
+ // otherwise: create dofs newly
+ for (unsigned int d=0; d<fe.dofs_per_vertex; ++d)
+ cell->set_vertex_dof_index (v, d, next_free_dof++);
+ };
+
+ // dofs of line
+ for (unsigned int d=0; d<fe.dofs_per_line; ++d)
+ cell->set_dof_index (d, next_free_dof++);
+
+ // note that this cell has been processed
+ cell->set_user_flag ();
+
+ return next_free_dof;
+};
+
+
+
+
+int DoFHandler<2>::distribute_dofs_on_cell (active_cell_iterator &cell,
+ const FiniteElement<2> &fe,
+ unsigned int next_free_dof) {
+ if (fe.dofs_per_vertex > 0)
+ // number dofs on vertices
+ for (unsigned int vertex=0; vertex<4; ++vertex)
+ // check whether dofs for this
+ // vertex have been distributed
+ // (only check the first dof)
+ if (cell->vertex_dof_index(vertex, 0) == -1)
+ for (unsigned int d=0; d<fe.dofs_per_vertex; ++d)
+ cell->set_vertex_dof_index (vertex, d, next_free_dof++);
+
+ // for the four sides
+ for (unsigned int side=0; side<4; ++side)
+ {
+ line_iterator line = cell->line(side);
+
+ // distribute dofs if necessary
+ if ((fe.dofs_per_line > 0) &&
+ // check whether line dof is already
+ // numbered (check only first dof)
+ (line->dof_index(0) == -1))
+ // if not: distribute dofs
+ for (unsigned int d=0; d<fe.dofs_per_line; ++d)
+ line->set_dof_index (d, next_free_dof++);
+
+ // note if line is subject to constraints
+ if (line->child_index(0) != -1)
+ line->set_user_flag ();
+ };
+
+
+ // dofs of quad
+ if (fe.dofs_per_quad > 0)
+ for (unsigned int d=0; d<fe.dofs_per_line; ++d)
+ cell->set_dof_index (d, next_free_dof++);
+
+
+ // note that this cell has been processed
+ cell->set_user_flag ();
+
+ return next_free_dof;
+};
+
+
+
+
+template <int dim>
+void DoFHandler<dim>::renumber_dofs (const RenumberingMethod method,
+ bool use_constraints,
+ const vector<int> &starting_points) {
+ // make the connection graph
+ dSMatrixStruct sparsity (n_dofs(), max_couplings_between_dofs());
+ make_sparsity_pattern (sparsity);
+
+ if (use_constraints)
+ {
+ ConstraintMatrix constraints;
+ make_constraint_matrix (constraints);
+ constraints.condense (sparsity);
+ };
+
+ int n_dofs = sparsity.n_rows();
+ // store the new dof numbers; -1 means
+ // that no new number was chosen yet
+ vector<int> new_number(sparsity.n_rows(), -1);
+
+ // store the indices of the dofs renumbered
+ // in the last round. Default to starting
+ // points
+ vector<int> last_round_dofs (starting_points);
+ // delete disallowed elements
+ for (unsigned int i=0; i<last_round_dofs.size(); ++i)
+ if ((last_round_dofs[i]<0) || (last_round_dofs[i]>=n_dofs))
+ last_round_dofs[i] = -1;
+ remove_if (last_round_dofs.begin(), last_round_dofs.end(),
+ bind2nd(equal_to<int>(), 0));
+
+ // now if no valid points remain:
+ // find dof with lowest coordination
+ // number
+ if (last_round_dofs.size() == 0)
+ {
+ int starting_point = -1;
+ unsigned int min_coordination = n_dofs;
+ for (int row=0; row<n_dofs; ++row)
+ {
+ int j;
+ for (j=sparsity.rowstart[row]; j<sparsity.rowstart[row+1]; ++j)
+ if (sparsity.colnums[j] == -1)
+ break;
+ // post: coordination is now
+ // j-rowstart[row]
+ if (j-sparsity.rowstart[row] < (signed int)min_coordination)
+ {
+ min_coordination = j-sparsity.rowstart[row];
+ starting_point = row;
+ };
+ };
+ // initialize the first dof
+ last_round_dofs.push_back (starting_point);
+ };
+
+
+ // store next free dof index
+ int next_free_number = 0;
+
+ // enumerate the first round dofs
+ for (unsigned int i=0; i!=last_round_dofs.size(); ++i)
+ new_number[last_round_dofs[i]] = next_free_number++;
+
+ bool all_dofs_renumbered = false;
+
+ // now do as many steps as needed to
+ // renumber all dofs
+ while (!all_dofs_renumbered)
+ {
+ // store the indices of the dofs to be
+ // renumbered in the next round
+ vector<int> next_round_dofs;
+
+ // find all neighbors of the
+ // dofs numbered in the last
+ // round
+ for (unsigned int i=0; i<last_round_dofs.size(); ++i)
+ for (int j=sparsity.rowstart[last_round_dofs[i]];
+ j<sparsity.rowstart[last_round_dofs[i]+1]; ++j)
+ if (sparsity.colnums[j] == -1)
+ break;
+ else
+ next_round_dofs.push_back (sparsity.colnums[j]);
+
+ // sort dof numbers
+ sort (next_round_dofs.begin(), next_round_dofs.end());
+
+ // delete multiple entries
+ vector<int>::iterator end_sorted;
+ end_sorted = unique (next_round_dofs.begin(), next_round_dofs.end());
+ next_round_dofs.erase (end_sorted, next_round_dofs.end());
+
+ // eliminate dofs which are
+ // already numbered
+ for (int s=next_round_dofs.size()-1; s>=0; --s)
+ if (new_number[next_round_dofs[s]] != -1)
+ next_round_dofs.erase (&next_round_dofs[s]);
+
+ // check whether there are any new
+ // dofs
+ all_dofs_renumbered = (next_round_dofs.size() == 0);
+ if (all_dofs_renumbered)
+ // end loop if possible
+ continue;
+
+
+ // store for each coordination
+ // number the dofs with these
+ // coordination number
+ multimap<unsigned int, int, less<unsigned int> > dofs_by_coordination;
+
+ // find coordination number for
+ // each of these dofs
+ for (vector<int>::iterator s=next_round_dofs.begin();
+ s!=next_round_dofs.end(); ++s)
+ {
+ unsigned int coordination = 0;
+ for (int j=sparsity.rowstart[*s]; j<sparsity.rowstart[*s+1]; ++j)
+ if (sparsity.colnums[j] == -1)
+ break;
+ else
+ ++coordination;
+
+ // insert this dof at its
+ // coordination number
+ const pair<const unsigned int, int> new_entry (coordination, *s);
+ dofs_by_coordination.insert (new_entry);
+ };
+
+ ////
+ multimap<unsigned int, int, less<unsigned int> >::iterator i;
+ for (i = dofs_by_coordination.begin(); i!=dofs_by_coordination.end(); ++i)
+ new_number[(*i).second] = next_free_number++;
+
+ // after that: copy this round's
+ // dofs for the next round
+ last_round_dofs = next_round_dofs;
+ };
+
+#ifdef DEBUG
+ // test for all indices numbered
+ if (find (new_number.begin(), new_number.end(), -1) != new_number.end())
+ Assert (false, ExcRenumberingIncomplete());
+ Assert (next_free_number == n_dofs,
+ ExcRenumberingIncomplete());
+#endif
+
+ switch (method)
+ {
+ case Cuthill_McKee:
+ break;
+ case reverse_Cuthill_McKee:
+ {
+ for (vector<int>::iterator i=new_number.begin(); i!=new_number.end(); ++i)
+ *i = n_dofs-*i;
+ break;
+ };
+ default:
+ Assert (false, ExcNotImplemented());
+ };
+
+ // actually perform renumbering;
+ // this is dimension specific and
+ // thus needs an own function
+ do_renumbering (new_number);
+};
+
+
+
+void DoFHandler<1>::do_renumbering (const vector<int> &new_numbers) {
+ // note that we can not use cell iterators
+ // in this function since then we would
+ // renumber the dofs on the interface of
+ // two cells more than once. Anyway, this
+ // ways it's not only more correct but also
+ // faster
+ for (vector<int>::iterator i=vertex_dofs.begin(); i!=vertex_dofs.end(); ++i)
+ if (*i != -1)
+ *i = new_numbers[*i];
+
+ for (unsigned int level=0; level<levels.size(); ++level)
+ for (vector<int>::iterator i=levels[level]->line_dofs.begin();
+ i!=levels[level]->line_dofs.end(); ++i)
+ if (*i != -1)
+ *i = new_numbers[*i];
+};
+
+
+
+void DoFHandler<2>::do_renumbering (const vector<int> &new_numbers) {
+ for (vector<int>::iterator i=vertex_dofs.begin(); i!=vertex_dofs.end(); ++i)
+ if (*i != -1)
+ *i = new_numbers[*i];
+
+ for (unsigned int level=0; level<levels.size(); ++level)
+ {
+ for (vector<int>::iterator i=levels[level]->line_dofs.begin();
+ i!=levels[level]->line_dofs.end(); ++i)
+ if (*i != -1)
+ *i = new_numbers[*i];
+ for (vector<int>::iterator i=levels[level]->quad_dofs.begin();
+ i!=levels[level]->quad_dofs.end(); ++i)
+ if (*i != -1)
+ *i = new_numbers[*i];
+ };
+};
+
+
+
+
+void DoFHandler<1>::make_constraint_matrix (ConstraintMatrix &cm) const {
+ cm.clear ();
+};
+
+
+
+
+void DoFHandler<2>::make_constraint_matrix (ConstraintMatrix &constraints) const {
+ constraints.clear ();
+
+ line_iterator line = begin_line(),
+ endl = end_line();
+ // loop over all lines; only on lines
+ // there can be constraints.
+ for (; line != endl; ++line)
+ // if dofs on this line are subject
+ // to constraints
+ if (line->user_flag_set() == true)
+ {
+ // reserve space to gather
+ // the dof numbers. We could
+ // get them when we need them,
+ // but it seems easier to gather
+ // them only once.
+ vector<int> dofs_on_mother;
+ vector<int> dofs_on_children;
+ dofs_on_mother.reserve (2*selected_fe->dofs_per_vertex+
+ selected_fe->dofs_per_line);
+ dofs_on_children.reserve (selected_fe->dofs_per_vertex+
+ 2*selected_fe->dofs_per_line);
+
+ Assert(2*selected_fe->dofs_per_vertex+selected_fe->dofs_per_line ==
+ (unsigned int)selected_fe->constraints().n(),
+ ExcDifferentDimensions(2*selected_fe->dofs_per_vertex+
+ selected_fe->dofs_per_line,
+ selected_fe->constraints().n()));
+ Assert(selected_fe->dofs_per_vertex+2*selected_fe->dofs_per_line ==
+ (unsigned int)selected_fe->constraints().m(),
+ ExcDifferentDimensions(3*selected_fe->dofs_per_vertex+
+ 2*selected_fe->dofs_per_line,
+ selected_fe->constraints().m()));
+
+ // fill the dofs indices. Use same
+ // enumeration scheme as in
+ // #FiniteElement::constraints()#
+ for (unsigned int vertex=0; vertex<2; ++vertex)
+ for (unsigned int dof=0; dof!=selected_fe->dofs_per_vertex; ++dof)
+ dofs_on_mother.push_back (line->vertex_dof_index(vertex,dof));
+ for (unsigned int dof=0; dof!=selected_fe->dofs_per_line; ++dof)
+ dofs_on_mother.push_back (line->dof_index(dof));
+
+ for (unsigned int dof=0; dof!=selected_fe->dofs_per_vertex; ++dof)
+ dofs_on_children.push_back (line->child(0)->vertex_dof_index(1,dof));
+ for (unsigned int child=0; child<2; ++child)
+ for (unsigned int dof=0; dof!=selected_fe->dofs_per_line; ++dof)
+ dofs_on_children.push_back (line->child(child)->dof_index(dof));
+
+ // for each row in the constraint
+ // matrix for this line:
+ for (unsigned int row=0; row!=dofs_on_children.size(); ++row)
+ {
+ constraints.add_line (dofs_on_children[row]);
+ for (unsigned int i=0; i!=dofs_on_mother.size(); ++i)
+ constraints.add_entry (dofs_on_children[row],
+ dofs_on_mother[i],
+ selected_fe->constraints()(row,i));
+ };
+ };
+
+ constraints.close ();
+};
+
+
+
+
+void DoFHandler<1>::make_sparsity_pattern (dSMatrixStruct &sparsity) const {
+ active_cell_iterator cell = begin_active(),
+ endc = end();
+
+ // set up an array which dofs are used
+ // on a specific cell
+ unsigned int *dofs_on_this_cell = new unsigned int[selected_fe->total_dofs];
+
+ for (; cell!=endc; ++cell)
+ {
+ unsigned int dof_number=0;
+
+ // fill dof indices on vertices
+ for (unsigned int vertex=0; vertex<2; ++vertex)
+ for (unsigned int d=0; d<selected_fe->dofs_per_vertex; ++d)
+ dofs_on_this_cell[dof_number++] = cell->vertex_dof_index (vertex,d);
+
+ // fill dof indices on line
+ for (unsigned int d=0; d<selected_fe->dofs_per_line; ++d)
+ dofs_on_this_cell[dof_number++] = cell->dof_index (d);
+
+ // make sparsity pattern for this cell
+ for (unsigned int i=0; i<selected_fe->total_dofs; ++i)
+ for (unsigned int j=0; j<selected_fe->total_dofs; ++j)
+ sparsity.add (dofs_on_this_cell[i],
+ dofs_on_this_cell[j]);
+ };
+
+ delete[] dofs_on_this_cell;
+};
+
+
+
+void DoFHandler<2>::make_sparsity_pattern (dSMatrixStruct &sparsity) const {
+ active_cell_iterator cell = begin_active(),
+ endc = end();
+
+ // set up an array which dofs are used
+ // on a specific cell
+ unsigned int *dofs_on_this_cell = new unsigned int[selected_fe->total_dofs];
+
+
+ for (; cell!=endc; ++cell)
+ {
+ int dof_number=0;
+
+ // fill dof indices on vertices
+ for (unsigned int vertex=0; vertex<4; ++vertex)
+ for (unsigned int d=0; d<selected_fe->dofs_per_vertex; ++d)
+ dofs_on_this_cell[dof_number++] = cell->vertex_dof_index (vertex,d);
+
+ for (unsigned int line=0; line<4; ++line)
+ for (unsigned int d=0; d<selected_fe->dofs_per_line; ++d)
+ dofs_on_this_cell[dof_number++] = cell->line(line)->dof_index (d);
+
+ // fill dof indices on quad
+ for (unsigned int d=0; d<selected_fe->dofs_per_quad; ++d)
+ dofs_on_this_cell[dof_number++] = cell->dof_index (d);
+
+ // make sparsity pattern for this cell
+ for (unsigned int i=0; i<selected_fe->total_dofs; ++i)
+ for (unsigned int j=0; j<selected_fe->total_dofs; ++j)
+ sparsity.add (dofs_on_this_cell[i],
+ dofs_on_this_cell[j]);
+ };
+
+ delete[] dofs_on_this_cell;
+};
+
+
+
+template <int dim>
+void DoFHandler<dim>::make_transfer_matrix (const DoFHandler<dim> &transfer_from,
+ dSMatrixStruct &transfer_pattern) const {
+ Assert (tria->n_cells(0) == transfer_from.tria->n_cells(0),
+ ExcGridsDoNotMatch());
+ Assert (*selected_fe == *transfer_from.selected_fe,
+ ExcGridsDoNotMatch());
+ // assert for once at the beginning the
+ // the matrices have the correct sizes
+#ifdef DEBUG
+ for (unsigned int c=0; c<(1<<dim); ++c)
+ {
+ Assert ((unsigned int)selected_fe->prolongate(c).m() ==
+ selected_fe->total_dofs,
+ ExcMatrixHasWrongSize(selected_fe->prolongate(c).m()));
+ Assert ((unsigned int)selected_fe->prolongate(c).n() ==
+ selected_fe->total_dofs,
+ ExcMatrixHasWrongSize(selected_fe->prolongate(c).n()));
+ Assert ((unsigned int)selected_fe->restrict(c).m() ==
+ selected_fe->total_dofs,
+ ExcMatrixHasWrongSize(selected_fe->restrict(c).m()));
+ Assert ((unsigned int)selected_fe->restrict(c).n() ==
+ selected_fe->total_dofs,
+ ExcMatrixHasWrongSize(selected_fe->restrict(c).n()));
+ };
+#endif
+
+ cell_iterator old_cell = transfer_from.begin(0),
+ new_cell = begin(0);
+ unsigned int n_coarse_cells = tria->n_cells(0);
+
+ // first run: make up sparsity structure
+ for (unsigned int j=0; j<n_coarse_cells; ++j, ++old_cell, ++new_cell)
+ transfer_cell (old_cell, new_cell, transfer_pattern);
+
+ transfer_pattern.compress();
+};
+
+
+
+template <int dim>
+void DoFHandler<dim>::make_transfer_matrix (const DoFHandler<dim> &transfer_from,
+ dSMatrix &transfer_matrix) const {
+ cell_iterator old_cell = transfer_from.begin(0),
+ new_cell = begin(0);
+ unsigned int n_coarse_cells = tria->n_cells(0);
+
+ // second run: make up matrix entries
+ for (unsigned int j=0; j<n_coarse_cells; ++j, ++old_cell, ++new_cell)
+ transfer_cell (old_cell, new_cell, transfer_matrix);
+};
+
+
+
+template <int dim>
+void DoFHandler<dim>::transfer_cell (const TriaIterator<dim,DoFCellAccessor<dim> > &old_cell,
+ const TriaIterator<dim,DoFCellAccessor<dim> > &new_cell,
+ dSMatrixStruct &transfer_pattern) const {
+ if (!new_cell->active() && !old_cell->active())
+ // both cells have children; go deeper
+ for (unsigned int child=0; child<(1<<dim); ++child)
+ transfer_cell (old_cell->child(child), new_cell->child(child),
+ transfer_pattern);
+ else
+ if (new_cell->active() && old_cell->active())
+ // both cells have no children
+ {
+ vector<int> old_dofs, new_dofs;
+ old_cell->dof_indices (old_dofs);
+ new_cell->dof_indices (new_dofs);
+ Assert (old_dofs.size() == selected_fe->total_dofs,
+ ExcInternalError ());
+ Assert (new_dofs.size() == selected_fe->total_dofs,
+ ExcInternalError ());
+
+ // copy dofs one-by-one
+ for (unsigned int j=0; j<old_dofs.size(); ++j)
+ transfer_pattern.add (new_dofs[j], old_dofs[j]);
+ }
+ else
+ if (!new_cell->active() && old_cell->active())
+ // new cell has children, old one has not
+ {
+ cell_iterator child[1<<dim];
+ for (unsigned int c=0; c<(1<<dim); ++c)
+ {
+ child[c] = new_cell->child(c);
+ Assert (child[c]->active(),
+ ExcOnlyOnelevelTransferImplemented());
+ };
+
+ // numbers of old dofs
+ vector<int> old_dof_indices;
+ old_cell->dof_indices (old_dof_indices);
+
+ Assert (old_dof_indices.size() == selected_fe->total_dofs,
+ ExcInternalError ());
+
+ for (unsigned int c=0; c<(1<<dim); ++c)
+ {
+ // numbers of child dofs
+ vector<int> child_dof_indices;
+ child[c]->dof_indices (child_dof_indices);
+
+ Assert (child_dof_indices.size() == selected_fe->total_dofs,
+ ExcInternalError ());
+
+ for (unsigned int k=0; k<selected_fe->total_dofs; ++k)
+ for (unsigned int j=0; j<selected_fe->total_dofs; ++j)
+ if (selected_fe->prolongate(c)(k,j) != 0.)
+ transfer_pattern.add (child_dof_indices[k],
+ old_dof_indices[j]);
+ };
+ } else {
+ // old cell has children, new one has not
+ cell_iterator child[1<<dim];
+ for (unsigned int c=0; c<(1<<dim); ++c)
+ {
+ child[c] = old_cell->child(c);
+ Assert (child[c]->active(),
+ ExcOnlyOnelevelTransferImplemented());
+ };
+
+ // numbers of new dofs
+ vector<int> new_dof_indices;
+ new_cell->dof_indices(new_dof_indices);
+
+ Assert (new_dof_indices.size() == selected_fe->total_dofs,
+ ExcInternalError ());
+
+ for (unsigned int c=0; c<(1<<dim); ++c)
+ {
+ // numbers of child dofs
+ vector<int> child_dof_indices;
+ child[c]->dof_indices (child_dof_indices);
+
+ Assert (child_dof_indices.size() == selected_fe->total_dofs,
+ ExcInternalError ());
+
+ for (unsigned int k=0; k<selected_fe->total_dofs; ++k)
+ for (unsigned int j=0; j<selected_fe->total_dofs; ++j)
+ if (selected_fe->restrict(c)(k,j) != 0.)
+ transfer_pattern.add (new_dof_indices[k],
+ child_dof_indices[j]);
+ };
+ };
+};
+
+
+
+template <int dim>
+void DoFHandler<dim>::transfer_cell (const TriaIterator<dim,DoFCellAccessor<dim> > &old_cell,
+ const TriaIterator<dim,DoFCellAccessor<dim> > &new_cell,
+ dSMatrix &transfer_matrix) const {
+ if (!new_cell->active() && !old_cell->active())
+ // both cells have children; go deeper
+ for (unsigned int child=0; child<(1<<dim); ++child)
+ transfer_cell (old_cell->child(child), new_cell->child(child),
+ transfer_matrix);
+ else
+ if (new_cell->active() && old_cell->active())
+ // both cells have no children
+ {
+ vector<int> old_dofs, new_dofs;
+ old_cell->dof_indices (old_dofs);
+ new_cell->dof_indices (new_dofs);
+ Assert (old_dofs.size() == selected_fe->total_dofs,
+ ExcInternalError ());
+ Assert (new_dofs.size() == selected_fe->total_dofs,
+ ExcInternalError ());
+
+ // copy dofs one-by-one
+ for (unsigned int j=0; j<old_dofs.size(); ++j)
+ transfer_matrix.set (new_dofs[j], old_dofs[j], 1.0);
+ }
+ else
+ if (!new_cell->active() && old_cell->active())
+ // new cell has children, old one has not
+ {
+ cell_iterator child[1<<dim];
+ for (unsigned int c=0; c<(1<<dim); ++c)
+ {
+ child[c] = new_cell->child(c);
+ Assert (child[c]->active(),
+ ExcOnlyOnelevelTransferImplemented());
+ };
+
+ // numbers of old dofs
+ vector<int> old_dof_indices;
+ old_cell->dof_indices (old_dof_indices);
+
+ Assert (old_dof_indices.size() == selected_fe->total_dofs,
+ ExcInternalError ());
+
+ for (unsigned int c=0; c<(1<<dim); ++c)
+ {
+ // numbers of child dofs
+ vector<int> child_dof_indices;
+ child[c]->dof_indices (child_dof_indices);
+
+ Assert (child_dof_indices.size() == selected_fe->total_dofs,
+ ExcInternalError ());
+
+ for (unsigned int k=0; k<selected_fe->total_dofs; ++k)
+ for (unsigned int j=0; j<selected_fe->total_dofs; ++j)
+ if (selected_fe->prolongate(c)(k,j) != 0.)
+ transfer_matrix.set (child_dof_indices[k],
+ old_dof_indices[j],
+ selected_fe->prolongate(c)(k,j));
+ };
+ } else {
+ // old cell has children, new one has not
+ cell_iterator child[1<<dim];
+ for (unsigned int c=0; c<(1<<dim); ++c)
+ {
+ child[c] = old_cell->child(c);
+ Assert (child[c]->active(),
+ ExcOnlyOnelevelTransferImplemented());
+ };
+
+ // numbers of new dofs
+ vector<int> new_dof_indices;
+ new_cell->dof_indices(new_dof_indices);
+
+ Assert (new_dof_indices.size() == selected_fe->total_dofs,
+ ExcInternalError ());
+
+ for (unsigned int c=0; c<(1<<dim); ++c)
+ {
+ // numbers of child dofs
+ vector<int> child_dof_indices;
+ child[c]->dof_indices (child_dof_indices);
+
+ Assert (child_dof_indices.size() == selected_fe->total_dofs,
+ ExcInternalError ());
+
+ for (unsigned int k=0; k<selected_fe->total_dofs; ++k)
+ for (unsigned int j=0; j<selected_fe->total_dofs; ++j)
+ if (selected_fe->restrict(c)(k,j) != 0.)
+ transfer_matrix.set (new_dof_indices[k],
+ child_dof_indices[j],
+ selected_fe->restrict(c)(k,j));
+ };
+ };
+};
+
+
+
+
+unsigned int DoFHandler<1>::max_couplings_between_dofs () const {
+ Assert (selected_fe != 0, ExcNoFESelected());
+ return 3*selected_fe->dofs_per_vertex + 2*selected_fe->dofs_per_line;
+};
+
+
+
+unsigned int DoFHandler<2>::max_couplings_between_dofs () const {
+ Assert (selected_fe != 0, ExcNoFESelected());
+ unsigned int max_adjacent_cells = tria->max_adjacent_cells();
+
+ // get these numbers by drawing pictures
+ // and counting...
+ if (max_adjacent_cells == 4)
+ return (13*selected_fe->dofs_per_vertex +
+ 20*selected_fe->dofs_per_line +
+ 8*selected_fe->dofs_per_quad);
+ else
+ if (max_adjacent_cells == 5)
+ return (15*selected_fe->dofs_per_vertex +
+ 23*selected_fe->dofs_per_line +
+ 9*selected_fe->dofs_per_quad);
+ else
+ if (max_adjacent_cells == 6)
+ // are you really sure you
+ // want to use such grids??
+ return (19*selected_fe->dofs_per_vertex +
+ 30*selected_fe->dofs_per_line +
+ 16*selected_fe->dofs_per_quad);
+ else
+ {
+ Assert (false, ExcNotImplemented());
+ return 0;
+ };
+};
+
+
+
+unsigned int DoFHandler<1>::max_transfer_entries (const unsigned int max_level_diff) const {
+ Assert (max_level_diff<2, ExcOnlyOnelevelTransferImplemented());
+ switch (max_level_diff)
+ {
+ case 0:
+ return 1;
+ case 1:
+ return (2*selected_fe->dofs_per_line+
+ selected_fe->dofs_per_vertex) * 2 + 1;
+ };
+ return 0;
+};
+
+
+
+unsigned int DoFHandler<2>::max_transfer_entries (const unsigned int max_level_diff) const {
+ Assert (max_level_diff<2, ExcOnlyOnelevelTransferImplemented());
+ switch (max_level_diff)
+ {
+ case 0:
+ return 1;
+ case 1:
+ return (4*selected_fe->dofs_per_quad +
+ 12*selected_fe->dofs_per_line+
+ 5*selected_fe->dofs_per_vertex) * 4 +1;
+ };
+ return 0;
+};
+
+
+
+void DoFHandler<1>::reserve_space (const FiniteElement<1> &fe) {
+ Assert (tria->n_levels() > 0, ExcInvalidTriangulation());
+ // delete all levels and set them up
+ // newly, since vectors are
+ // troublesome if you want to change
+ // their size
+ for (unsigned int i=0; i<levels.size(); ++i)
+ delete levels[i];
+ levels.erase (levels.begin(), levels.end());
+
+ vertex_dofs.erase (vertex_dofs.begin(), vertex_dofs.end());
+ vertex_dofs.reserve (tria->vertices.size());
+ vertex_dofs.insert (vertex_dofs.end(),
+ tria->vertices.size(),
+ -1);
+
+ for (unsigned int i=0; i<tria->n_levels(); ++i)
+ {
+ levels.push_back (new DoFLevel<1>);
+
+ levels.back()->line_dofs.reserve (tria->levels[i]->lines.lines.size() *
+ fe.dofs_per_line);
+ levels.back()->line_dofs.insert (levels.back()->line_dofs.end(),
+ (tria->levels[i]->lines.lines.size() *
+ fe.dofs_per_line),
+ -1);
+ };
+};
+
+
+
+void DoFHandler<2>::reserve_space (const FiniteElement<2> &fe) {
+ Assert (tria->n_levels() > 0, ExcInvalidTriangulation());
+
+ // delete all levels and set them up
+ // newly, since vectors are
+ // troublesome if you want to change
+ // their size
+ for (unsigned int i=0; i<levels.size(); ++i)
+ delete levels[i];
+ levels.erase (levels.begin(), levels.end());
+
+ vertex_dofs.erase (vertex_dofs.begin(), vertex_dofs.end());
+ vertex_dofs.reserve (tria->vertices.size());
+ vertex_dofs.insert (vertex_dofs.end(),
+ tria->vertices.size(),
+ -1);
+
+ for (unsigned int i=0; i<tria->n_levels(); ++i)
+ {
+ levels.push_back (new DoFLevel<2>);
+
+ levels.back()->line_dofs.reserve (tria->levels[i]->lines.lines.size() *
+ fe.dofs_per_line);
+ levels.back()->line_dofs.insert (levels.back()->line_dofs.end(),
+ (tria->levels[i]->lines.lines.size() *
+ fe.dofs_per_line),
+ -1);
+
+ levels.back()->quad_dofs.reserve (tria->levels[i]->quads.quads.size() *
+ fe.dofs_per_quad);
+ levels.back()->quad_dofs.insert (levels.back()->quad_dofs.end(),
+ (tria->levels[i]->quads.quads.size() *
+ fe.dofs_per_quad),
+ -1);
+ };
+};
+
+
+
+
+
+/*-------------- Explicit Instantiations -------------------------------*/
+template class DoFHandler<1>;
+template class DoFHandler<2>;
+
+
+
--- /dev/null
+# $Id$
+
+CXX =c++
+CXXFLAGS.g=-DDEBUG -g -Wall -pedantic -Wconversion -Winline -Woverloaded-virtual -I../../include
+CXXFLAGS =-O3 -Wuninitialized -finline-functions -ffast-math -funroll-loops -felide-constructors -fnonnull-objects -I../../include
+
+ifeq ($(shell uname),SunOS)
+CXXFLAGS := -V2.7.2.3 $(CXXFLAGS)
+CXXFLAGS.g:= -V2.7.2.3 $(CXXFLAGS.g)
+endif
+
+
+cc-files = $(wildcard *.cc)
+o-files = $(cc-files:.cc=.o)
+go-files = $(cc-files:.cc=.go)
+h-files = $(wildcard ../include/*/*.h)
+
+
+%.go : %.cc
+ @echo ============================ Compiling with debugging information: $<
+ @echo $(CXX) ... -c $< -o $@
+ @$(CXX) $(CXXFLAGS.g) -c $< -o $@
+%.o : %.cc
+ @echo ============================ Compiling with optimization: $<
+ @echo $(CXX) ... -c $< -o $@
+ @$(CXX) $(CXXFLAGS) -c $< -o $@
+
+
+lib: lib.g.a lib.a
+
+lib.a: ../../lib/libbasic.a($(o-files))
+
+lib.g.a: ../../lib/libbasic.g.a($(go-files))
+
+clean:
+ rm -f *.o *.go *~ Makefile.dep
+
+
+
+.PHONY: lib lib.a lib.g.a clean
+
+
+#Rule to generate the dependency file. This file is
+#automagically remade whenever needed, i.e. whenever
+#one of the cc-/h-files changed. Make detects whether
+#to remake this file upon inclusion at the bottom
+#of this file.
+#
+#use perl to generate rules for the .go files as well
+#as to make rules not for tria.o and the like, but
+#rather for libbasic.a(tria.o)
+Makefile.dep: $(cc-files) $(h-files)
+ @echo ============================ Remaking Makefile
+ @$(CXX) -I../../include -DDEBUG -M *.cc > Makefile.dep.o
+ @cp Makefile.dep.o Makefile.dep.go
+ @perl -pi -e 's!^(.*\.o):!../../lib/libbasic.a(\1):!g' Makefile.dep.o
+ @perl -pi -e 's!\.o:!.go:!g' Makefile.dep.go
+ @perl -pi -e 's!^(.*\.go):!../../lib/libbasic.g.a(\1):!g' Makefile.dep.go
+ @cat Makefile.dep.o Makefile.dep.go > Makefile.dep
+ @rm Makefile.dep.o Makefile.dep.go
+
+include Makefile.dep
--- /dev/null
+../../lib/libbasic.a(fe.o): fe.cc ../../include/fe/fe.h ../../include/../deal/dfmatrix.h \
+ /usr/include/stdio.h /usr/include/sys/feature_tests.h \
+ /usr/include/sys/va_list.h ../../include/../deal/dvector.h \
+ ../../include/../deal/types.h /usr/include/stdlib.h \
+ ../../include/../deal/errors.h ../../include/../deal/vectorbase.h \
+ ../../include/../deal/ivector.h ../../include/grid/point.h \
+ ../../include/basic/exceptions.h /usr/local/include/g++/iostream.h \
+ /usr/local/include/g++/streambuf.h /usr/local/include/g++/libio.h \
+ /usr/local/lib/g++-include/_G_config.h ../../include/grid/tria.h \
+ /usr/local/include/g++/vector.h /usr/local/include/g++/algobase.h \
+ /usr/local/include/g++/pair.h /usr/local/include/g++/stl_config.h \
+ /usr/local/include/g++/stl_relops.h /usr/local/include/g++/stl_pair.h \
+ /usr/local/include/g++/iterator.h /usr/local/include/g++/function.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/stddef.h \
+ /usr/local/include/g++/stl_function.h \
+ /usr/local/include/g++/stl_iterator.h \
+ /usr/local/include/g++/type_traits.h \
+ /usr/local/include/g++/stl_construct.h \
+ /usr/local/lib/g++-include/new.h /usr/local/lib/g++-include/std/new.h \
+ /usr/local/lib/g++-include/std/cstddef.h \
+ /usr/local/include/g++/stl_raw_storage_iter.h \
+ /usr/local/include/g++/stl_algobase.h /usr/include/string.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/limits.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/syslimits.h \
+ /usr/include/limits.h /usr/include/sys/isa_defs.h \
+ /usr/local/include/g++/stl_uninitialized.h \
+ /usr/local/include/g++/alloc.h /usr/local/include/g++/stl_alloc.h \
+ /usr/local/sparc-sun-solaris2.5.1/include/assert.h \
+ /usr/local/include/g++/stl_vector.h ../../include/grid/tria_line.h \
+ ../../include/grid/tria_quad.h ../../include/grid/tria_boundary.h \
+ ../../include/fe/quadrature.h
+../../lib/libbasic.a(fe_lib.o): fe_lib.cc ../../include/fe/fe_lib.h ../../include/fe/fe.h \
+ ../../include/../deal/dfmatrix.h /usr/include/stdio.h \
+ /usr/include/sys/feature_tests.h /usr/include/sys/va_list.h \
+ ../../include/../deal/dvector.h ../../include/../deal/types.h \
+ /usr/include/stdlib.h ../../include/../deal/errors.h \
+ ../../include/../deal/vectorbase.h ../../include/../deal/ivector.h \
+ ../../include/grid/point.h ../../include/basic/exceptions.h \
+ /usr/local/include/g++/iostream.h /usr/local/include/g++/streambuf.h \
+ /usr/local/include/g++/libio.h /usr/local/lib/g++-include/_G_config.h \
+ ../../include/grid/tria.h /usr/local/include/g++/vector.h \
+ /usr/local/include/g++/algobase.h /usr/local/include/g++/pair.h \
+ /usr/local/include/g++/stl_config.h \
+ /usr/local/include/g++/stl_relops.h /usr/local/include/g++/stl_pair.h \
+ /usr/local/include/g++/iterator.h /usr/local/include/g++/function.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/stddef.h \
+ /usr/local/include/g++/stl_function.h \
+ /usr/local/include/g++/stl_iterator.h \
+ /usr/local/include/g++/type_traits.h \
+ /usr/local/include/g++/stl_construct.h \
+ /usr/local/lib/g++-include/new.h /usr/local/lib/g++-include/std/new.h \
+ /usr/local/lib/g++-include/std/cstddef.h \
+ /usr/local/include/g++/stl_raw_storage_iter.h \
+ /usr/local/include/g++/stl_algobase.h /usr/include/string.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/limits.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/syslimits.h \
+ /usr/include/limits.h /usr/include/sys/isa_defs.h \
+ /usr/local/include/g++/stl_uninitialized.h \
+ /usr/local/include/g++/alloc.h /usr/local/include/g++/stl_alloc.h \
+ /usr/local/sparc-sun-solaris2.5.1/include/assert.h \
+ /usr/local/include/g++/stl_vector.h ../../include/grid/tria_line.h \
+ ../../include/grid/tria_quad.h ../../include/grid/tria_boundary.h
+../../lib/libbasic.a(quadrature_lib.o): quadrature_lib.cc ../../include/fe/quadrature_lib.h \
+ ../../include/fe/quadrature.h ../../include/grid/point.h \
+ ../../include/basic/exceptions.h /usr/local/include/g++/iostream.h \
+ /usr/local/include/g++/streambuf.h /usr/local/include/g++/libio.h \
+ /usr/local/lib/g++-include/_G_config.h \
+ /usr/local/include/g++/vector.h /usr/local/include/g++/algobase.h \
+ /usr/local/include/g++/pair.h /usr/local/include/g++/stl_config.h \
+ /usr/local/include/g++/stl_relops.h /usr/local/include/g++/stl_pair.h \
+ /usr/local/include/g++/iterator.h /usr/local/include/g++/function.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/stddef.h \
+ /usr/local/include/g++/stl_function.h \
+ /usr/local/include/g++/stl_iterator.h \
+ /usr/local/include/g++/type_traits.h \
+ /usr/local/include/g++/stl_construct.h \
+ /usr/local/lib/g++-include/new.h /usr/local/lib/g++-include/std/new.h \
+ /usr/local/lib/g++-include/std/cstddef.h \
+ /usr/local/include/g++/stl_raw_storage_iter.h \
+ /usr/local/include/g++/stl_algobase.h /usr/include/string.h \
+ /usr/include/sys/feature_tests.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/limits.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/syslimits.h \
+ /usr/include/limits.h /usr/include/sys/isa_defs.h \
+ /usr/include/stdlib.h /usr/local/include/g++/stl_uninitialized.h \
+ /usr/local/include/g++/alloc.h /usr/local/include/g++/stl_alloc.h \
+ /usr/local/sparc-sun-solaris2.5.1/include/assert.h \
+ /usr/local/include/g++/stl_vector.h
+../../lib/libbasic.g.a(fe.go): fe.cc ../../include/fe/fe.h ../../include/../deal/dfmatrix.h \
+ /usr/include/stdio.h /usr/include/sys/feature_tests.h \
+ /usr/include/sys/va_list.h ../../include/../deal/dvector.h \
+ ../../include/../deal/types.h /usr/include/stdlib.h \
+ ../../include/../deal/errors.h ../../include/../deal/vectorbase.h \
+ ../../include/../deal/ivector.h ../../include/grid/point.h \
+ ../../include/basic/exceptions.h /usr/local/include/g++/iostream.h \
+ /usr/local/include/g++/streambuf.h /usr/local/include/g++/libio.h \
+ /usr/local/lib/g++-include/_G_config.h ../../include/grid/tria.h \
+ /usr/local/include/g++/vector.h /usr/local/include/g++/algobase.h \
+ /usr/local/include/g++/pair.h /usr/local/include/g++/stl_config.h \
+ /usr/local/include/g++/stl_relops.h /usr/local/include/g++/stl_pair.h \
+ /usr/local/include/g++/iterator.h /usr/local/include/g++/function.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/stddef.h \
+ /usr/local/include/g++/stl_function.h \
+ /usr/local/include/g++/stl_iterator.h \
+ /usr/local/include/g++/type_traits.h \
+ /usr/local/include/g++/stl_construct.h \
+ /usr/local/lib/g++-include/new.h /usr/local/lib/g++-include/std/new.h \
+ /usr/local/lib/g++-include/std/cstddef.h \
+ /usr/local/include/g++/stl_raw_storage_iter.h \
+ /usr/local/include/g++/stl_algobase.h /usr/include/string.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/limits.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/syslimits.h \
+ /usr/include/limits.h /usr/include/sys/isa_defs.h \
+ /usr/local/include/g++/stl_uninitialized.h \
+ /usr/local/include/g++/alloc.h /usr/local/include/g++/stl_alloc.h \
+ /usr/local/sparc-sun-solaris2.5.1/include/assert.h \
+ /usr/local/include/g++/stl_vector.h ../../include/grid/tria_line.h \
+ ../../include/grid/tria_quad.h ../../include/grid/tria_boundary.h \
+ ../../include/fe/quadrature.h
+../../lib/libbasic.g.a(fe_lib.go): fe_lib.cc ../../include/fe/fe_lib.h ../../include/fe/fe.h \
+ ../../include/../deal/dfmatrix.h /usr/include/stdio.h \
+ /usr/include/sys/feature_tests.h /usr/include/sys/va_list.h \
+ ../../include/../deal/dvector.h ../../include/../deal/types.h \
+ /usr/include/stdlib.h ../../include/../deal/errors.h \
+ ../../include/../deal/vectorbase.h ../../include/../deal/ivector.h \
+ ../../include/grid/point.h ../../include/basic/exceptions.h \
+ /usr/local/include/g++/iostream.h /usr/local/include/g++/streambuf.h \
+ /usr/local/include/g++/libio.h /usr/local/lib/g++-include/_G_config.h \
+ ../../include/grid/tria.h /usr/local/include/g++/vector.h \
+ /usr/local/include/g++/algobase.h /usr/local/include/g++/pair.h \
+ /usr/local/include/g++/stl_config.h \
+ /usr/local/include/g++/stl_relops.h /usr/local/include/g++/stl_pair.h \
+ /usr/local/include/g++/iterator.h /usr/local/include/g++/function.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/stddef.h \
+ /usr/local/include/g++/stl_function.h \
+ /usr/local/include/g++/stl_iterator.h \
+ /usr/local/include/g++/type_traits.h \
+ /usr/local/include/g++/stl_construct.h \
+ /usr/local/lib/g++-include/new.h /usr/local/lib/g++-include/std/new.h \
+ /usr/local/lib/g++-include/std/cstddef.h \
+ /usr/local/include/g++/stl_raw_storage_iter.h \
+ /usr/local/include/g++/stl_algobase.h /usr/include/string.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/limits.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/syslimits.h \
+ /usr/include/limits.h /usr/include/sys/isa_defs.h \
+ /usr/local/include/g++/stl_uninitialized.h \
+ /usr/local/include/g++/alloc.h /usr/local/include/g++/stl_alloc.h \
+ /usr/local/sparc-sun-solaris2.5.1/include/assert.h \
+ /usr/local/include/g++/stl_vector.h ../../include/grid/tria_line.h \
+ ../../include/grid/tria_quad.h ../../include/grid/tria_boundary.h
+../../lib/libbasic.g.a(quadrature_lib.go): quadrature_lib.cc ../../include/fe/quadrature_lib.h \
+ ../../include/fe/quadrature.h ../../include/grid/point.h \
+ ../../include/basic/exceptions.h /usr/local/include/g++/iostream.h \
+ /usr/local/include/g++/streambuf.h /usr/local/include/g++/libio.h \
+ /usr/local/lib/g++-include/_G_config.h \
+ /usr/local/include/g++/vector.h /usr/local/include/g++/algobase.h \
+ /usr/local/include/g++/pair.h /usr/local/include/g++/stl_config.h \
+ /usr/local/include/g++/stl_relops.h /usr/local/include/g++/stl_pair.h \
+ /usr/local/include/g++/iterator.h /usr/local/include/g++/function.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/stddef.h \
+ /usr/local/include/g++/stl_function.h \
+ /usr/local/include/g++/stl_iterator.h \
+ /usr/local/include/g++/type_traits.h \
+ /usr/local/include/g++/stl_construct.h \
+ /usr/local/lib/g++-include/new.h /usr/local/lib/g++-include/std/new.h \
+ /usr/local/lib/g++-include/std/cstddef.h \
+ /usr/local/include/g++/stl_raw_storage_iter.h \
+ /usr/local/include/g++/stl_algobase.h /usr/include/string.h \
+ /usr/include/sys/feature_tests.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/limits.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/syslimits.h \
+ /usr/include/limits.h /usr/include/sys/isa_defs.h \
+ /usr/include/stdlib.h /usr/local/include/g++/stl_uninitialized.h \
+ /usr/local/include/g++/alloc.h /usr/local/include/g++/stl_alloc.h \
+ /usr/local/sparc-sun-solaris2.5.1/include/assert.h \
+ /usr/local/include/g++/stl_vector.h
--- /dev/null
+/* $Id$ */
+
+#include <fe/fe.h>
+#include <fe/quadrature.h>
+
+
+
+/*------------------------------- FEValues -------------------------------*/
+
+
+template <int dim>
+FEValues<dim>::FEValues (const FiniteElement<dim> &fe,
+ const Quadrature<dim> &quadrature) :
+ shape_values(fe.total_dofs, quadrature.n_quad_points),
+ shape_gradients(fe.total_dofs,
+ vector<Point<dim> >(quadrature.n_quad_points)),
+ unit_shape_gradients(fe.total_dofs,
+ vector<Point<dim> >(quadrature.n_quad_points)),
+ weights(quadrature.n_quad_points, 0),
+ JxW_values(quadrature.n_quad_points, 0),
+ quadrature_points(quadrature.n_quad_points, Point<dim>()),
+ unit_quadrature_points(quadrature.n_quad_points, Point<dim>()),
+ jacobi_matrices (quadrature.n_quad_points)
+{
+ for (unsigned int i=0; i<fe.total_dofs; ++i)
+ for (unsigned int j=0; j<quadrature.n_quad_points; ++j)
+ {
+ shape_values(i,j) = fe.shape_value(i, quadrature.quad_point(j));
+ unit_shape_gradients[i][j]
+ = fe.shape_grad(i, quadrature.quad_point(j));
+ };
+
+ for (unsigned int i=0; i<weights.size(); ++i)
+ {
+ weights[i] = quadrature.weight(i);
+ unit_quadrature_points[i] = quadrature.quad_point(i);
+ };
+};
+
+
+
+template <int dim>
+double FEValues<dim>::shape_value (const unsigned int i,
+ const unsigned int j) const {
+ Assert (i<(unsigned int)shape_values.m(), ExcInvalidIndex (i, shape_values.m()));
+ Assert (j<(unsigned int)shape_values.n(), ExcInvalidIndex (j, shape_values.n()));
+
+ return shape_values(i,j);
+};
+
+
+
+template <int dim>
+const Point<dim> &
+FEValues<dim>::shape_grad (const unsigned int i,
+ const unsigned int j) const {
+ Assert (i<(unsigned int)shape_values.m(), ExcInvalidIndex (i, shape_values.m()));
+ Assert (j<(unsigned int)shape_values.n(), ExcInvalidIndex (j, shape_values.n()));
+
+ return shape_gradients[i][j];
+};
+
+
+
+void FEValues<1>::reinit (const Triangulation<1>::cell_iterator &cell,
+ const FiniteElement<1> &fe) {
+ const unsigned int dim=1;
+ // fill jacobi matrices and real
+ //quadrature points
+ fe.fill_fe_values (cell,
+ unit_quadrature_points,
+ jacobi_matrices,
+ quadrature_points);
+ // compute gradients on real element
+ for (unsigned int i=0; i<fe.total_dofs; ++i)
+ for (unsigned int j=0; j<quadrature_points.size(); ++j)
+ for (unsigned int s=0; s<dim; ++s)
+ {
+ shape_gradients[i][j](s) = 0;
+
+ // (grad psi)_s =
+ // (grad_{\xi\eta})_b J_{bs}
+ // with J_{bs}=(d\xi_b)/(dx_s)
+ for (unsigned int b=0; b<dim; ++b)
+ shape_gradients[i][j](s)
+ +=
+ unit_shape_gradients[i][j](b) * jacobi_matrices[j](b,s);
+ };
+
+ // compute Jacobi determinants in
+ // quadrature points.
+ for (unsigned int i=0; i<quadrature_points.size(); ++i)
+ JxW_values[i] = jacobi_matrices[i].determinant() * weights[i];
+};
+
+
+
+void FEValues<2>::reinit (const Triangulation<2>::cell_iterator &cell,
+ const FiniteElement<2> &fe) {
+ const unsigned int dim=2;
+ // fill jacobi matrices and real
+ //quadrature points
+ fe.fill_fe_values (cell,
+ unit_quadrature_points,
+ jacobi_matrices,
+ quadrature_points);
+ // compute gradients on real element
+ for (unsigned int i=0; i<fe.total_dofs; ++i)
+ for (unsigned int j=0; j<quadrature_points.size(); ++j)
+ for (unsigned int s=0; s<dim; ++s)
+ {
+ shape_gradients[i][j](s) = 0;
+
+ // (grad psi)_s =
+ // (grad_{\xi\eta})_b J_{bs}
+ // with J_{bs}=(d\xi_b)/(dx_s)
+ for (unsigned int b=0; b<dim; ++b)
+ shape_gradients[i][j](s)
+ +=
+ unit_shape_gradients[i][j](b) * jacobi_matrices[j](b,s);
+ };
+
+ // compute Jacobi determinants in
+ // quadrature points.
+ for (unsigned int i=0; i<quadrature_points.size(); ++i)
+ JxW_values[i] = jacobi_matrices[i].determinant() * weights[i];
+};
+
+
+
+
+/*------------------------------- FiniteElementBase ----------------------*/
+
+template <int dim>
+FiniteElementBase<dim>::FiniteElementBase (const FiniteElementBase<dim> &f) :
+ total_dofs(f.total_dofs),
+ interface_constraints (f.interface_constraints)
+{
+ for (unsigned int i=0; i<(1<<dim); ++i)
+ {
+ restriction[i] = f.restriction[i];
+ prolongation[i] = f.prolongation[i];
+ };
+}
+
+
+
+template <int dim>
+const dFMatrix &
+FiniteElementBase<dim>::restrict (const unsigned int child) const {
+ Assert (child<(1<<dim), ExcInvalidIndex(child));
+ return restriction[child];
+};
+
+
+
+template <int dim>
+const dFMatrix &
+FiniteElementBase<dim>::prolongate (const unsigned int child) const {
+ Assert (child<(1<<dim), ExcInvalidIndex(child));
+ return prolongation[child];
+};
+
+
+
+template <int dim>
+const dFMatrix &
+FiniteElementBase<dim>::constraints () const {
+ return interface_constraints;
+};
+
+
+
+template <int dim>
+bool FiniteElementBase<dim>::operator == (const FiniteElementBase<dim> &f) const {
+ return ((total_dofs == f.total_dofs) &&
+ (interface_constraints == f.interface_constraints));
+};
+
+
+
+template <int dim>
+double FiniteElementBase<dim>::shape_value (const unsigned int,
+ const Point<dim> &) const {
+ Assert (false, ExcPureFunctionCalled());
+ return 0;
+};
+
+
+
+template <int dim>
+Point<dim> FiniteElementBase<dim>::shape_grad (const unsigned int,
+ const Point<dim> &) const {
+ Assert (false, ExcPureFunctionCalled());
+ return Point<dim>();
+};
+
+
+
+void FiniteElementBase<1>::fill_fe_values (const Triangulation<1>::cell_iterator &,
+ const vector<Point<1> > &,
+ vector<dFMatrix> &,
+ vector<Point<1> > &) const {
+ Assert (false, ExcPureFunctionCalled());
+};
+
+
+
+void FiniteElementBase<2>::fill_fe_values (const Triangulation<2>::cell_iterator &,
+ const vector<Point<2> > &,
+ vector<dFMatrix> &,
+ vector<Point<2> > &) const {
+ Assert (false, ExcPureFunctionCalled());
+};
+
+
+
+/*------------------------------- FiniteElement ----------------------*/
+
+
+bool FiniteElement<1>::operator == (const FiniteElement<1> &f) const {
+ return ((dofs_per_vertex == f.dofs_per_vertex) &&
+ (dofs_per_line == f.dofs_per_line) &&
+ (FiniteElementBase<1>::operator == (f)));
+};
+
+
+
+bool FiniteElement<2>::operator == (const FiniteElement<2> &f) const {
+ return ((dofs_per_vertex == f.dofs_per_vertex) &&
+ (dofs_per_line == f.dofs_per_line) &&
+ (dofs_per_quad == f.dofs_per_quad) &&
+ (FiniteElementBase<2>::operator == (f)));
+};
+
+
+
+
+
+/*------------------------------- Explicit Instantiations -------------*/
+
+template class FEValues<1>;
+template class FEValues<2>;
+
+template class FiniteElementBase<1>;
+template class FiniteElementBase<2>;
+
+template class FiniteElement<1>;
+template class FiniteElement<2>;
--- /dev/null
+/* $Id$ */
+
+#include <fe/fe_lib.h>
+
+
+
+FELinear<1>::FELinear () :
+ FiniteElement<1> (1, 0)
+{
+ restriction[0].reinit (2,2);
+ restriction[1].reinit (2,2);
+
+ // for restriction and prolongation matrices:
+ // note that we do not add up all the
+ // contributions since then we would get
+ // two summands per vertex in 1d (four
+ // in 2d, etc), but only one per line dof.
+ // We could accomplish for that by dividing
+ // the vertex dof values by 2 (4, etc), but
+ // would get into trouble at the boundary
+ // of the domain since there only one
+ // cell contributes to a vertex. Rather,
+ // we do not add up the contributions but
+ // set them right into the matrices!
+ restriction[0](0,0) = 1.0;
+ restriction[0](0,1) = 1./2.;
+ restriction[0](1,1) = 1./2.;
+
+ restriction[1](0,0) = 1./2.;
+ restriction[1](1,0) = 1./2.;
+ restriction[1](1,1) = 1.0;
+
+
+ prolongation[0].reinit (2,2);
+ prolongation[1].reinit (2,2);
+
+ prolongation[0](0,0) = 1.0;
+ prolongation[0](1,0) = 1./2.;
+ prolongation[0](1,1) = 1./2.;
+
+ prolongation[1](0,0) = 1./2.;
+ prolongation[1](0,1) = 1./2.;
+ prolongation[1](1,1) = 1.0;
+};
+
+
+
+double
+FELinear<1>::shape_value(const unsigned int i,
+ const Point<1>& p) const
+{
+ Assert((i<total_dofs), ExcInvalidIndex(i));
+ switch (i)
+ {
+ case 0: return 1.-p(0);
+ case 1: return p(0);
+ }
+ return 0.;
+}
+
+
+
+Point<1>
+FELinear<1>::shape_grad(const unsigned int i,
+ const Point<1>&) const
+{
+ Assert((i<total_dofs), ExcInvalidIndex(i));
+ switch (i)
+ {
+ case 0: return Point<1>(-1.);
+ case 1: return Point<1>(1.);
+ }
+ return Point<1>();
+}
+
+
+
+FELinear<2>::FELinear () :
+ FiniteElement<2> (1, 0, 0)
+{
+ interface_constraints.reinit(1,2);
+ interface_constraints(0,0) = 1./2.;
+ interface_constraints(0,1) = 1./2.;
+
+ restriction[0].reinit(4,4);
+ restriction[1].reinit(4,4);
+ restriction[2].reinit(4,4);
+ restriction[3].reinit(4,4);
+
+ prolongation[0].reinit(4,4);
+ prolongation[1].reinit(4,4);
+ prolongation[2].reinit(4,4);
+ prolongation[3].reinit(4,4);
+
+ restriction[0](0,0) = 1.0;
+ restriction[0](0,1) = 1./2.;
+ restriction[0](1,1) = 1./2.;
+ restriction[0](0,3) = 1./2.;
+ restriction[0](3,3) = 1./2.;
+ restriction[0](0,2) = 1./4.;
+ restriction[0](1,2) = 1./4.;
+ restriction[0](2,2) = 1./4.;
+ restriction[0](3,2) = 1./4.;
+
+ restriction[1](1,1) = 1.0;
+ restriction[1](0,0) = 1./2.;
+ restriction[1](1,0) = 1./2.;
+ restriction[1](1,2) = 1./2.;
+ restriction[1](2,2) = 1./2.;
+ restriction[1](0,3) = 1./4.;
+ restriction[1](1,3) = 1./4.;
+ restriction[1](2,3) = 1./4.;
+ restriction[1](3,3) = 1./4.;
+
+ restriction[2](2,2) = 1.0;
+ restriction[2](2,1) = 1./2.;
+ restriction[2](1,1) = 1./2.;
+ restriction[2](2,3) = 1./2.;
+ restriction[2](3,3) = 1./2.;
+ restriction[2](0,0) = 1./4.;
+ restriction[2](1,0) = 1./4.;
+ restriction[2](2,0) = 1./4.;
+ restriction[2](3,0) = 1./4.;
+
+ restriction[3](3,3) = 1.0;
+ restriction[3](0,0) = 1./2.;
+ restriction[3](3,0) = 1./2.;
+ restriction[3](2,2) = 1./2.;
+ restriction[3](3,2) = 1./2.;
+ restriction[3](0,1) = 1./4.;
+ restriction[3](1,1) = 1./4.;
+ restriction[3](2,1) = 1./4.;
+ restriction[3](3,1) = 1./4.;
+
+ prolongation[0](0,0) = 1.0;
+ prolongation[0](1,0) = 1./2.;
+ prolongation[0](1,1) = 1./2.;
+ prolongation[0](3,0) = 1./2.;
+ prolongation[0](3,3) = 1./2.;
+ prolongation[0](2,0) = 1./4.;
+ prolongation[0](2,1) = 1./4.;
+ prolongation[0](2,2) = 1./4.;
+ prolongation[0](2,3) = 1./4.;
+
+ prolongation[1](1,1) = 1.0;
+ prolongation[1](0,0) = 1./2.;
+ prolongation[1](0,1) = 1./2.;
+ prolongation[1](2,1) = 1./2.;
+ prolongation[1](2,2) = 1./2.;
+ prolongation[1](3,0) = 1./4.;
+ prolongation[1](3,1) = 1./4.;
+ prolongation[1](3,2) = 1./4.;
+ prolongation[1](3,3) = 1./4.;
+
+ prolongation[2](2,2) = 1.0;
+ prolongation[2](1,2) = 1./2.;
+ prolongation[2](1,1) = 1./2.;
+ prolongation[2](3,2) = 1./2.;
+ prolongation[2](3,3) = 1./2.;
+ prolongation[2](0,0) = 1./4.;
+ prolongation[2](0,1) = 1./4.;
+ prolongation[2](0,2) = 1./4.;
+ prolongation[2](0,3) = 1./4.;
+
+ prolongation[3](3,3) = 1.0;
+ prolongation[3](0,0) = 1./2.;
+ prolongation[3](0,3) = 1./2.;
+ prolongation[3](2,2) = 1./2.;
+ prolongation[3](2,3) = 1./2.;
+ prolongation[3](1,0) = 1./4.;
+ prolongation[3](1,1) = 1./4.;
+ prolongation[3](1,2) = 1./4.;
+ prolongation[3](1,3) = 1./4.;
+};
+
+
+
+double
+FELinear<2>::shape_value(const unsigned int i,
+ const Point<2>& p) const
+{
+ Assert((i<total_dofs), ExcInvalidIndex(i));
+ switch (i)
+ {
+ case 0: return (1.-p(0)) * (1.-p(1));
+ case 1: return p(0) * (1.-p(1));
+ case 2: return p(0) * p(1);
+ case 3: return (1.-p(0)) * p(1);
+ }
+ return 0.;
+}
+
+
+
+Point<2>
+FELinear<2>::shape_grad(const unsigned int i,
+ const Point<2>& p) const
+{
+ Assert((i<total_dofs), ExcInvalidIndex(i));
+ switch (i)
+ {
+ case 0: return Point<2> (p(1)-1., p(0)-1.);
+ case 1: return Point<2> (1.-p(1), -p(0));
+ case 2: return Point<2> (p(1), p(0));
+ case 3: return Point<2> (-p(1), 1.-p(0));
+ }
+ return Point<2> ();
+}
+
+
+
+FEQuadratic<1>::FEQuadratic () :
+ FiniteElement<1> (1, 1) {};
+
+
+FEQuadratic<2>::FEQuadratic () :
+ FiniteElement<2> (1, 1, 1)
+{
+ interface_constraints.reinit(3,3);
+ interface_constraints(0,2) = 1.0;
+ interface_constraints(1,0) = 3./8.;
+ interface_constraints(1,1) = -1./8.;
+ interface_constraints(1,2) = 3./4.;
+ interface_constraints(2,0) = -1./8.;
+ interface_constraints(2,1) = 3./8.;
+ interface_constraints(2,2) = 3./4.;
+};
+
+
+
+
+FECubic<1>::FECubic () :
+ FiniteElement<1> (1, 2) {};
+
+
+FECubic<2>::FECubic () :
+ FiniteElement<2> (1, 2, 4) {};
+
--- /dev/null
+# $Id$
+
+CXX =c++
+CXXFLAGS.g=-DDEBUG -g -Wall -pedantic -Wconversion -Winline -Woverloaded-virtual -I../../include
+CXXFLAGS =-O3 -Wuninitialized -finline-functions -ffast-math -funroll-loops -felide-constructors -fnonnull-objects -I../../include
+
+ifeq ($(shell uname),SunOS)
+CXXFLAGS := -V2.7.2.3 $(CXXFLAGS)
+CXXFLAGS.g:= -V2.7.2.3 $(CXXFLAGS.g)
+endif
+
+
+cc-files = $(wildcard *.cc)
+o-files = $(cc-files:.cc=.o)
+go-files = $(cc-files:.cc=.go)
+h-files = $(wildcard ../include/*/*.h)
+
+
+%.go : %.cc
+ @echo ============================ Compiling with debugging information: $<
+ @echo $(CXX) ... -c $< -o $@
+ @$(CXX) $(CXXFLAGS.g) -c $< -o $@
+%.o : %.cc
+ @echo ============================ Compiling with optimization: $<
+ @echo $(CXX) ... -c $< -o $@
+ @$(CXX) $(CXXFLAGS) -c $< -o $@
+
+
+lib: lib.g.a lib.a
+
+lib.a: ../../lib/libbasic.a($(o-files))
+
+lib.g.a: ../../lib/libbasic.g.a($(go-files))
+
+clean:
+ rm -f *.o *.go *~ Makefile.dep
+
+
+
+.PHONY: lib lib.a lib.g.a clean
+
+
+#Rule to generate the dependency file. This file is
+#automagically remade whenever needed, i.e. whenever
+#one of the cc-/h-files changed. Make detects whether
+#to remake this file upon inclusion at the bottom
+#of this file.
+#
+#use perl to generate rules for the .go files as well
+#as to make rules not for tria.o and the like, but
+#rather for libbasic.a(tria.o)
+Makefile.dep: $(cc-files) $(h-files)
+ @echo ============================ Remaking Makefile
+ @$(CXX) -I../../include -DDEBUG -M *.cc > Makefile.dep.o
+ @cp Makefile.dep.o Makefile.dep.go
+ @perl -pi -e 's!^(.*\.o):!../../lib/libbasic.a(\1):!g' Makefile.dep.o
+ @perl -pi -e 's!\.o:!.go:!g' Makefile.dep.go
+ @perl -pi -e 's!^(.*\.go):!../../lib/libbasic.g.a(\1):!g' Makefile.dep.go
+ @cat Makefile.dep.o Makefile.dep.go > Makefile.dep
+ @rm Makefile.dep.o Makefile.dep.go
+
+include Makefile.dep
--- /dev/null
+../../lib/libbasic.a(dof.o): dof.cc ../../include/grid/dof.h /usr/local/include/g++/vector.h \
+ /usr/local/include/g++/algobase.h /usr/local/include/g++/pair.h \
+ /usr/local/include/g++/stl_config.h \
+ /usr/local/include/g++/stl_relops.h /usr/local/include/g++/stl_pair.h \
+ /usr/local/include/g++/iterator.h /usr/local/include/g++/function.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/stddef.h \
+ /usr/local/include/g++/stl_function.h \
+ /usr/local/include/g++/iostream.h /usr/local/include/g++/streambuf.h \
+ /usr/local/include/g++/libio.h /usr/local/lib/g++-include/_G_config.h \
+ /usr/local/include/g++/stl_iterator.h \
+ /usr/local/include/g++/type_traits.h \
+ /usr/local/include/g++/stl_construct.h \
+ /usr/local/lib/g++-include/new.h /usr/local/lib/g++-include/std/new.h \
+ /usr/local/lib/g++-include/std/cstddef.h \
+ /usr/local/include/g++/stl_raw_storage_iter.h \
+ /usr/local/include/g++/stl_algobase.h /usr/include/string.h \
+ /usr/include/sys/feature_tests.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/limits.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/syslimits.h \
+ /usr/include/limits.h /usr/include/sys/isa_defs.h \
+ /usr/include/stdlib.h /usr/local/include/g++/stl_uninitialized.h \
+ /usr/local/include/g++/alloc.h /usr/local/include/g++/stl_alloc.h \
+ /usr/local/sparc-sun-solaris2.5.1/include/assert.h \
+ /usr/local/include/g++/stl_vector.h ../../include/fe/fe.h \
+ ../../include/../deal/dfmatrix.h /usr/include/stdio.h \
+ /usr/include/sys/va_list.h ../../include/../deal/dvector.h \
+ ../../include/../deal/types.h ../../include/../deal/errors.h \
+ ../../include/../deal/vectorbase.h ../../include/../deal/ivector.h \
+ ../../include/grid/point.h ../../include/basic/exceptions.h \
+ ../../include/grid/tria.h ../../include/grid/tria_line.h \
+ ../../include/grid/tria_quad.h ../../include/grid/tria_boundary.h \
+ ../../include/grid/dof_accessor.h ../../include/grid/tria_accessor.h \
+ ../../include/grid/dof_constraints.h \
+ ../../include/grid/tria_iterator.h ../../include/../deal/dsmatrix.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/math.h \
+ /usr/include/math.h /usr/include/floatingpoint.h \
+ /usr/include/sys/ieeefp.h /usr/local/include/g++/multimap.h \
+ /usr/local/include/g++/tree.h /usr/local/include/g++/stl_tree.h \
+ /usr/local/include/g++/stl_multimap.h /usr/local/include/g++/algo.h \
+ /usr/local/include/g++/tempbuf.h /usr/local/include/g++/stl_tempbuf.h \
+ /usr/local/include/g++/stl_algo.h /usr/local/include/g++/stl_heap.h \
+ /usr/local/include/g++/stl_numeric.h
+../../lib/libbasic.a(dof_accessor.o): dof_accessor.cc ../../include/grid/dof_accessor.h \
+ ../../include/grid/tria_accessor.h ../../include/basic/exceptions.h \
+ /usr/local/include/g++/iostream.h /usr/local/include/g++/streambuf.h \
+ /usr/local/include/g++/libio.h /usr/local/lib/g++-include/_G_config.h \
+ ../../include/grid/dof.h /usr/local/include/g++/vector.h \
+ /usr/local/include/g++/algobase.h /usr/local/include/g++/pair.h \
+ /usr/local/include/g++/stl_config.h \
+ /usr/local/include/g++/stl_relops.h /usr/local/include/g++/stl_pair.h \
+ /usr/local/include/g++/iterator.h /usr/local/include/g++/function.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/stddef.h \
+ /usr/local/include/g++/stl_function.h \
+ /usr/local/include/g++/stl_iterator.h \
+ /usr/local/include/g++/type_traits.h \
+ /usr/local/include/g++/stl_construct.h \
+ /usr/local/lib/g++-include/new.h /usr/local/lib/g++-include/std/new.h \
+ /usr/local/lib/g++-include/std/cstddef.h \
+ /usr/local/include/g++/stl_raw_storage_iter.h \
+ /usr/local/include/g++/stl_algobase.h /usr/include/string.h \
+ /usr/include/sys/feature_tests.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/limits.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/syslimits.h \
+ /usr/include/limits.h /usr/include/sys/isa_defs.h \
+ /usr/include/stdlib.h /usr/local/include/g++/stl_uninitialized.h \
+ /usr/local/include/g++/alloc.h /usr/local/include/g++/stl_alloc.h \
+ /usr/local/sparc-sun-solaris2.5.1/include/assert.h \
+ /usr/local/include/g++/stl_vector.h ../../include/fe/fe.h \
+ ../../include/../deal/dfmatrix.h /usr/include/stdio.h \
+ /usr/include/sys/va_list.h ../../include/../deal/dvector.h \
+ ../../include/../deal/types.h ../../include/../deal/errors.h \
+ ../../include/../deal/vectorbase.h ../../include/../deal/ivector.h \
+ ../../include/grid/point.h ../../include/grid/tria.h \
+ ../../include/grid/tria_line.h ../../include/grid/tria_quad.h \
+ ../../include/grid/tria_boundary.h ../../include/grid/tria_iterator.h \
+ ../../include/grid/tria_iterator.templates.h
+../../lib/libbasic.a(dof_constraints.o): dof_constraints.cc /usr/local/include/g++/algo.h \
+ /usr/local/include/g++/algobase.h /usr/local/include/g++/pair.h \
+ /usr/local/include/g++/stl_config.h \
+ /usr/local/include/g++/stl_relops.h /usr/local/include/g++/stl_pair.h \
+ /usr/local/include/g++/iterator.h /usr/local/include/g++/function.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/stddef.h \
+ /usr/local/include/g++/stl_function.h \
+ /usr/local/include/g++/iostream.h /usr/local/include/g++/streambuf.h \
+ /usr/local/include/g++/libio.h /usr/local/lib/g++-include/_G_config.h \
+ /usr/local/include/g++/stl_iterator.h \
+ /usr/local/include/g++/type_traits.h \
+ /usr/local/include/g++/stl_construct.h \
+ /usr/local/lib/g++-include/new.h /usr/local/lib/g++-include/std/new.h \
+ /usr/local/lib/g++-include/std/cstddef.h \
+ /usr/local/include/g++/stl_raw_storage_iter.h \
+ /usr/local/include/g++/stl_algobase.h /usr/include/string.h \
+ /usr/include/sys/feature_tests.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/limits.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/syslimits.h \
+ /usr/include/limits.h /usr/include/sys/isa_defs.h \
+ /usr/include/stdlib.h /usr/local/include/g++/stl_uninitialized.h \
+ /usr/local/include/g++/tempbuf.h /usr/local/include/g++/stl_tempbuf.h \
+ /usr/local/include/g++/stl_algo.h /usr/local/include/g++/stl_heap.h \
+ /usr/local/include/g++/stl_numeric.h \
+ ../../include/grid/dof_constraints.h /usr/local/include/g++/vector.h \
+ /usr/local/include/g++/alloc.h /usr/local/include/g++/stl_alloc.h \
+ /usr/local/sparc-sun-solaris2.5.1/include/assert.h \
+ /usr/local/include/g++/stl_vector.h ../../include/basic/exceptions.h \
+ ../../include/../deal/dsmatrix.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/math.h \
+ /usr/include/math.h /usr/include/floatingpoint.h /usr/include/stdio.h \
+ /usr/include/sys/va_list.h /usr/include/sys/ieeefp.h \
+ ../../include/../deal/dvector.h ../../include/../deal/types.h \
+ ../../include/../deal/errors.h ../../include/../deal/vectorbase.h
+../../lib/libbasic.a(tria.o): tria.cc ../../include/grid/tria_iterator.h \
+ /usr/local/include/g++/iterator.h /usr/local/include/g++/function.h \
+ /usr/local/include/g++/stl_config.h \
+ /usr/local/include/g++/stl_relops.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/stddef.h \
+ /usr/local/include/g++/stl_function.h \
+ /usr/local/include/g++/iostream.h /usr/local/include/g++/streambuf.h \
+ /usr/local/include/g++/libio.h /usr/local/lib/g++-include/_G_config.h \
+ /usr/local/include/g++/stl_iterator.h \
+ /usr/local/include/g++/type_traits.h \
+ /usr/local/include/g++/stl_construct.h \
+ /usr/local/lib/g++-include/new.h /usr/local/lib/g++-include/std/new.h \
+ /usr/local/lib/g++-include/std/cstddef.h \
+ /usr/local/include/g++/stl_raw_storage_iter.h \
+ ../../include/basic/exceptions.h ../../include/grid/point.h \
+ ../../include/grid/tria_accessor.h ../../include/grid/tria.h \
+ /usr/local/include/g++/vector.h /usr/local/include/g++/algobase.h \
+ /usr/local/include/g++/pair.h /usr/local/include/g++/stl_pair.h \
+ /usr/local/include/g++/stl_algobase.h /usr/include/string.h \
+ /usr/include/sys/feature_tests.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/limits.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/syslimits.h \
+ /usr/include/limits.h /usr/include/sys/isa_defs.h \
+ /usr/include/stdlib.h /usr/local/include/g++/stl_uninitialized.h \
+ /usr/local/include/g++/alloc.h /usr/local/include/g++/stl_alloc.h \
+ /usr/local/sparc-sun-solaris2.5.1/include/assert.h \
+ /usr/local/include/g++/stl_vector.h ../../include/grid/tria_line.h \
+ ../../include/grid/tria_quad.h ../../include/grid/tria_boundary.h \
+ ../../include/basic/magic_numbers.h /usr/local/include/g++/algo.h \
+ /usr/local/include/g++/tempbuf.h /usr/local/include/g++/stl_tempbuf.h \
+ /usr/local/include/g++/stl_algo.h /usr/local/include/g++/stl_heap.h \
+ /usr/local/include/g++/stl_numeric.h
+../../lib/libbasic.a(tria_accessor.o): tria_accessor.cc ../../include/grid/tria.h \
+ /usr/local/include/g++/vector.h /usr/local/include/g++/algobase.h \
+ /usr/local/include/g++/pair.h /usr/local/include/g++/stl_config.h \
+ /usr/local/include/g++/stl_relops.h /usr/local/include/g++/stl_pair.h \
+ /usr/local/include/g++/iterator.h /usr/local/include/g++/function.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/stddef.h \
+ /usr/local/include/g++/stl_function.h \
+ /usr/local/include/g++/iostream.h /usr/local/include/g++/streambuf.h \
+ /usr/local/include/g++/libio.h /usr/local/lib/g++-include/_G_config.h \
+ /usr/local/include/g++/stl_iterator.h \
+ /usr/local/include/g++/type_traits.h \
+ /usr/local/include/g++/stl_construct.h \
+ /usr/local/lib/g++-include/new.h /usr/local/lib/g++-include/std/new.h \
+ /usr/local/lib/g++-include/std/cstddef.h \
+ /usr/local/include/g++/stl_raw_storage_iter.h \
+ /usr/local/include/g++/stl_algobase.h /usr/include/string.h \
+ /usr/include/sys/feature_tests.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/limits.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/syslimits.h \
+ /usr/include/limits.h /usr/include/sys/isa_defs.h \
+ /usr/include/stdlib.h /usr/local/include/g++/stl_uninitialized.h \
+ /usr/local/include/g++/alloc.h /usr/local/include/g++/stl_alloc.h \
+ /usr/local/sparc-sun-solaris2.5.1/include/assert.h \
+ /usr/local/include/g++/stl_vector.h ../../include/grid/tria_line.h \
+ ../../include/basic/exceptions.h ../../include/grid/tria_quad.h \
+ ../../include/grid/point.h ../../include/grid/tria_boundary.h \
+ ../../include/grid/tria_iterator.h ../../include/grid/tria_accessor.h \
+ ../../include/grid/tria_iterator.templates.h
+../../lib/libbasic.g.a(dof.go): dof.cc ../../include/grid/dof.h /usr/local/include/g++/vector.h \
+ /usr/local/include/g++/algobase.h /usr/local/include/g++/pair.h \
+ /usr/local/include/g++/stl_config.h \
+ /usr/local/include/g++/stl_relops.h /usr/local/include/g++/stl_pair.h \
+ /usr/local/include/g++/iterator.h /usr/local/include/g++/function.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/stddef.h \
+ /usr/local/include/g++/stl_function.h \
+ /usr/local/include/g++/iostream.h /usr/local/include/g++/streambuf.h \
+ /usr/local/include/g++/libio.h /usr/local/lib/g++-include/_G_config.h \
+ /usr/local/include/g++/stl_iterator.h \
+ /usr/local/include/g++/type_traits.h \
+ /usr/local/include/g++/stl_construct.h \
+ /usr/local/lib/g++-include/new.h /usr/local/lib/g++-include/std/new.h \
+ /usr/local/lib/g++-include/std/cstddef.h \
+ /usr/local/include/g++/stl_raw_storage_iter.h \
+ /usr/local/include/g++/stl_algobase.h /usr/include/string.h \
+ /usr/include/sys/feature_tests.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/limits.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/syslimits.h \
+ /usr/include/limits.h /usr/include/sys/isa_defs.h \
+ /usr/include/stdlib.h /usr/local/include/g++/stl_uninitialized.h \
+ /usr/local/include/g++/alloc.h /usr/local/include/g++/stl_alloc.h \
+ /usr/local/sparc-sun-solaris2.5.1/include/assert.h \
+ /usr/local/include/g++/stl_vector.h ../../include/fe/fe.h \
+ ../../include/../deal/dfmatrix.h /usr/include/stdio.h \
+ /usr/include/sys/va_list.h ../../include/../deal/dvector.h \
+ ../../include/../deal/types.h ../../include/../deal/errors.h \
+ ../../include/../deal/vectorbase.h ../../include/../deal/ivector.h \
+ ../../include/grid/point.h ../../include/basic/exceptions.h \
+ ../../include/grid/tria.h ../../include/grid/tria_line.h \
+ ../../include/grid/tria_quad.h ../../include/grid/tria_boundary.h \
+ ../../include/grid/dof_accessor.h ../../include/grid/tria_accessor.h \
+ ../../include/grid/dof_constraints.h \
+ ../../include/grid/tria_iterator.h ../../include/../deal/dsmatrix.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/math.h \
+ /usr/include/math.h /usr/include/floatingpoint.h \
+ /usr/include/sys/ieeefp.h /usr/local/include/g++/multimap.h \
+ /usr/local/include/g++/tree.h /usr/local/include/g++/stl_tree.h \
+ /usr/local/include/g++/stl_multimap.h /usr/local/include/g++/algo.h \
+ /usr/local/include/g++/tempbuf.h /usr/local/include/g++/stl_tempbuf.h \
+ /usr/local/include/g++/stl_algo.h /usr/local/include/g++/stl_heap.h \
+ /usr/local/include/g++/stl_numeric.h
+../../lib/libbasic.g.a(dof_accessor.go): dof_accessor.cc ../../include/grid/dof_accessor.h \
+ ../../include/grid/tria_accessor.h ../../include/basic/exceptions.h \
+ /usr/local/include/g++/iostream.h /usr/local/include/g++/streambuf.h \
+ /usr/local/include/g++/libio.h /usr/local/lib/g++-include/_G_config.h \
+ ../../include/grid/dof.h /usr/local/include/g++/vector.h \
+ /usr/local/include/g++/algobase.h /usr/local/include/g++/pair.h \
+ /usr/local/include/g++/stl_config.h \
+ /usr/local/include/g++/stl_relops.h /usr/local/include/g++/stl_pair.h \
+ /usr/local/include/g++/iterator.h /usr/local/include/g++/function.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/stddef.h \
+ /usr/local/include/g++/stl_function.h \
+ /usr/local/include/g++/stl_iterator.h \
+ /usr/local/include/g++/type_traits.h \
+ /usr/local/include/g++/stl_construct.h \
+ /usr/local/lib/g++-include/new.h /usr/local/lib/g++-include/std/new.h \
+ /usr/local/lib/g++-include/std/cstddef.h \
+ /usr/local/include/g++/stl_raw_storage_iter.h \
+ /usr/local/include/g++/stl_algobase.h /usr/include/string.h \
+ /usr/include/sys/feature_tests.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/limits.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/syslimits.h \
+ /usr/include/limits.h /usr/include/sys/isa_defs.h \
+ /usr/include/stdlib.h /usr/local/include/g++/stl_uninitialized.h \
+ /usr/local/include/g++/alloc.h /usr/local/include/g++/stl_alloc.h \
+ /usr/local/sparc-sun-solaris2.5.1/include/assert.h \
+ /usr/local/include/g++/stl_vector.h ../../include/fe/fe.h \
+ ../../include/../deal/dfmatrix.h /usr/include/stdio.h \
+ /usr/include/sys/va_list.h ../../include/../deal/dvector.h \
+ ../../include/../deal/types.h ../../include/../deal/errors.h \
+ ../../include/../deal/vectorbase.h ../../include/../deal/ivector.h \
+ ../../include/grid/point.h ../../include/grid/tria.h \
+ ../../include/grid/tria_line.h ../../include/grid/tria_quad.h \
+ ../../include/grid/tria_boundary.h ../../include/grid/tria_iterator.h \
+ ../../include/grid/tria_iterator.templates.h
+../../lib/libbasic.g.a(dof_constraints.go): dof_constraints.cc /usr/local/include/g++/algo.h \
+ /usr/local/include/g++/algobase.h /usr/local/include/g++/pair.h \
+ /usr/local/include/g++/stl_config.h \
+ /usr/local/include/g++/stl_relops.h /usr/local/include/g++/stl_pair.h \
+ /usr/local/include/g++/iterator.h /usr/local/include/g++/function.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/stddef.h \
+ /usr/local/include/g++/stl_function.h \
+ /usr/local/include/g++/iostream.h /usr/local/include/g++/streambuf.h \
+ /usr/local/include/g++/libio.h /usr/local/lib/g++-include/_G_config.h \
+ /usr/local/include/g++/stl_iterator.h \
+ /usr/local/include/g++/type_traits.h \
+ /usr/local/include/g++/stl_construct.h \
+ /usr/local/lib/g++-include/new.h /usr/local/lib/g++-include/std/new.h \
+ /usr/local/lib/g++-include/std/cstddef.h \
+ /usr/local/include/g++/stl_raw_storage_iter.h \
+ /usr/local/include/g++/stl_algobase.h /usr/include/string.h \
+ /usr/include/sys/feature_tests.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/limits.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/syslimits.h \
+ /usr/include/limits.h /usr/include/sys/isa_defs.h \
+ /usr/include/stdlib.h /usr/local/include/g++/stl_uninitialized.h \
+ /usr/local/include/g++/tempbuf.h /usr/local/include/g++/stl_tempbuf.h \
+ /usr/local/include/g++/stl_algo.h /usr/local/include/g++/stl_heap.h \
+ /usr/local/include/g++/stl_numeric.h \
+ ../../include/grid/dof_constraints.h /usr/local/include/g++/vector.h \
+ /usr/local/include/g++/alloc.h /usr/local/include/g++/stl_alloc.h \
+ /usr/local/sparc-sun-solaris2.5.1/include/assert.h \
+ /usr/local/include/g++/stl_vector.h ../../include/basic/exceptions.h \
+ ../../include/../deal/dsmatrix.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/math.h \
+ /usr/include/math.h /usr/include/floatingpoint.h /usr/include/stdio.h \
+ /usr/include/sys/va_list.h /usr/include/sys/ieeefp.h \
+ ../../include/../deal/dvector.h ../../include/../deal/types.h \
+ ../../include/../deal/errors.h ../../include/../deal/vectorbase.h
+../../lib/libbasic.g.a(tria.go): tria.cc ../../include/grid/tria_iterator.h \
+ /usr/local/include/g++/iterator.h /usr/local/include/g++/function.h \
+ /usr/local/include/g++/stl_config.h \
+ /usr/local/include/g++/stl_relops.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/stddef.h \
+ /usr/local/include/g++/stl_function.h \
+ /usr/local/include/g++/iostream.h /usr/local/include/g++/streambuf.h \
+ /usr/local/include/g++/libio.h /usr/local/lib/g++-include/_G_config.h \
+ /usr/local/include/g++/stl_iterator.h \
+ /usr/local/include/g++/type_traits.h \
+ /usr/local/include/g++/stl_construct.h \
+ /usr/local/lib/g++-include/new.h /usr/local/lib/g++-include/std/new.h \
+ /usr/local/lib/g++-include/std/cstddef.h \
+ /usr/local/include/g++/stl_raw_storage_iter.h \
+ ../../include/basic/exceptions.h ../../include/grid/point.h \
+ ../../include/grid/tria_accessor.h ../../include/grid/tria.h \
+ /usr/local/include/g++/vector.h /usr/local/include/g++/algobase.h \
+ /usr/local/include/g++/pair.h /usr/local/include/g++/stl_pair.h \
+ /usr/local/include/g++/stl_algobase.h /usr/include/string.h \
+ /usr/include/sys/feature_tests.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/limits.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/syslimits.h \
+ /usr/include/limits.h /usr/include/sys/isa_defs.h \
+ /usr/include/stdlib.h /usr/local/include/g++/stl_uninitialized.h \
+ /usr/local/include/g++/alloc.h /usr/local/include/g++/stl_alloc.h \
+ /usr/local/sparc-sun-solaris2.5.1/include/assert.h \
+ /usr/local/include/g++/stl_vector.h ../../include/grid/tria_line.h \
+ ../../include/grid/tria_quad.h ../../include/grid/tria_boundary.h \
+ ../../include/basic/magic_numbers.h /usr/local/include/g++/algo.h \
+ /usr/local/include/g++/tempbuf.h /usr/local/include/g++/stl_tempbuf.h \
+ /usr/local/include/g++/stl_algo.h /usr/local/include/g++/stl_heap.h \
+ /usr/local/include/g++/stl_numeric.h
+../../lib/libbasic.g.a(tria_accessor.go): tria_accessor.cc ../../include/grid/tria.h \
+ /usr/local/include/g++/vector.h /usr/local/include/g++/algobase.h \
+ /usr/local/include/g++/pair.h /usr/local/include/g++/stl_config.h \
+ /usr/local/include/g++/stl_relops.h /usr/local/include/g++/stl_pair.h \
+ /usr/local/include/g++/iterator.h /usr/local/include/g++/function.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/stddef.h \
+ /usr/local/include/g++/stl_function.h \
+ /usr/local/include/g++/iostream.h /usr/local/include/g++/streambuf.h \
+ /usr/local/include/g++/libio.h /usr/local/lib/g++-include/_G_config.h \
+ /usr/local/include/g++/stl_iterator.h \
+ /usr/local/include/g++/type_traits.h \
+ /usr/local/include/g++/stl_construct.h \
+ /usr/local/lib/g++-include/new.h /usr/local/lib/g++-include/std/new.h \
+ /usr/local/lib/g++-include/std/cstddef.h \
+ /usr/local/include/g++/stl_raw_storage_iter.h \
+ /usr/local/include/g++/stl_algobase.h /usr/include/string.h \
+ /usr/include/sys/feature_tests.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/limits.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/syslimits.h \
+ /usr/include/limits.h /usr/include/sys/isa_defs.h \
+ /usr/include/stdlib.h /usr/local/include/g++/stl_uninitialized.h \
+ /usr/local/include/g++/alloc.h /usr/local/include/g++/stl_alloc.h \
+ /usr/local/sparc-sun-solaris2.5.1/include/assert.h \
+ /usr/local/include/g++/stl_vector.h ../../include/grid/tria_line.h \
+ ../../include/basic/exceptions.h ../../include/grid/tria_quad.h \
+ ../../include/grid/point.h ../../include/grid/tria_boundary.h \
+ ../../include/grid/tria_iterator.h ../../include/grid/tria_accessor.h \
+ ../../include/grid/tria_iterator.templates.h
--- /dev/null
+/* $Id$ */
+
+#include <grid/tria_iterator.h>
+#include <grid/tria.h>
+#include <basic/magic_numbers.h>
+#include <iostream.h>
+#include <algo.h>
+
+
+
+template <int dim>
+Triangulation<dim>::Triangulation () {
+ static StraightBoundary<dim> default_boundary;
+ boundary = &default_boundary;
+
+ levels.push_back (new TriangulationLevel<dim>);
+};
+
+
+template <int dim>
+Triangulation<dim>::~Triangulation () {
+ for (unsigned int i=0; i<levels.size(); ++i)
+ delete levels[i];
+
+ levels.erase (levels.begin(), levels.end());
+};
+
+
+
+template <int dim>
+void Triangulation<dim>::set_boundary (const Boundary<dim> *boundary_object) {
+ boundary = boundary_object;
+};
+
+
+
+void Triangulation<1>::create_unit_hypercube () {
+ vertices.push_back (Point<1> (0.0));
+ vertices.push_back (Point<1> (1.0));
+
+ vertices_used.insert (vertices_used.end(), 2, true);
+
+ levels[0]->lines.lines.push_back (Line(0,1));
+ levels[0]->lines.children.push_back (-1);
+ levels[0]->lines.used.push_back (true);
+ levels[0]->lines.user_flags.push_back (false);
+ levels[0]->neighbors.push_back (make_pair(-1,-1));
+ levels[0]->neighbors.push_back (make_pair(-1,-1));
+
+ levels[0]->refine_flags.insert (levels[0]->refine_flags.end(), 1, false);
+};
+
+
+
+
+void Triangulation<2>::create_unit_hypercube () {
+ // create vertices
+ vertices.push_back (Point<2> (0,0));
+ vertices.push_back (Point<2> (1,0));
+ vertices.push_back (Point<2> (1,1));
+ vertices.push_back (Point<2> (0,1));
+ vertices_used.insert (vertices_used.end(), 4, true);
+
+ // create lines
+ levels[0]->lines.lines.push_back (Line (0,1));
+ levels[0]->lines.children.push_back (-1);
+ levels[0]->lines.used.push_back (true);
+ levels[0]->lines.user_flags.push_back (false);
+
+ levels[0]->lines.lines.push_back (Line (1,2));
+ levels[0]->lines.children.push_back (-1);
+ levels[0]->lines.used.push_back (true);
+ levels[0]->lines.user_flags.push_back (false);
+
+ levels[0]->lines.lines.push_back (Line (3,2));
+ levels[0]->lines.children.push_back (-1);
+ levels[0]->lines.used.push_back (true);
+ levels[0]->lines.user_flags.push_back (false);
+
+ levels[0]->lines.lines.push_back (Line (0,3));
+ levels[0]->lines.children.push_back (-1);
+ levels[0]->lines.used.push_back (true);
+ levels[0]->lines.user_flags.push_back (false);
+
+ // create quads
+ levels[0]->quads.quads.push_back (Quad (0,1,2,3));
+ levels[0]->quads.children.push_back (-1);
+ levels[0]->quads.used.push_back (true);
+ levels[0]->quads.user_flags.push_back (false);
+
+ levels[0]->neighbors.push_back (make_pair(-1,-1));
+ levels[0]->neighbors.push_back (make_pair(-1,-1));
+ levels[0]->neighbors.push_back (make_pair(-1,-1));
+ levels[0]->neighbors.push_back (make_pair(-1,-1));
+
+ levels[0]->refine_flags.insert (levels[0]->refine_flags.end(), 1, false);
+};
+
+
+
+
+template <int dim>
+void Triangulation<dim>::set_all_refine_flags () {
+ active_cell_iterator cell = begin_active(),
+ endc = end();
+
+ for (; cell != endc; ++cell)
+ cell->set_refine_flag ();
+};
+
+
+
+template <int dim>
+void Triangulation<dim>::refine_global (const unsigned int times) {
+ for (unsigned int i=0; i<times; ++i)
+ {
+ set_all_refine_flags();
+ execute_refinement ();
+ };
+};
+
+
+
+template <int dim>
+void Triangulation<dim>::save_refine_flags (ostream &out) const {
+ unsigned int N = n_active_cells();
+ active_cell_iterator cell = begin_active(),
+ endc = end();
+
+ unsigned char *flags = new unsigned char[N/8+1];
+ for (unsigned int i=0; i<N/8+1; ++i) flags[i]=0;
+
+ for (unsigned int position=0; cell!=endc; ++cell, ++position)
+ flags[position/8] |= (cell->refine_flag_set() ? (1<<(position%8)) : 0);
+
+ // format:
+ // 0. magic number 0xabcc
+ // 1. number of active cells
+ // 2. the flags
+ // 3. magic number 0xabcd
+ out << mn_tria_refine_flags_begin << " " << N << endl;
+ for (unsigned int i=0; i<N/8+1; ++i)
+ out << (unsigned int)flags[i] << " ";
+
+ out << endl;
+ out << mn_tria_refine_flags_end << endl;
+
+ delete[] flags;
+};
+
+
+
+template <int dim>
+void Triangulation<dim>::load_refine_flags (istream &in) {
+ int magic_number;
+ in >> magic_number;
+ Assert (magic_number==mn_tria_refine_flags_begin, ExcGridReadError());
+
+ unsigned int N;
+ in >> N;
+ Assert (N==n_active_cells(), ExcGridsDoNotMatch(N, n_active_cells()));
+
+ unsigned char *flags = new unsigned char[N/8+1];
+ unsigned short int tmp;
+ for (unsigned int i=0; i<N/8+1; ++i)
+ {
+ in >> tmp;
+ flags[i] = tmp;
+ };
+
+
+ active_cell_iterator cell = begin_active(),
+ endc = end();
+ unsigned int position=0;
+ for (; cell!=endc; ++cell, ++position)
+ if (flags[position/8] & (1<<(position%8)))
+ cell->set_refine_flag();
+ else
+ cell->clear_refine_flag();
+
+ Assert (position==N, ExcGridReadError());
+
+ in >> magic_number;
+ Assert (magic_number==mn_tria_refine_flags_end, ExcGridReadError());
+
+ delete[] flags;
+};
+
+
+
+
+void Triangulation<1>::clear_user_flags () {
+ cell_iterator cell = begin(),
+ endc = end();
+ for (; cell!=endc; ++cell)
+ cell->clear_user_flag ();
+};
+
+
+
+void Triangulation<2>::clear_user_flags () {
+ line_iterator line = begin_line(),
+ endl = end_line();
+ for (; line!=endl; ++line)
+ line->clear_user_flag ();
+
+ cell_iterator cell = begin(),
+ endc = end();
+ for (; cell!=endc; ++cell)
+ cell->clear_user_flag ();
+};
+
+
+
+
+void Triangulation<1>::save_user_flags (ostream &out) const {
+ save_user_flags_line (out);
+};
+
+
+
+void Triangulation<2>::save_user_flags (ostream &out) const {
+ save_user_flags_line (out);
+ save_user_flags_quad (out);
+};
+
+
+
+template <int dim>
+void Triangulation<dim>::save_user_flags_line (ostream &out) const {
+ unsigned int N = n_lines();
+ line_iterator line = begin_line(),
+ endc = end_line();
+
+ unsigned char *flags = new unsigned char[N/8+1];
+ for (unsigned int i=0; i<N/8+1; ++i) flags[i]=0;
+
+ for (unsigned int position=0; line!=endc; ++line, ++position)
+ flags[position/8] |= (line->user_flag_set() ? (1<<(position%8)) : 0);
+
+ // format:
+ // 0. magic number 0xabce
+ // 1. number of lines
+ // 2. the flags
+ // 3. magic number 0xabcf
+ out << mn_tria_line_user_flags_begin << " " << N << endl;
+ for (unsigned int i=0; i<N/8+1; ++i)
+ out << (unsigned int)flags[i] << " ";
+
+ out << endl;
+ out << mn_tria_line_user_flags_end << endl;
+
+ delete[] flags;
+};
+
+
+
+template <int dim>
+void Triangulation<dim>::load_user_flags_line (istream &in) {
+ int magic_number;
+ in >> magic_number;
+ Assert (magic_number==mn_tria_line_user_flags_begin, ExcGridReadError());
+
+ unsigned int N;
+ in >> N;
+ Assert (N==n_lines(), ExcGridsDoNotMatch(N, n_lines()));
+
+ unsigned char *flags = new unsigned char[N/8+1];
+ unsigned short int tmp;
+ for (unsigned int i=0; i<N/8+1; ++i)
+ {
+ in >> tmp;
+ flags[i] = tmp;
+ };
+
+
+ line_iterator line = begin_line(),
+ endc = end_line();
+ unsigned int position=0;
+ for (; line!=endc; ++line, ++position)
+ if (flags[position/8] & (1<<(position%8)))
+ line->set_user_flag();
+ else
+ line->clear_user_flag();
+
+ Assert (position==N, ExcGridReadError());
+
+ in >> magic_number;
+ Assert (magic_number==mn_tria_line_user_flags_end, ExcGridReadError());
+
+ delete[] flags;
+};
+
+
+
+void Triangulation<1>::save_user_flags_quad (ostream &) const {
+ Assert (false, ExcFunctionNotUseful());
+};
+
+
+
+template <int dim>
+void Triangulation<dim>::save_user_flags_quad (ostream &out) const {
+ unsigned int N = n_quads();
+ quad_iterator quad = begin_quad(),
+ endc = end_quad();
+
+ unsigned char *flags = new unsigned char[N/8+1];
+ for (unsigned int i=0; i<N/8+1; ++i) flags[i]=0;
+
+ for (unsigned int position=0; quad!=endc; ++quad, ++position)
+ flags[position/8] |= (quad->user_flag_set() ? (1<<(position%8)) : 0);
+
+ // format:
+ // 0. magic number 0xabce
+ // 1. number of quads
+ // 2. the flags
+ // 3. magic number 0xabcf
+ out << mn_tria_quad_user_flags_begin << " " << N << endl;
+ for (unsigned int i=0; i<N/8+1; ++i)
+ out << (unsigned int)flags[i] << " ";
+
+ out << endl;
+ out << mn_tria_quad_user_flags_end << endl;
+
+ delete[] flags;
+};
+
+
+
+void Triangulation<1>::load_user_flags_quad (istream &) {
+ Assert (false, ExcFunctionNotUseful());
+};
+
+
+
+template <int dim>
+void Triangulation<dim>::load_user_flags_quad (istream &in) {
+ int magic_number;
+ in >> magic_number;
+ Assert (magic_number==mn_tria_quad_user_flags_begin, ExcGridReadError());
+
+ unsigned int N;
+ in >> N;
+ Assert (N==n_quads(), ExcGridsDoNotMatch(N, n_quads()));
+
+ unsigned char *flags = new unsigned char[N/8+1];
+ unsigned short int tmp;
+ for (unsigned int i=0; i<N/8+1; ++i)
+ {
+ in >> tmp;
+ flags[i] = tmp;
+ };
+
+
+ quad_iterator quad = begin_quad(),
+ endc = end_quad();
+ unsigned int position=0;
+ for (; quad!=endc; ++quad, ++position)
+ if (flags[position/8] & (1<<(position%8)))
+ quad->set_user_flag();
+ else
+ quad->clear_user_flag();
+
+ Assert (position==N, ExcGridReadError());
+
+ in >> magic_number;
+ Assert (magic_number==mn_tria_quad_user_flags_end, ExcGridReadError());
+
+ delete[] flags;
+};
+
+
+
+TriaDimensionInfo<1>::raw_cell_iterator
+Triangulation<1>::begin_raw (const unsigned int level) const {
+ return begin_raw_line (level);
+};
+
+
+
+TriaDimensionInfo<1>::cell_iterator
+Triangulation<1>::begin (const unsigned int level) const {
+ return begin_line (level);
+};
+
+
+
+TriaDimensionInfo<1>::active_cell_iterator
+Triangulation<1>::begin_active (const unsigned int level) const {
+ return begin_active_line (level);
+};
+
+
+
+TriaDimensionInfo<1>::raw_cell_iterator
+Triangulation<1>::end () const {
+ return end_line ();
+};
+
+
+
+TriaDimensionInfo<1>::raw_cell_iterator
+Triangulation<1>::last_raw () const {
+ return last_raw_line ();
+};
+
+
+
+TriaDimensionInfo<1>::raw_cell_iterator
+Triangulation<1>::last_raw (const unsigned int level) const {
+ return last_raw_line (level);
+};
+
+
+
+TriaDimensionInfo<1>::cell_iterator
+Triangulation<1>::last () const {
+ return last_line ();
+};
+
+
+
+TriaDimensionInfo<1>::cell_iterator
+Triangulation<1>::last (const unsigned int level) const {
+ return last_line (level);
+};
+
+
+
+TriaDimensionInfo<1>::active_cell_iterator
+Triangulation<1>::last_active () const {
+ return last_active_line ();
+};
+
+
+
+TriaDimensionInfo<1>::active_cell_iterator
+Triangulation<1>::last_active (const unsigned int level) const {
+ return last_active_line (level);
+};
+
+
+
+
+
+TriaDimensionInfo<2>::raw_cell_iterator
+Triangulation<2>::begin_raw (const unsigned int level) const {
+ return begin_raw_quad (level);
+};
+
+
+
+TriaDimensionInfo<2>::cell_iterator
+Triangulation<2>::begin (const unsigned int level) const {
+ return begin_quad (level);
+};
+
+
+
+TriaDimensionInfo<2>::active_cell_iterator
+Triangulation<2>::begin_active (const unsigned int level) const {
+ return begin_active_quad (level);
+};
+
+
+
+TriaDimensionInfo<2>::raw_cell_iterator
+Triangulation<2>::end () const {
+ return end_quad ();
+};
+
+
+
+TriaDimensionInfo<2>::raw_cell_iterator
+Triangulation<2>::last_raw () const {
+ return last_raw_quad ();
+};
+
+
+
+TriaDimensionInfo<2>::raw_cell_iterator
+Triangulation<2>::last_raw (const unsigned int level) const {
+ return last_raw_quad (level);
+};
+
+
+
+TriaDimensionInfo<2>::cell_iterator
+Triangulation<2>::last () const {
+ return last_quad ();
+};
+
+
+
+TriaDimensionInfo<2>::cell_iterator
+Triangulation<2>::last (const unsigned int level) const {
+ return last_quad (level);
+};
+
+
+
+TriaDimensionInfo<2>::active_cell_iterator
+Triangulation<2>::last_active () const {
+ return last_active_quad ();
+};
+
+
+
+TriaDimensionInfo<2>::active_cell_iterator
+Triangulation<2>::last_active (const unsigned int level) const {
+ return last_active_quad (level);
+};
+
+
+
+
+
+TriaDimensionInfo<1>::raw_line_iterator
+Triangulation<1>::begin_raw_line (unsigned int level) const {
+ Assert (level<levels.size(),
+ ExcInvalidLevel(level));
+
+ // does this level have cells?
+ if (levels[level]->lines.lines.size() == 0)
+ return end();
+
+ return raw_cell_iterator ((Triangulation<1>*)this,
+ level,
+ 0);
+};
+
+
+
+TriaDimensionInfo<2>::raw_line_iterator
+Triangulation<2>::begin_raw_line (unsigned int level) const {
+ Assert (level<levels.size(),
+ ExcInvalidLevel(level));
+
+ // does this level have cells?
+ if (levels[level]->lines.lines.size() == 0)
+ return end_line();
+
+ return raw_line_iterator ((Triangulation<2>*)this,
+ level,
+ 0);
+};
+
+
+
+TriaDimensionInfo<2>::raw_quad_iterator
+Triangulation<2>::begin_raw_quad (unsigned int level) const {
+ Assert (level<levels.size(),
+ ExcInvalidLevel(level));
+
+ if (levels[level]->quads.quads.size() == 0)
+ return end_quad();
+
+ return raw_quad_iterator ((Triangulation<2>*)this,
+ level,
+ 0);
+};
+
+
+
+TriaDimensionInfo<1>::line_iterator
+Triangulation<1>::begin_line (unsigned int level) const {
+ // level is checked in begin_raw
+ raw_line_iterator ri = begin_raw_line (level);
+ if (ri.state() != valid)
+ return ri;
+ while (ri->used() == false)
+ if ((++ri).state() != valid)
+ return ri;
+ return ri;
+};
+
+
+
+TriaDimensionInfo<2>::line_iterator
+Triangulation<2>::begin_line (unsigned int level) const {
+ // level is checked in begin_raw
+ raw_line_iterator ri = begin_raw_line (level);
+ if (ri.state() != valid)
+ return ri;
+ while (ri->used() == false)
+ if ((++ri).state() != valid)
+ return ri;
+ return ri;
+};
+
+
+
+TriaDimensionInfo<2>::quad_iterator
+Triangulation<2>::begin_quad (unsigned int level) const {
+ // level is checked in begin_raw
+ raw_quad_iterator ri = begin_raw_quad (level);
+ if (ri.state() != valid)
+ return ri;
+ while (ri->used() == false)
+ if ((++ri).state() != valid)
+ return ri;
+ return ri;
+};
+
+
+
+TriaDimensionInfo<1>::active_line_iterator
+Triangulation<1>::begin_active_line (unsigned int level) const {
+ // level is checked in begin_raw
+ line_iterator i = begin_line (level);
+ if (i.state() != valid)
+ return i;
+ while (i->has_children())
+ if ((++i).state() != valid)
+ return i;
+ return i;
+};
+
+
+
+TriaDimensionInfo<2>::active_line_iterator
+Triangulation<2>::begin_active_line (unsigned int level) const {
+ // level is checked in begin_raw
+ line_iterator i = begin_line (level);
+ if (i.state() != valid)
+ return i;
+ while (i->has_children())
+ if ((++i).state() != valid)
+ return i;
+ return i;
+};
+
+
+
+TriaDimensionInfo<2>::active_quad_iterator
+Triangulation<2>::begin_active_quad (unsigned int level) const {
+ // level is checked in begin_raw
+ quad_iterator i = begin(level);
+ if (i.state() != valid)
+ return i;
+ while (i->has_children())
+ if ((++i).state() != valid)
+ return i;
+ return i;
+};
+
+
+
+TriaDimensionInfo<1>::raw_line_iterator
+Triangulation<1>::end_line () const {
+ return raw_line_iterator ((Triangulation<1>*)this,
+ -1,
+ -1);
+};
+
+
+
+TriaDimensionInfo<2>::raw_line_iterator
+Triangulation<2>::end_line () const {
+ return raw_line_iterator ((Triangulation<2>*)this,
+ -1,
+ -1);
+};
+
+
+
+TriaDimensionInfo<2>::raw_quad_iterator
+Triangulation<2>::end_quad () const {
+ return raw_quad_iterator ((Triangulation<2>*)this,
+ -1,
+ -1);
+};
+
+
+
+TriaDimensionInfo<1>::raw_line_iterator
+Triangulation<1>::last_raw_line (const unsigned int level) const {
+ Assert (level<levels.size(),
+ ExcInvalidLevel(level));
+
+ return raw_line_iterator ((Triangulation<1>*)this,
+ level,
+ levels[level]->lines.lines.size()-1);
+};
+
+
+
+TriaDimensionInfo<2>::raw_line_iterator
+Triangulation<2>::last_raw_line (const unsigned int level) const {
+ Assert (level<levels.size(),
+ ExcInvalidLevel(level));
+
+ return raw_line_iterator ((Triangulation<2>*)this,
+ level,
+ levels[level]->lines.lines.size()-1);
+};
+
+
+
+TriaDimensionInfo<2>::raw_quad_iterator
+Triangulation<2>::last_raw_quad (const unsigned int level) const {
+ Assert (level<levels.size(),
+ ExcInvalidLevel(level));
+
+ return raw_quad_iterator ((Triangulation<2>*)this,
+ level,
+ levels[level]->quads.quads.size()-1);
+};
+
+
+
+TriaDimensionInfo<1>::raw_line_iterator
+Triangulation<1>::last_raw_line () const {
+ return last_raw_line (levels.size()-1);
+};
+
+
+
+TriaDimensionInfo<2>::raw_line_iterator
+Triangulation<2>::last_raw_line () const {
+ return last_raw_line (levels.size()-1);
+};
+
+
+
+TriaDimensionInfo<2>::raw_quad_iterator
+Triangulation<2>::last_raw_quad () const {
+ return last_raw_quad (levels.size()-1);
+};
+
+
+
+TriaDimensionInfo<1>::line_iterator
+Triangulation<1>::last_line (const unsigned int level) const {
+ // level is checked in begin_raw
+ raw_line_iterator ri = last_raw_line(level);
+ if (ri->used()==true)
+ return ri;
+ while ((--ri).state() == valid)
+ if (ri->used()==true)
+ return ri;
+ return ri;
+};
+
+
+
+TriaDimensionInfo<2>::line_iterator
+Triangulation<2>::last_line (const unsigned int level) const {
+ // level is checked in begin_raw
+ raw_line_iterator ri = last_raw_line(level);
+ if (ri->used()==true)
+ return ri;
+ while ((--ri).state() == valid)
+ if (ri->used()==true)
+ return ri;
+ return ri;
+};
+
+
+
+TriaDimensionInfo<2>::quad_iterator
+Triangulation<2>::last_quad (const unsigned int level) const {
+ // level is checked in begin_raw
+ raw_quad_iterator ri = last_raw_quad(level);
+ if (ri->used()==true)
+ return ri;
+ while ((--ri).state() == valid)
+ if (ri->used()==true)
+ return ri;
+ return ri;
+};
+
+
+
+TriaDimensionInfo<1>::line_iterator
+Triangulation<1>::last_line () const {
+ return last_line (levels.size()-1);
+};
+
+
+
+TriaDimensionInfo<2>::line_iterator
+Triangulation<2>::last_line () const {
+ return last_line (levels.size()-1);
+};
+
+
+
+TriaDimensionInfo<2>::quad_iterator
+Triangulation<2>::last_quad () const {
+ return last_quad (levels.size()-1);
+};
+
+
+
+TriaDimensionInfo<1>::active_line_iterator
+Triangulation<1>::last_active_line (const unsigned int level) const {
+ // level is checked in begin_raw
+ line_iterator i = last_line(level);
+ if (i->has_children()==false)
+ return i;
+ while ((--i).state() == valid)
+ if (i->has_children()==false)
+ return i;
+ return i;
+};
+
+
+
+TriaDimensionInfo<2>::active_line_iterator
+Triangulation<2>::last_active_line (const unsigned int level) const {
+ // level is checked in begin_raw
+ line_iterator i = last_line(level);
+ if (i->has_children()==false)
+ return i;
+ while ((--i).state() == valid)
+ if (i->has_children()==false)
+ return i;
+ return i;
+};
+
+
+
+TriaDimensionInfo<2>::active_quad_iterator
+Triangulation<2>::last_active_quad (const unsigned int level) const {
+ // level is checked in begin_raw
+ quad_iterator i = last_quad(level);
+ if (i->has_children()==false)
+ return i;
+ while ((--i).state() == valid)
+ if (i->has_children()==false)
+ return i;
+ return i;
+};
+
+
+
+
+TriaDimensionInfo<1>::active_line_iterator
+Triangulation<1>::last_active_line () const {
+ return last_active_line (levels.size()-1);
+};
+
+
+
+TriaDimensionInfo<2>::active_line_iterator
+Triangulation<2>::last_active_line () const {
+ return last_active_line (levels.size()-1);
+};
+
+
+
+TriaDimensionInfo<2>::active_quad_iterator
+Triangulation<2>::last_active_quad () const {
+ return last_active_quad (levels.size()-1);
+};
+
+
+
+
+
+
+
+template <int dim>
+unsigned int Triangulation<dim>::n_cells () const {
+ unsigned int n=0;
+ for (unsigned int l=0; l<levels.size(); ++l)
+ n += n_cells (l);
+ return n;
+};
+
+
+
+unsigned int Triangulation<1>::n_cells (const unsigned int level) const {
+ return n_lines (level);
+};
+
+
+
+unsigned int Triangulation<2>::n_cells (const unsigned int level) const {
+ return n_quads (level);
+};
+
+
+
+template <int dim>
+unsigned int Triangulation<dim>::n_active_cells () const {
+ unsigned int n=0;
+ for (unsigned int l=0; l<levels.size(); ++l)
+ n += n_active_cells (l);
+ return n;
+};
+
+
+
+unsigned int Triangulation<1>::n_active_cells (const unsigned int level) const {
+ return n_active_lines (level);
+};
+
+
+
+unsigned int Triangulation<2>::n_active_cells (const unsigned int level) const {
+ return n_active_quads (level);
+};
+
+
+
+template <int dim>
+unsigned int Triangulation<dim>::n_lines () const {
+ unsigned int n=0;
+ for (unsigned int l=0; l<levels.size(); ++l)
+ n += n_lines (l);
+ return n;
+};
+
+
+
+template <int dim>
+unsigned int Triangulation<dim>::n_lines (const unsigned int level) const {
+ line_iterator line = begin_line (level),
+ endc = (level == levels.size()-1 ?
+ line_iterator(end_line()) :
+ begin_line (level+1));
+ unsigned int n=0;
+ for (; line!=endc; ++line)
+ ++n;
+ return n;
+};
+
+
+
+template <int dim>
+unsigned int Triangulation<dim>::n_active_lines () const {
+ unsigned int n=0;
+ for (unsigned int l=0; l<levels.size(); ++l)
+ n += n_active_lines (l);
+ return n;
+};
+
+
+
+template <int dim>
+unsigned int Triangulation<dim>::n_active_lines (const unsigned int level) const {
+ active_line_iterator line = begin_active_line (level),
+ endc = (level == levels.size()-1 ?
+ active_line_iterator(end_line()) :
+ begin_active_line (level+1));
+ unsigned int n=0;
+ for (; line!=endc; ++line)
+ ++n;
+ return n;
+};
+
+
+
+template <int dim>
+unsigned int Triangulation<dim>::n_quads () const {
+ unsigned int n=0;
+ for (unsigned int l=0; l<levels.size(); ++l)
+ n += n_quads (l);
+ return n;
+};
+
+
+
+unsigned int Triangulation<1>::n_quads (const unsigned int) const {
+ Assert (false, ExcFunctionNotUseful());
+ return 0;
+};
+
+
+
+template <int dim>
+unsigned int Triangulation<dim>::n_quads (const unsigned int level) const {
+ quad_iterator quad = begin_quad (level),
+ endc = (level == levels.size()-1 ?
+ quad_iterator(end_quad()) :
+ begin (level+1));
+ unsigned int n=0;
+ for (; quad!=endc; ++quad)
+ ++n;
+ return n;
+};
+
+
+
+template <int dim>
+unsigned int Triangulation<dim>::n_active_quads () const {
+ unsigned int n=0;
+ for (unsigned int l=0; l<levels.size(); ++l)
+ n += n_active_quads (l);
+ return n;
+};
+
+
+
+unsigned int Triangulation<1>::n_active_quads (const unsigned int) const {
+ Assert (false, ExcFunctionNotUseful());
+ return 0;
+};
+
+
+
+template <int dim>
+unsigned int Triangulation<dim>::n_active_quads (const unsigned int level) const {
+ active_quad_iterator quad = begin_active_quad (level),
+ endc = (level == levels.size()-1 ?
+ active_quad_iterator(end_quad()) :
+ begin_active_quad (level+1));
+ unsigned int n=0;
+ for (; quad!=endc; ++quad)
+ ++n;
+ return n;
+};
+
+
+
+
+template <int dim>
+unsigned int Triangulation<dim>::n_levels () const {
+ return levels.size();
+};
+
+
+
+unsigned int Triangulation<1>::max_adjacent_cells () const {
+ return 2;
+};
+
+
+
+template <int dim>
+unsigned int Triangulation<dim>::max_adjacent_cells () const {
+ cell_iterator cell = begin(0),
+ endc = (levels.size() != 0 ? begin(1) : cell_iterator(end()));
+ // store the largest index of the vertices
+ // used on level 0
+ unsigned int max_vertex_index = 0;
+ for (; cell!=endc; ++cell)
+ for (unsigned vertex=0; vertex<(1<<dim); ++vertex)
+ if (cell->vertex_index(vertex) > (signed int)max_vertex_index)
+ max_vertex_index = cell->vertex_index(vertex);
+
+ // store the number of times a cell touches
+ // a vertex. An unsigned int should suffice,
+ // even for larger dimensions
+ vector<unsigned short int> usage_count (max_vertex_index+1, 0);
+ // touch a vertex's usage count everytime
+ // we find an adjacent element
+ for (cell=begin(); cell!=endc; ++cell)
+ for (unsigned vertex=0; vertex<(1<<dim); ++vertex)
+ ++usage_count[cell->vertex_index(vertex)];
+
+ // use max(.,.) when gcc2.8 is available
+ const unsigned short int max_entry = *(max_element (usage_count.begin(),
+ usage_count.end()));
+ if (max_entry > (1<<dim))
+ return max_entry;
+ else
+ return (1<<dim);
+};
+
+
+
+
+
+template <int dim>
+void Triangulation<dim>::print_gnuplot (ostream &out) const {
+ for (unsigned int i=0; i<levels.size(); ++i)
+ print_gnuplot (out, i);
+};
+
+
+
+template <int dim>
+void Triangulation<dim>::print_gnuplot (ostream &out, const unsigned int level) const {
+ active_cell_iterator cell = begin_active (level),
+ endc = (level == levels.size()-1 ?
+ active_cell_iterator(end()) :
+ begin_active (level+1));
+
+ out << "#Active cells on level " << level
+ << ": " << n_active_cells (level) << endl;
+ for (; cell != endc; ++cell)
+ print_gnuplot (out, cell);
+};
+
+
+
+void Triangulation<1>::print_gnuplot (ostream &out,
+ const TriaDimensionInfo<1>::active_cell_iterator & cell) const {
+ out << cell->vertex(0) << " " << cell->level() << endl
+ << cell->vertex(1) << " " << cell->level() << endl
+ << endl;
+};
+
+
+
+void Triangulation<2>::print_gnuplot (ostream &out,
+ const TriaDimensionInfo<2>::active_cell_iterator & cell) const {
+ out << cell->vertex(0) << " " << cell->level() << endl
+ << cell->vertex(1) << " " << cell->level() << endl
+ << cell->vertex(2) << " " << cell->level() << endl
+ << cell->vertex(3) << " " << cell->level() << endl
+ << cell->vertex(0) << " " << cell->level() << endl
+ << endl // double new line for gnuplot 3d plots
+ << endl;
+};
+
+
+
+void Triangulation<1>::execute_refinement () {
+ prepare_refinement ();
+
+ // check how much space is needed
+ // on every level
+ // we need not check the highest
+ // level since either
+ // - on the highest level no cells
+ // are flagged for refinement
+ // - there are, but prepare_refinement
+ // added another empty level
+ unsigned int needed_vertices = 0;
+ for (int level=levels.size()-2; level>=0; --level)
+ {
+ // count number of flagged cells on
+ // this level
+ unsigned int flagged_cells = 0;
+ active_cell_iterator acell = begin_active(level),
+ aendc = begin_active(level+1);
+ for (; acell!=aendc; ++acell)
+ if (acell->refine_flag_set())
+ ++flagged_cells;
+
+ // count number of used cells on
+ // the next higher level
+ unsigned int used_cells = 0;
+ count_if (levels[level+1]->lines.used.begin(),
+ levels[level+1]->lines.used.end(),
+ bind2nd (equal_to<bool>(), true),
+ used_cells);
+
+ // reserve space for the used_cells
+ // cells already existing on the next
+ // higher level as well as for the
+ // 2*flagged_cells that will be created
+ // on that level
+ levels[level+1]->
+ TriangulationLevel<0>::reserve_space (used_cells+2*flagged_cells, 1);
+ // reserve space for 2*flagged_cells
+ // new lines on the next higher
+ // level
+ levels[level+1]->
+ TriangulationLevel<1>::reserve_space (2*flagged_cells);
+
+ needed_vertices += flagged_cells;
+ };
+
+ // add to needed vertices how
+ // many vertices are already in use
+ count_if (vertices_used.begin(), vertices_used.end(),
+ bind2nd (equal_to<bool>(), true),
+ needed_vertices);
+
+ vertices.reserve (needed_vertices);
+ vertices_used.reserve (needed_vertices);
+ vertices.insert (vertices.end(),
+ needed_vertices-vertices.size(),
+ Point<1>());
+ vertices_used.insert (vertices_used.end(),
+ needed_vertices-vertices_used.size(),
+ false);
+
+
+
+
+ // Do REFINEMENT
+ // on every level; exclude highest level as
+ // above
+
+ // index of next unused vertex
+ unsigned int next_unused_vertex = 0;
+
+ for (int level=levels.size()-2; level>=0; --level)
+ {
+
+ active_cell_iterator cell = begin_active(level),
+ endc = begin_active(level+1);
+
+ raw_cell_iterator next_unused_cell = begin_raw (level+1);
+
+ for (; (cell!=endc) && (cell->level()==level); ++cell)
+ if (cell->refine_flag_set())
+ {
+ // clear refinement flag
+ cell->clear_refine_flag ();
+
+ // search for next unused vertex
+ while (vertices_used[next_unused_vertex] == true)
+ ++next_unused_vertex;
+ Assert (next_unused_vertex < vertices.size(),
+ ExcTooFewVerticesAllocated());
+
+ // first insert new vertex
+ Point<1> new_point = cell->vertex(0);
+ new_point += cell->vertex(1);
+ new_point /= 2.0;
+
+ vertices[next_unused_vertex] = new_point;
+ vertices_used[next_unused_vertex] = true;
+
+ // search for next two unused cell
+ // (++ takes care of the end of
+ // the vector)
+ raw_cell_iterator first_child, second_child;
+ while (next_unused_cell->used() == true)
+ ++next_unused_cell;
+ first_child = next_unused_cell;
+ first_child->set_used_flag ();
+ ++next_unused_cell;
+ Assert (next_unused_cell->used() == false,
+ ExcCellShouldBeUnused());
+ second_child = next_unused_cell;
+ second_child->set_used_flag ();
+
+ // insert first child
+ cell->set_children (first_child->index());
+ first_child->clear_children ();
+ first_child->set (Line (cell->vertex_index(0), next_unused_vertex));
+ // reset neighborship info
+ // (refer to \Ref{TriangulationLevel<0>}
+ // for details)
+ first_child->set_neighbor (1, second_child);
+ if (cell->neighbor(0).state() != valid)
+ first_child->set_neighbor (0, cell->neighbor(0));
+ else
+ if (cell->neighbor(0)->active())
+ // since the neighbors level is
+ // always <=level, if the
+ // cell is active, then there
+ // are no cells to the left which
+ // may want to know about this
+ // new child cell.
+ first_child->set_neighbor (0, cell->neighbor(0));
+ else
+ // left neighbor is refined
+ {
+ // set neighbor to cell on
+ // same level
+ first_child->set_neighbor (0, cell->neighbor(0)->child(1));
+
+ // reset neighbor info of
+ // leftmost descendant of the
+ // left neighbor of cell
+ cell_iterator left_neighbor = cell->neighbor(0);
+ while (left_neighbor->active() == false)
+ left_neighbor = left_neighbor->child(1);
+ left_neighbor->set_neighbor(1, first_child);
+ };
+
+ // insert second child
+ second_child->clear_children ();
+ second_child->set (Line (next_unused_vertex, cell->vertex_index(1)));
+ second_child->set_neighbor (0, first_child);
+ if (cell->neighbor(1).state() != valid)
+ second_child->set_neighbor (1, cell->neighbor(1));
+ else
+ if (cell->neighbor(1)->active)
+ second_child->set_neighbor (1, cell->neighbor(1));
+ else
+ // right neighbor is refined
+ {
+ second_child->set_neighbor (1, cell->neighbor(1)->child(0));
+
+ cell_iterator right_neighbor = cell->neighbor(1);
+ while (right_neighbor->active() == false)
+ right_neighbor = right_neighbor->child(0);
+ right_neighbor->set_neighbor(0, second_child);
+ };
+ };
+ };
+
+#ifdef DEBUG
+ for (unsigned int level=0; level<levels.size(); ++level)
+ levels[level]->monitor_memory (1);
+#endif
+};
+
+
+
+
+
+
+void Triangulation<2>::execute_refinement () {
+ prepare_refinement ();
+
+ // check how much space is needed
+ // on every level
+ // we need not check the highest
+ // level since either
+ // - on the highest level no cells
+ // are flagged for refinement
+ // - there are, but prepare_refinement
+ // added another empty level
+ unsigned int needed_vertices = 0;
+ for (int level=levels.size()-2; level>=0; --level)
+ {
+ // count number of flagged cells on
+ // this level and compute how many
+ // new vertices and new lines will
+ // be needed
+ unsigned int flagged_cells = 0;
+ unsigned int needed_lines = 0;
+ active_cell_iterator acell = begin_active(level),
+ aendc = begin_active(level+1);
+ for (; acell!=aendc; ++acell)
+ if (acell->refine_flag_set())
+ {
+ ++flagged_cells;
+
+ // new vertex at center of cell
+ // is needed in any case
+ ++needed_vertices;
+ // also the four inner lines
+ needed_lines += 4;
+
+ // for all neighbors of
+ // this cell
+ for (unsigned int nb=0; nb<4; ++nb)
+ {
+ cell_iterator neighbor = acell->neighbor(nb);
+ // if cell is at boundary
+ if (neighbor.state() != valid)
+ {
+ // new midpoint vertex
+ // necessary
+ ++needed_vertices;
+ // also two new lines
+ needed_lines += 2;
+
+ continue;
+ };
+ // there is a neighbor. There
+ // are three cases:
+ // 1 nb is on same level and
+ // not refined (subcases:
+ // flagged for refinement
+ // or not)
+ // 2 nb is on same level and
+ // refined (->no additional
+ // vertices and lines needed)
+ // 3 nb is one level down
+ // (but will be refined)
+ if ((neighbor->level() == acell->level()) &&
+ (neighbor->active() == true))
+ {
+ // case 1
+ if (((neighbor->refine_flag_set() == true) &&
+ (acell->index() < neighbor->index()))
+ // case 1a
+ // we need one more vertex
+ // and two more lines, but
+ // we must only count them
+ // once. Convention: count
+ // them for the cell with
+ // the lower index
+ ||
+ (neighbor->refine_flag_set() == false))
+ // case 1b
+ {
+ ++needed_vertices;
+ needed_lines += 2;
+ };
+
+ continue;
+ };
+
+ if ((neighbor->level() == acell->level()) &&
+ (neighbor->active() == false))
+ // case 2
+ continue;
+
+ if (neighbor->level() == acell->level()-1)
+ // case 3
+ {
+ ++needed_vertices;
+ needed_lines += 2;
+
+ continue;
+ };
+
+ Assert (false, ExcUncaughtState());
+ };
+ };
+
+ // count number of used lines on
+ // the next higher level
+ unsigned int used_lines = 0;
+ count_if (levels[level+1]->lines.used.begin(),
+ levels[level+1]->lines.used.end(),
+ bind2nd (equal_to<bool>(), true),
+ used_lines);
+
+ // count number of used cells on
+ // the next higher level
+ unsigned int used_cells = 0;
+ count_if (levels[level+1]->quads.used.begin(),
+ levels[level+1]->quads.used.end(),
+ bind2nd (equal_to<bool>(), true),
+ used_cells);
+
+
+ // reserve space for the used_cells
+ // cells already existing on the next
+ // higher level as well as for the
+ // 4*flagged_cells that will be created
+ // on that level
+ levels[level+1]->
+ TriangulationLevel<0>::reserve_space (used_cells+4*flagged_cells, 2);
+ // reserve space for needed_lines
+ // new lines
+ levels[level+1]->
+ TriangulationLevel<1>::reserve_space (needed_lines);
+ // reserve space for 4*flagged_cells
+ // new lines on the next higher
+ // level
+ levels[level+1]->
+ TriangulationLevel<2>::reserve_space (4*flagged_cells);
+ };
+
+ // add to needed vertices how
+ // many vertices are already in use
+ count_if (vertices_used.begin(), vertices_used.end(),
+ bind2nd (equal_to<bool>(), true),
+ needed_vertices);
+
+ // reserve enough space for all vertices
+ vertices.reserve (needed_vertices);
+ vertices_used.reserve (needed_vertices);
+ vertices.insert (vertices.end(),
+ needed_vertices-vertices.size(),
+ Point<2>());
+ vertices_used.insert (vertices_used.end(),
+ needed_vertices-vertices_used.size(),
+ false);
+
+
+
+
+ // Do REFINEMENT
+ // on every level; exclude highest level as
+ // above
+
+ // index of next unused vertex
+ unsigned int next_unused_vertex = 0;
+
+ for (int level=0; level<(int)levels.size()-1; ++level)
+ {
+
+ active_cell_iterator cell = begin_active(level),
+ endc = begin_active(level+1);
+
+ raw_line_iterator next_unused_line = begin_raw_line (level+1);
+ raw_cell_iterator next_unused_cell = begin_raw (level+1);
+
+ for (; (cell!=endc) && (cell->level()==level); ++cell)
+ if (cell->refine_flag_set())
+ {
+ // clear refinement flag
+ cell->clear_refine_flag ();
+
+
+/* For the refinement process: since we go the levels up from the lowest, there
+ are (unlike above) only two possibilities: a neighbor cell is on the same
+ level or one level up (in both cases, it may or may not be refined later on,
+ but we don't care here).
+
+ First:
+ Set up an array of the 3x3 vertices, which are distributed on the cell
+ (the array consists of indices into the #vertices# vector
+
+ 6--5--4
+ | | |
+ 7--8--3
+ | | |
+ 0--1--2
+
+ Second:
+ Set up an array of the new lines (the array consists of iterator pointers
+ into the lines arrays)
+
+ .-5-.-4-. The directions are: .->-.->-.
+ 6 9 3 ^ ^ ^
+ .-10.11- . .->-.->-.
+ 7 8 2 ^ ^ ^
+ .-0-.-1-. .->-.->-.
+
+ Please note that since the children of line are created in the direction of
+ that line, the lines 4,5 and 6,7 are created in the wrong time order. This
+ has the consequence that if n be the next free line number before the
+ refinement process, the line numbered with 4 above will get index n+5,
+ while the line number 5 above will get the index n+4. The same applies
+ to the lines 6 and 7.
+
+ Third:
+ Set up an array of neighbors:
+
+ 5 4
+ .--.--.
+ 6| | |3
+ .--.--.
+ 7| | |2
+ .--.--.
+ 0 1
+
+ We need this array for two reasons: first to get the lines which will
+ bound the four subcells (if the neighboring cell is refined, these
+ lines already exist), and second to update neighborship information.
+ Since if a neighbor is not refined, its neighborship record only
+ points to the present, unrefined, cell rather than the children we
+ are presently creating, we only need the neighborship information
+ if the neighbor cells are refined. In all other cases, we store
+ the unrefined neighbor address
+
+ We also need for every neighbor (if refined) which number among its
+ neighbors the present (unrefined) cell has, since that number is to
+ be replaced and because that also is the number of the subline which
+ will be the interface between that neighbor and the to be created cell.
+ We will store this number (between 0 and 3) in the field
+ #neighbors_neighbor#.
+
+ It would be sufficient to use the children of the common line to the
+ neighbor, if we only wanted to get the new sublines and the new vertex,
+ but because we need to update the neighborship information of the
+ two refined subcells of the neighbor, we need to search these anyway.
+
+ Convention:
+ The created children are numbered like this:
+
+ .--.--.
+ |3 . 2|
+ .--.--.
+ |0 | 1|
+ .--.--.
+ */
+
+ int new_vertices[9] = {cell->vertex_index(0), -1,
+ cell->vertex_index(1), -1,
+ cell->vertex_index(2), -1,
+ cell->vertex_index(3), -1,
+ -1};
+ raw_line_iterator new_lines[12];
+ cell_iterator neighbors[8] = {cell->neighbor(0),
+ cell->neighbor(0),
+ cell->neighbor(1),
+ cell->neighbor(1),
+ cell->neighbor(2),
+ cell->neighbor(2),
+ cell->neighbor(3),
+ cell->neighbor(3)};
+ int neighbors_neighbor[8] = {-1,-1,-1,-1,-1,-1,-1,-1};
+
+ // remember: the #i#th line
+ // is the common line to the
+ // #i#th neighbor
+ for (unsigned int nb=0; nb<4; ++nb)
+ {
+ bool neighbor_refined=false;
+ if (cell->neighbor(nb).state() == valid)
+ if (cell->neighbor(nb)->active() == false)
+ // (ask in two if-statements,
+ // since otherwise both
+ // conditions would be executed,
+ // but the second will throw an
+ // error if the first fails!)
+ neighbor_refined=true;
+
+ if (neighbor_refined)
+ {
+ // neighbor exists and is
+ // refined
+ // ->the common line has
+ // two children which
+ // we can use.
+ cell_iterator neighbor = cell->neighbor(nb);
+ for (unsigned int nb_nb=0; nb_nb<4; ++nb_nb)
+ if (neighbor->neighbor(nb_nb)==cell)
+ // this cell is the nb_nb-th
+ // neighbor or neighbor(nb)
+ {
+ neighbors_neighbor[2*nb] = neighbors_neighbor[2*nb+1] = nb_nb;
+ // vertex 1 of child 0
+ // is always the interior
+ // one
+ new_vertices[2*nb+1] = neighbor->line(nb_nb)
+ ->child(0)->vertex_index(1);
+
+ if (nb < 2)
+ {
+ new_lines[2*nb] = neighbor->line(nb_nb)->child(0);
+ new_lines[2*nb+1]= neighbor->line(nb_nb)->child(1);
+ } else {
+ // lines 2 and 3 have
+ // opposite sense
+ new_lines[2*nb] = neighbor->line(nb_nb)->child(1);
+ new_lines[2*nb+1]= neighbor->line(nb_nb)->child(0);
+ };
+
+ // finally find out which
+ // are the two neighbor
+ // subcells, adjacent to
+ // the two sublines
+ const int child_mapping[4][2] = {{0,1},{1,2},{3,2},{0,3}};
+ if (nb < 2)
+ {
+ neighbors[2*nb] = neighbor->child(child_mapping[nb_nb][0]);
+ neighbors[2*nb+1]= neighbor->child(child_mapping[nb_nb][1]);
+ } else {
+ neighbors[2*nb] = neighbor->child(child_mapping[nb_nb][1]);
+ neighbors[2*nb+1]= neighbor->child(child_mapping[nb_nb][0]);
+ };
+ };
+ }
+ else
+
+ // neighboring cell either
+ // does not exist or is
+ // not refined -> we need a
+ // new vertex and two new lines
+ {
+ // search for next unused vertex
+ while (vertices_used[next_unused_vertex] == true)
+ ++next_unused_vertex;
+ Assert (next_unused_vertex < vertices.size(),
+ ExcTooFewVerticesAllocated());
+
+ // where shall we put the new
+ // vertex?
+ Point<2> new_point;
+ if (cell->at_boundary(nb))
+ {
+ // boundary vertex
+ const Point<2> *neighbors[2] =
+ {&vertices[new_vertices[2*nb]],
+ &vertices[new_vertices[(2*nb+2)%8]]};
+ new_point = boundary->in_between (neighbors);
+ } else {
+ // vertex between two
+ // normal cells
+ new_point = vertices[new_vertices[2*nb]];
+ new_point += vertices[new_vertices[(2*nb+2)%8]];
+ new_point /= 2.0;
+ };
+
+ new_vertices[nb*2+1] = next_unused_vertex;
+ vertices[new_vertices[nb*2+1]] = new_point;
+ vertices_used[new_vertices[nb*2+1]] = true;
+
+ // search for next unused line
+ // (++ takes care of the end of
+ // the vector)
+ while (next_unused_line->used() == true)
+ ++next_unused_line;
+
+ cell->line(nb)->set_children (next_unused_line->index());
+
+ if (nb<2)
+ {
+ new_lines[nb*2] = next_unused_line;
+ ++next_unused_line;
+ Assert (next_unused_line->used() == false,
+ ExcCellShouldBeUnused());
+ new_lines[nb*2+1] = next_unused_line;
+
+ new_lines[nb*2]->set(Line(new_vertices[2*nb],
+ new_vertices[2*nb+1]));
+ new_lines[nb*2]->set_used_flag ();
+ new_lines[nb*2]->clear_children ();
+
+ new_lines[nb*2+1]->set(Line(new_vertices[2*nb+1],
+ new_vertices[(2*nb+2)%8]));
+ new_lines[nb*2+1]->set_used_flag ();
+ new_lines[nb*2+1]->clear_children ();
+ } else {
+ new_lines[nb*2+1] = next_unused_line;
+ ++next_unused_line;
+ Assert (next_unused_line->used() == false,
+ ExcCellShouldBeUnused());
+ new_lines[nb*2] = next_unused_line;
+
+ new_lines[nb*2]->set(Line(new_vertices[2*nb+1],
+ new_vertices[2*nb]));
+ new_lines[nb*2]->set_used_flag ();
+ new_lines[nb*2]->clear_children ();
+
+ new_lines[nb*2+1]->set(Line(new_vertices[(2*nb+2)%8],
+ new_vertices[2*nb+1]));
+ new_lines[nb*2+1]->set_used_flag ();
+ new_lines[nb*2+1]->clear_children ();
+ };
+ };
+ };
+
+ // add new vertex in the middle
+ // search for next unused
+ // vertex
+ while (vertices_used[next_unused_vertex] == true)
+ ++next_unused_vertex;
+ Assert (next_unused_vertex < vertices.size(),
+ ExcTooFewVerticesAllocated());
+
+ // new vertex is placed at the
+ // arithmetic mean of all 8
+ // neighboring points.
+ Point<2> new_point(0,0);
+ for (unsigned int i=0; i<8; ++i)
+ new_point += vertices[new_vertices[i]];
+ new_point /= 8.0;
+
+ new_vertices[8] = next_unused_vertex;
+ vertices[new_vertices[8]] = new_point;
+ vertices_used[new_vertices[8]] = true;
+
+ // add the 4 inner lines
+
+ // search for next unused line
+ while (next_unused_line->used() == true)
+ ++next_unused_line;
+ new_lines[8] = next_unused_line;
+ new_lines[8]->set(Line(new_vertices[1],
+ new_vertices[8]));
+ new_lines[8]->set_used_flag ();
+ new_lines[8]->clear_children ();
+
+ while (next_unused_line->used() == true)
+ ++next_unused_line;
+ new_lines[9] = next_unused_line;
+ new_lines[9]->set(Line(new_vertices[8],
+ new_vertices[5]));
+ new_lines[9]->set_used_flag ();
+ new_lines[9]->clear_children ();
+
+ while (next_unused_line->used() == true)
+ ++next_unused_line;
+ new_lines[10] = next_unused_line;
+ new_lines[10]->set(Line(new_vertices[7],
+ new_vertices[8]));
+ new_lines[10]->set_used_flag ();
+ new_lines[10]->clear_children ();
+
+ while (next_unused_line->used() == true)
+ ++next_unused_line;
+ new_lines[11] = next_unused_line;
+ new_lines[11]->set(Line(new_vertices[8],
+ new_vertices[3]));
+ new_lines[11]->set_used_flag ();
+ new_lines[11]->clear_children ();
+
+ // finally add the four new cells!
+
+ // search for next unused cell
+ // the four children have to be put
+ // into the array consecutively
+ while (next_unused_cell->used() == true)
+ ++next_unused_cell;
+
+ raw_cell_iterator subcells[4];
+ for (unsigned int i=0; i<4; ++i)
+ {
+ Assert (next_unused_cell->used() == false,
+ ExcCellShouldBeUnused());
+ subcells[i] = next_unused_cell;
+ ++next_unused_cell;
+ };
+
+
+
+ cell->set_children (subcells[0]->index());
+
+ subcells[0]->set (Quad(new_lines[0]->index(), new_lines[8]->index(),
+ new_lines[10]->index(), new_lines[7]->index()));
+ subcells[0]->set_used_flag();
+ subcells[0]->clear_children();
+
+
+ subcells[1]->set (Quad(new_lines[1]->index(), new_lines[2]->index(),
+ new_lines[11]->index(), new_lines[8]->index()));
+ subcells[1]->set_used_flag();
+ subcells[1]->clear_children();
+
+
+ subcells[2]->set (Quad(new_lines[11]->index(), new_lines[3]->index(),
+ new_lines[4]->index(), new_lines[9]->index()));
+ subcells[2]->set_used_flag();
+ subcells[2]->clear_children();
+
+
+ subcells[3]->set (Quad(new_lines[10]->index(), new_lines[9]->index(),
+ new_lines[5]->index(), new_lines[6]->index()));
+ subcells[3]->set_used_flag();
+ subcells[3]->clear_children();
+
+ // finally set neighborship info of
+ // external cells
+ // (neighbor_mapping is the mapping
+ // between the 8 neighbors and the
+ // adjacent new cells in the interior)
+ const int neighbor_mapping[8] = {0,1, 1,2, 2,3, 3,0};
+
+ for (unsigned int nb=0; nb<8; ++nb)
+ if (neighbors[nb].state() == valid)
+ if (neighbors[nb]->level() == level+1)
+ // neighbor is refined cell
+ neighbors[nb]->set_neighbor(neighbors_neighbor[nb],
+ subcells[neighbor_mapping[nb]]);
+
+ // and neighbarship of new cells
+ subcells[0]->set_neighbor (0, neighbors[0]);
+ subcells[0]->set_neighbor (1, subcells[1]);
+ subcells[0]->set_neighbor (2, subcells[3]);
+ subcells[0]->set_neighbor (3, neighbors[7]);
+
+ subcells[1]->set_neighbor (0, neighbors[1]);
+ subcells[1]->set_neighbor (1, neighbors[2]);
+ subcells[1]->set_neighbor (2, subcells[2]);
+ subcells[1]->set_neighbor (3, subcells[0]);
+
+ subcells[2]->set_neighbor (0, subcells[1]);
+ subcells[2]->set_neighbor (1, neighbors[3]);
+ subcells[2]->set_neighbor (2, neighbors[4]);
+ subcells[2]->set_neighbor (3, subcells[3]);
+
+ subcells[3]->set_neighbor (0, subcells[0]);
+ subcells[3]->set_neighbor (1, subcells[2]);
+ subcells[3]->set_neighbor (2, neighbors[5]);
+ subcells[3]->set_neighbor (3, neighbors[6]);
+ };
+ };
+#ifdef DEBUG
+ for (unsigned int level=0; level<levels.size(); ++level)
+ levels[level]->monitor_memory (2);
+#endif
+};
+
+
+
+
+template <int dim>
+void Triangulation<dim>::prepare_refinement () {
+ // make sure no two adjacent active cells
+ // have refinement levels differing
+ // with more than one.
+ // Precondition: on the old grid,
+ // there are no such cells.
+ if (dim>=2)
+ {
+ active_cell_iterator cell = last_active(),
+ endc = end();
+ // loop over active cells
+ for (; cell != endc; --cell)
+ if (cell->refine_flag_set() == true)
+ // loop over neighbors of cell
+ for (unsigned int i=0; i<(2*dim); ++i)
+ if (cell->neighbor(i).state() == valid)
+ if ((cell->neighbor_level(i) == cell->level()-1)
+ &&
+ (cell->neighbor(i)->refine_flag_set() == false))
+ cell->neighbor(i)->set_refine_flag();
+ };
+
+
+ // check whether a new level is needed
+ raw_cell_iterator cell = begin_active (levels.size()-1),
+ endc = end();
+ for (; cell != endc; ++cell)
+ if (cell->refine_flag_set()==true)
+ {
+ levels.push_back (new TriangulationLevel<dim>);
+ return;
+ };
+};
+
+
+
+
+
+void TriangulationLevel<0>::reserve_space (const unsigned int total_cells,
+ const unsigned int dimension) {
+ refine_flags.reserve (total_cells);
+ refine_flags.insert (refine_flags.end(),
+ total_cells - refine_flags.size(),
+ false);
+
+ neighbors.reserve (total_cells*(2*dimension));
+ neighbors.insert (neighbors.end(),
+ total_cells*(2*dimension) - neighbors.size(),
+ make_pair(-1,-1));
+};
+
+
+
+
+void TriangulationLevel<0>::monitor_memory (const unsigned int true_dimension) const {
+ Assert (refine_flags.size() == refine_flags.capacity() ||
+ refine_flags.size()<256,
+ ExcMemoryWasted ("refine_flags",
+ refine_flags.size(), refine_flags.capacity()));
+ Assert (neighbors.size() == neighbors.capacity() ||
+ neighbors.size()<256,
+ ExcMemoryWasted ("neighbors",
+ neighbors.size(), neighbors.capacity()));
+ Assert (2*true_dimension*refine_flags.size() == neighbors.size(),
+ ExcMemoryInexact (refine_flags.size(), neighbors.size()));
+};
+
+
+
+void TriangulationLevel<1>::reserve_space (const unsigned int new_lines) {
+ vector<bool>::iterator u = lines.used.begin(),
+ e = lines.used.end();
+
+ unsigned int used_lines = 0;
+ for (; u!=e; ++u)
+ ++used_lines;
+
+ unsigned int new_size = used_lines + new_lines;
+
+ lines.lines.reserve (new_size);
+ lines.lines.insert (lines.lines.end(), new_size-lines.lines.size(), Line());
+
+ lines.used.reserve (new_size);
+ lines.used.insert (lines.used.end(), new_size-lines.used.size(), false);
+
+ lines.user_flags.reserve (new_size);
+ lines.user_flags.insert (lines.user_flags.end(), new_size-lines.user_flags.size(), false);
+
+ lines.children.reserve (new_size);
+ lines.children.insert (lines.children.end(), new_size-lines.children.size(),
+ -1);
+};
+
+
+
+
+void TriangulationLevel<1>::monitor_memory (const unsigned int true_dimension) const {
+ Assert (lines.lines.size() == lines.lines.capacity() ||
+ lines.lines.size()<256,
+ ExcMemoryWasted ("lines",
+ lines.lines.size(), lines.lines.capacity()));
+ Assert (lines.children.size() == lines.children.capacity() ||
+ lines.children.size()<256,
+ ExcMemoryWasted ("children",
+ lines.children.size(), lines.children.capacity()));
+ Assert (lines.used.size() == lines.used.capacity() ||
+ lines.used.size()<256,
+ ExcMemoryWasted ("used",
+ lines.used.size(), lines.used.capacity()));
+ Assert (lines.user_flags.size() == lines.user_flags.capacity() ||
+ lines.user_flags.size()<256,
+ ExcMemoryWasted ("user_flags",
+ lines.user_flags.size(), lines.user_flags.capacity()));
+ Assert (lines.lines.size() == lines.used.size(),
+ ExcMemoryInexact (lines.lines.size(), lines.used.size()));
+ Assert (lines.lines.size() == lines.user_flags.size(),
+ ExcMemoryInexact (lines.lines.size(), lines.user_flags.size()));
+ Assert (lines.lines.size() == lines.children.size(),
+ ExcMemoryInexact (lines.lines.size(), lines.children.size()));
+ Assert (lines.used[lines.used.size()-1]==true ,
+ ExcUnusedMemoryAtEnd());
+
+ TriangulationLevel<0>::monitor_memory (true_dimension);
+};
+
+
+
+void TriangulationLevel<2>::reserve_space (const unsigned int new_quads) {
+ vector<bool>::iterator u = quads.used.begin(),
+ e = quads.used.end();
+
+ unsigned int used_quads = 0;
+ for (; u!=e; ++u)
+ ++used_quads;
+
+ unsigned int new_size = used_quads + new_quads;
+
+ quads.quads.reserve (new_size);
+ quads.quads.insert (quads.quads.end(), new_size-quads.quads.size(), Quad());
+
+ quads.used.reserve (new_size);
+ quads.used.insert (quads.used.end(), new_size-quads.used.size(), false);
+
+ quads.user_flags.reserve (new_size);
+ quads.user_flags.insert (quads.user_flags.end(), new_size-quads.user_flags.size(), false);
+
+ quads.children.reserve (new_size);
+ quads.children.insert (quads.children.end(), new_size-quads.children.size(),
+ -1);
+};
+
+
+
+void TriangulationLevel<2>::monitor_memory (const unsigned int true_dimension) const {
+ Assert (quads.quads.size() == quads.quads.capacity() ||
+ quads.quads.size()<256,
+ ExcMemoryWasted ("quads",
+ quads.quads.size(), quads.quads.capacity()));
+ Assert (quads.children.size() == quads.children.capacity() ||
+ quads.children.size()<256,
+ ExcMemoryWasted ("children",
+ quads.children.size(), quads.children.capacity()));
+ Assert (quads.used.size() == quads.used.capacity() ||
+ quads.used.size()<256,
+ ExcMemoryWasted ("used",
+ quads.used.size(), quads.used.capacity()));
+ Assert (quads.user_flags.size() == quads.user_flags.capacity() ||
+ quads.user_flags.size()<256,
+ ExcMemoryWasted ("user_flags",
+ quads.user_flags.size(), quads.user_flags.capacity()));
+ Assert (quads.quads.size() == quads.used.size(),
+ ExcMemoryInexact (quads.quads.size(), quads.used.size()));
+ Assert (quads.quads.size() == quads.user_flags.size(),
+ ExcMemoryInexact (quads.quads.size(), quads.user_flags.size()));
+ Assert (quads.quads.size() == quads.children.size(),
+ ExcMemoryInexact (quads.quads.size(), quads.children.size()));
+ Assert (quads.used[quads.used.size()-1]==true ,
+ ExcUnusedMemoryAtEnd());
+
+ TriangulationLevel<1>::monitor_memory (true_dimension);
+};
+
+
+
+
+
+
+// explicit instantiations
+template class Triangulation<1>;
+template class Triangulation<2>;
+
--- /dev/null
+/* $Id$ */
+
+#include <grid/tria.h>
+#include <grid/tria_iterator.h>
+#include <grid/tria_accessor.h>
+#include <grid/tria_iterator.templates.h>
+
+/* Note: explicit instantiations at the end of the different sections! */
+
+
+
+/*------------------------ Functions: LineAccessor ---------------------------*/
+
+template <int dim>
+void TriaAccessor<dim>::copy_from (const TriaAccessor<dim> &a) {
+ present_level = a.present_level;
+ present_index = a.present_index;
+ tria = a.tria;
+};
+
+
+
+template <int dim>
+bool TriaAccessor<dim>::operator == (const TriaAccessor<dim> &a) const {
+ return ((present_level == a.present_level) &&
+ (present_index == a.present_index) &&
+ (tria == a.tria));
+};
+
+
+
+template <int dim>
+bool TriaAccessor<dim>::operator != (const TriaAccessor<dim> &a) const {
+ return ((present_level != a.present_level) ||
+ (present_index != a.present_index) ||
+ (tria != a.tria));
+};
+
+
+
+template <int dim>
+int TriaAccessor<dim>::level () const {
+ return present_level;
+};
+
+
+
+template <int dim>
+int TriaAccessor<dim>::index () const {
+ return present_index;
+};
+
+
+
+
+template <int dim>
+IteratorState TriaAccessor<dim>::state () const {
+ if ((present_level>=0) && (present_index>=0))
+ return valid;
+ else
+ if ((present_level==-1) && (present_index==-1))
+ return past_the_end;
+ else
+ return invalid;
+};
+
+
+
+
+
+template class TriaAccessor<1>;
+template class TriaAccessor<2>;
+
+
+
+
+/*------------------------ Functions: LineAccessor ---------------------------*/
+
+template <int dim>
+void LineAccessor<dim>::set (const Line &line) const {
+ tria->levels[present_level]->lines.lines[present_index] = line;
+};
+
+
+
+template <int dim>
+int LineAccessor<dim>::vertex_index (const unsigned int i) const {
+ Assert (i<2, ExcInvalidIndex(i,0,1));
+ return tria->levels[present_level]->lines.lines[present_index].vertex (i);
+};
+
+
+
+template <int dim>
+Point<dim> &
+LineAccessor<dim>::vertex (const unsigned int i) const {
+ return tria->vertices[vertex_index(i)];
+};
+
+
+
+template <int dim>
+bool LineAccessor<dim>::used () const {
+ Assert (state() == valid, ExcDereferenceInvalidObject());
+ return tria->levels[present_level]->lines.used[present_index];
+};
+
+
+
+template <int dim>
+void LineAccessor<dim>::set_used_flag () const {
+ Assert (state() == valid, ExcDereferenceInvalidObject());
+ tria->levels[present_level]->lines.used[present_index] = true;
+};
+
+
+
+template <int dim>
+void LineAccessor<dim>::clear_used_flag () const {
+ Assert (state() == valid, ExcDereferenceInvalidObject());
+ tria->levels[present_level]->lines.used[present_index] = false;
+};
+
+
+template <int dim>
+bool LineAccessor<dim>::user_flag_set () const {
+ Assert (used(), ExcRefineCellNotActive());
+ return tria->levels[present_level]->lines.user_flags[present_index];
+};
+
+
+
+template <int dim>
+void LineAccessor<dim>::set_user_flag () const {
+ Assert (used(), ExcCellNotUsed());
+ tria->levels[present_level]->lines.user_flags[present_index] = true;
+};
+
+
+
+template <int dim>
+void LineAccessor<dim>::clear_user_flag () const {
+ Assert (used(), ExcCellNotUsed());
+ tria->levels[present_level]->lines.user_flags[present_index] = false;
+};
+
+
+
+template <int dim>
+TriaIterator<dim,LineAccessor<dim> >
+LineAccessor<dim>::child (const unsigned int i) const {
+ Assert (i<2, ExcInvalidIndex(i,0,1));
+
+ TriaIterator<dim,LineAccessor<dim> > q (tria, present_level+1, child_index (i));
+
+#ifdef DEBUG
+ if (q.state() != past_the_end)
+ Assert (q->used(), ExcUnusedCellAsChild());
+#endif
+ return q;
+};
+
+
+template <int dim>
+int LineAccessor<dim>::child_index (unsigned int i) const {
+ Assert (i<2, ExcInvalidIndex(i,0,1));
+ return tria->levels[present_level]->lines.children[present_index]+i;
+};
+
+
+
+
+template <int dim>
+void LineAccessor<dim>::set_children (const int index) const {
+ Assert (used(), ExcRefineCellNotUsed());
+ tria->levels[present_level]->lines.children[present_index] = index;
+};
+
+
+
+template <int dim>
+void LineAccessor<dim>::clear_children () const {
+ set_children (-1);
+};
+
+
+
+template <int dim>
+bool LineAccessor<dim>::has_children () const {
+ Assert (state() == valid, ExcDereferenceInvalidObject());
+ return (tria->levels[present_level]->lines.children[present_index] != -1);
+}
+
+
+
+template <int dim>
+void LineAccessor<dim>::operator ++ () {
+ ++present_index;
+ // is index still in the range of
+ // the vector?
+ while (present_index
+ >=
+ (int)tria->levels[present_level]->lines.lines.size())
+ {
+ // no -> go one level up until we find
+ // one with more than zero cells
+ ++present_level;
+ present_index = 0;
+ // highest level reached?
+ if (present_level >= (int)tria->levels.size())
+ {
+ // return with past the end pointer
+ present_level = present_index = -1;
+ return;
+ };
+ };
+};
+
+
+
+template <int dim>
+void LineAccessor<dim>::operator -- () {
+ --present_index;
+ // is index still in the range of
+ // the vector?
+ while (present_index < 0)
+ {
+ // no -> go one level down
+ --present_level;
+ // lowest level reached?
+ if (present_level == -1)
+ {
+ // return with past the end pointer
+ present_level = present_index = -1;
+ return;
+ };
+ // else
+ present_index = tria->levels[present_level]->lines.lines.size()-1;
+ };
+};
+
+
+
+
+template class LineAccessor<1>;
+template class LineAccessor<2>;
+
+
+/*------------------------ Functions: QuadAccessor ---------------------------*/
+
+template <int dim>
+void QuadAccessor<dim>::set (const Quad &quad) const {
+ tria->levels[present_level]->quads.quads[present_index] = quad;
+};
+
+
+
+template <int dim>
+int QuadAccessor<dim>::vertex_index (const unsigned int corner) const {
+ Assert (corner<4, ExcInvalidIndex(corner,0,3));
+
+ const int corner_convention[4] = { 0,0,1,1 };
+ return line(corner)->vertex_index(corner_convention[corner]);
+};
+
+
+
+template <int dim>
+Point<dim> &
+QuadAccessor<dim>::vertex (const unsigned int i) const {
+ return tria->vertices[vertex_index(i)];
+};
+
+
+
+template <int dim>
+bool QuadAccessor<dim>::used () const {
+ Assert (state() == valid, ExcDereferenceInvalidObject());
+ return tria->levels[present_level]->quads.used[present_index];
+};
+
+
+
+template <int dim>
+void QuadAccessor<dim>::set_used_flag () const {
+ Assert (state() == valid, ExcDereferenceInvalidObject());
+ tria->levels[present_level]->quads.used[present_index] = true;
+};
+
+
+
+template <int dim>
+void QuadAccessor<dim>::clear_used_flag () const {
+ Assert (state() == valid, ExcDereferenceInvalidObject());
+ tria->levels[present_level]->quads.used[present_index] = false;
+};
+
+
+
+
+template <int dim>
+bool QuadAccessor<dim>::user_flag_set () const {
+ Assert (used(), ExcRefineCellNotActive());
+ return tria->levels[present_level]->quads.user_flags[present_index];
+};
+
+
+
+template <int dim>
+void QuadAccessor<dim>::set_user_flag () const {
+ Assert (used(), ExcCellNotUsed());
+ tria->levels[present_level]->quads.user_flags[present_index] = true;
+};
+
+
+
+template <int dim>
+void QuadAccessor<dim>::clear_user_flag () const {
+ Assert (used(), ExcCellNotUsed());
+ tria->levels[present_level]->quads.user_flags[present_index] = false;
+};
+
+
+
+
+template <int dim>
+TriaIterator<dim,LineAccessor<dim> >
+QuadAccessor<dim>::line (const unsigned int i) const {
+ return
+ TriaIterator<dim,LineAccessor<dim> >
+ (
+ tria,
+ present_level,
+ line_index (i)
+ );
+};
+
+
+
+template <int dim>
+unsigned int QuadAccessor<dim>::line_index (unsigned int i) const {
+ Assert (i<4, ExcInvalidIndex(i,0,3));
+
+ return tria->levels[present_level]->quads.quads[present_index].line(i);
+};
+
+
+
+template <int dim>
+TriaIterator<dim,QuadAccessor<dim> >
+QuadAccessor<dim>::child (const unsigned int i) const {
+ Assert (i<4, ExcInvalidIndex(i,0,3));
+
+ TriaIterator<2,QuadAccessor<dim> > q (tria, present_level+1, child_index (i));
+
+#ifdef DEBUG
+ if (q.state() != past_the_end)
+ Assert (q->used(), ExcUnusedCellAsChild());
+#endif
+ return q;
+};
+
+
+
+template <int dim>
+int QuadAccessor<dim>::child_index (unsigned int i) const {
+ Assert (i<4, ExcInvalidIndex(i,0,3));
+ return tria->levels[present_level]->quads.children[present_index]+i;
+};
+
+
+
+template <int dim>
+void QuadAccessor<dim>::set_children (const int index) const {
+ Assert (used(), ExcRefineCellNotUsed());
+ tria->levels[present_level]->quads.children[present_index] = index;
+};
+
+
+
+template <int dim>
+void QuadAccessor<dim>::clear_children () const {
+ set_children (-1);
+};
+
+
+
+template <int dim>
+bool QuadAccessor<dim>::has_children () const {
+ Assert (state() == valid, ExcDereferenceInvalidObject());
+ return (tria->levels[present_level]->quads.children[present_index] != -1);
+};
+
+
+
+template <int dim>
+void QuadAccessor<dim>::operator ++ () {
+ ++present_index;
+ // is index still in the range of
+ // the vector?
+ while (present_index
+ >=
+ (int)tria->levels[present_level]->quads.quads.size())
+ {
+ // no -> go one level up
+ ++present_level;
+ present_index = 0;
+ // highest level reached?
+ if (present_level >= (int)tria->levels.size())
+ {
+ // return with past the end pointer
+ present_level = present_index = -1;
+ return;
+ };
+ };
+};
+
+
+
+template <int dim>
+void QuadAccessor<dim>::operator -- () {
+ --present_index;
+ // is index still in the range of
+ // the vector?
+ while (present_index < 0)
+ {
+ // no -> go one level down
+ --present_level;
+ // lowest level reached?
+ if (present_level == -1)
+ {
+ // return with past the end pointer
+ present_level = present_index = -1;
+ return;
+ };
+ // else
+ present_index = tria->levels[present_level]->quads.quads.size()-1;
+ };
+};
+
+
+
+
+template class QuadAccessor<2>;
+
+
+
+/*------------------------ Functions: CellAccessor<dim> ---------------------*/
+
+template <int dim>
+int CellAccessor<dim>::neighbor_index (const unsigned int i) const {
+ Assert (i<2*dim, ExcInvalidNeighbor(i));
+ return tria->levels[present_level]->neighbors[present_index*2*dim+i].second;
+};
+
+
+
+template <int dim>
+int CellAccessor<dim>::neighbor_level (const unsigned int i) const {
+ Assert (i<2*dim, ExcInvalidNeighbor(i));
+ return tria->levels[present_level]->neighbors[present_index*2*dim+i].first;
+};
+
+
+
+template <int dim>
+void CellAccessor<dim>::set_neighbor (const unsigned int i,
+ const TriaIterator<dim,CellAccessor<dim> > &pointer) const {
+ Assert (i<2*dim, ExcInvalidNeighbor(i));
+ tria->levels[present_level]->neighbors[present_index*2*dim+i].first
+ = pointer.accessor.present_level;
+ tria->levels[present_level]->neighbors[present_index*2*dim+i].second
+ = pointer.accessor.present_index;
+};
+
+
+
+template <int dim>
+bool CellAccessor<dim>::at_boundary (const unsigned int i) const {
+ Assert (used(), ExcCellNotUsed());
+ Assert (i<2*dim, ExcInvalidIndex (i,0,2*dim-1));
+
+ return (neighbor(i).state() != valid);
+};
+
+
+
+template <int dim>
+bool CellAccessor<dim>::refine_flag_set () const {
+ Assert (used() && active(), ExcRefineCellNotActive());
+ return tria->levels[present_level]->refine_flags[present_index];
+};
+
+
+
+template <int dim>
+void CellAccessor<dim>::set_refine_flag () const {
+ Assert (used() && active(), ExcRefineCellNotActive());
+ tria->levels[present_level]->refine_flags[present_index] = true;
+};
+
+
+
+template <int dim>
+void CellAccessor<dim>::clear_refine_flag () const {
+ Assert (used() && active(), ExcRefineCellNotActive());
+ tria->levels[present_level]->refine_flags[present_index] = false;
+};
+
+
+
+template <int dim>
+TriaIterator<dim,CellAccessor<dim> >
+CellAccessor<dim>::neighbor (const unsigned int i) const {
+ TriaIterator<dim,CellAccessor<dim> > q (tria, neighbor_level (i), neighbor_index (i));
+
+#ifdef DEBUG
+ if (q.state() != past_the_end)
+ Assert (q->used(), ExcUnusedCellAsNeighbor());
+#endif
+ return q;
+};
+
+
+
+template <int dim>
+TriaIterator<dim,CellAccessor<dim> >
+CellAccessor<dim>::child (const unsigned int i) const {
+ TriaIterator<dim,CellAccessor<dim> > q (tria, present_level+1, child_index (i));
+
+#ifdef DEBUG
+ if (q.state() != past_the_end)
+ Assert (q->used(), ExcUnusedCellAsChild());
+#endif
+ return q;
+};
+
+
+
+template <int dim>
+bool CellAccessor<dim>::active () const {
+ return !has_children();
+};
+
+
+
+/*------------------------ Functions: CellAccessor<1> -----------------------*/
+
+
+bool CellAccessor<1>::at_boundary () const {
+ return at_boundary(0) || at_boundary(1);
+};
+
+
+
+
+/*------------------------ Functions: CellAccessor<2> -----------------------*/
+
+
+bool CellAccessor<2>::at_boundary () const {
+ return at_boundary(0) || at_boundary(1) || at_boundary(2) || at_boundary(3);
+};
+
+
+
+
+
+
+
+
+
+
+
+// explicit instantiations
+template class CellAccessor<1>;
+template class CellAccessor<2>;
+
+template class TriaRawIterator<1,LineAccessor<1> >;
+template class TriaRawIterator<1,CellAccessor<1> >;
+template class TriaRawIterator<2,LineAccessor<2> >;
+template class TriaRawIterator<2,QuadAccessor<2> >;
+template class TriaRawIterator<2,CellAccessor<2> >;
+
+template class TriaIterator<1,LineAccessor<1> >;
+template class TriaIterator<1,CellAccessor<1> >;
+template class TriaIterator<2,LineAccessor<2> >;
+template class TriaIterator<2,QuadAccessor<2> >;
+template class TriaIterator<2,CellAccessor<2> >;
+
+template class TriaActiveIterator<1,LineAccessor<1> >;
+template class TriaActiveIterator<1,CellAccessor<1> >;
+template class TriaActiveIterator<2,LineAccessor<2> >;
+template class TriaActiveIterator<2,QuadAccessor<2> >;
+template class TriaActiveIterator<2,CellAccessor<2> >;
+
+
--- /dev/null
+# $Id$
+
+CXX =c++
+CXXFLAGS.g=-DDEBUG -g -Wall -pedantic -Wconversion -Winline -Woverloaded-virtual -I../../include
+CXXFLAGS =-O3 -Wuninitialized -finline-functions -ffast-math -funroll-loops -felide-constructors -fnonnull-objects -I../../include
+
+ifeq ($(shell uname),SunOS)
+CXXFLAGS := -V2.7.2.3 $(CXXFLAGS)
+CXXFLAGS.g:= -V2.7.2.3 $(CXXFLAGS.g)
+endif
+
+
+cc-files = $(wildcard *.cc)
+o-files = $(cc-files:.cc=.o)
+go-files = $(cc-files:.cc=.go)
+h-files = $(wildcard ../include/*/*.h)
+
+
+%.go : %.cc
+ @echo ============================ Compiling with debugging information: $<
+ @echo $(CXX) ... -c $< -o $@
+ @$(CXX) $(CXXFLAGS.g) -c $< -o $@
+%.o : %.cc
+ @echo ============================ Compiling with optimization: $<
+ @echo $(CXX) ... -c $< -o $@
+ @$(CXX) $(CXXFLAGS) -c $< -o $@
+
+
+lib: lib.g.a lib.a
+
+lib.a: ../../lib/libbasic.a($(o-files))
+
+lib.g.a: ../../lib/libbasic.g.a($(go-files))
+
+clean:
+ rm -f *.o *.go *~ Makefile.dep
+
+
+
+.PHONY: lib lib.a lib.g.a clean
+
+
+#Rule to generate the dependency file. This file is
+#automagically remade whenever needed, i.e. whenever
+#one of the cc-/h-files changed. Make detects whether
+#to remake this file upon inclusion at the bottom
+#of this file.
+#
+#use perl to generate rules for the .go files as well
+#as to make rules not for tria.o and the like, but
+#rather for libbasic.a(tria.o)
+Makefile.dep: $(cc-files) $(h-files)
+ @echo ============================ Remaking Makefile
+ @$(CXX) -I../../include -DDEBUG -M *.cc > Makefile.dep.o
+ @cp Makefile.dep.o Makefile.dep.go
+ @perl -pi -e 's!^(.*\.o):!../../lib/libbasic.a(\1):!g' Makefile.dep.o
+ @perl -pi -e 's!\.o:!.go:!g' Makefile.dep.go
+ @perl -pi -e 's!^(.*\.go):!../../lib/libbasic.g.a(\1):!g' Makefile.dep.go
+ @cat Makefile.dep.o Makefile.dep.go > Makefile.dep
+ @rm Makefile.dep.o Makefile.dep.go
+
+include Makefile.dep
--- /dev/null
+/* $Id$ */
+
+#include <numerics/assembler.h>
+#include <numerics/base.h>
+#include <grid/tria_iterator.h>
+#include "../../deal/dfmatrix.h"
+#include "../../deal/dvector.h"
+
+
+extern TriaIterator<1,CellAccessor<1> > __dummy127; // do this to calm down gcc2.7,
+extern TriaIterator<2,CellAccessor<2> > __dummy128; // wait for gcc2.8
+
+
+template <int dim>
+Equation<dim>::Equation (const unsigned int n_equations) :
+ n_eq(n_equations) {};
+
+
+
+void Equation<1>::assemble (dFMatrix &,
+ vector<dVector> &,
+ const FEValues<1> &,
+ const Triangulation<1>::cell_iterator &) const {
+ Assert (false, ExcPureVirtualFunctionCalled());
+};
+
+
+
+void Equation<2>::assemble (dFMatrix &,
+ vector<dVector> &,
+ const FEValues<2> &,
+ const Triangulation<2>::cell_iterator &) const {
+ Assert (false, ExcPureVirtualFunctionCalled());
+};
+
+
+
+void Equation<1>::assemble (dFMatrix &,
+ const FEValues<1> &,
+ const Triangulation<1>::cell_iterator &) const {
+ Assert (false, ExcPureVirtualFunctionCalled());
+};
+
+
+
+void Equation<2>::assemble (dFMatrix &,
+ const FEValues<2> &,
+ const Triangulation<2>::cell_iterator &) const {
+ Assert (false, ExcPureVirtualFunctionCalled());
+};
+
+
+
+void Equation<1>::assemble (vector<dVector> &,
+ const FEValues<1> &,
+ const Triangulation<1>::cell_iterator &) const {
+ Assert (false, ExcPureVirtualFunctionCalled());
+};
+
+
+
+void Equation<2>::assemble (vector<dVector> &,
+ const FEValues<2> &,
+ const Triangulation<2>::cell_iterator &) const {
+ Assert (false, ExcPureVirtualFunctionCalled());
+};
+
+
+
+
+template <int dim>
+Assembler<dim>::Assembler (Triangulation<dim> *tria,
+ const int level,
+ const int index,
+ const void *local_data) :
+ DoFCellAccessor<dim> (tria,level,index,
+ ((AssemblerData*)local_data)->dof),
+ cell_matrix (dof_handler->get_selected_fe().total_dofs),
+ cell_vectors (((AssemblerData*)local_data)->n_rhs,
+ dVector(dof_handler->get_selected_fe().total_dofs)),
+ assemble_matrix (((AssemblerData*)local_data)->assemble_matrix),
+ assemble_rhs (((AssemblerData*)local_data)->assemble_rhs),
+ problem (((AssemblerData*)local_data)->problem),
+ fe_values (dof_handler->get_selected_fe(),
+ *((AssemblerData*)local_data)->quadrature)
+{
+ Assert (((AssemblerData*)local_data)->dof != 0,
+ ExcInvalidData());
+ Assert (((AssemblerData*)local_data)->n_rhs != 0,
+ ExcInvalidData());
+ Assert (((AssemblerData*)local_data)->problem != 0,
+ ExcInvalidData());
+
+ Assert ((unsigned int)problem->system_matrix.m() == dof_handler->n_dofs(),
+ ExcInvalidData());
+ Assert ((unsigned int)problem->system_matrix.n() == dof_handler->n_dofs(),
+ ExcInvalidData());
+ Assert (problem->right_hand_sides.size() == cell_vectors.size(),
+ ExcInvalidData());
+ for (unsigned int i=0; i<cell_vectors.size(); ++i)
+ Assert ((unsigned int)problem->right_hand_sides[i]->n() == dof_handler->n_dofs(),
+ ExcInvalidData());
+};
+
+
+
+template <int dim>
+void Assembler<dim>::assemble (const Equation<dim> &equation) {
+ // re-init fe values for this cell
+ fe_values.reinit (Triangulation<dim>::cell_iterator (tria,
+ present_level,
+ present_index),
+ dof_handler->get_selected_fe());
+
+ if (assemble_matrix)
+ // clear cell matrix
+ for (unsigned int i=0; i<dof_handler->get_selected_fe().total_dofs; ++i)
+ for (unsigned int j=0; j<dof_handler->get_selected_fe().total_dofs; ++j)
+ cell_matrix(i,j) = 0;
+
+
+ if (assemble_rhs)
+ // clear cell vector
+ for (unsigned int vec=0; vec<cell_vectors.size(); ++vec)
+ for (unsigned int j=0; j<dof_handler->get_selected_fe().total_dofs; ++j)
+ cell_vectors[vec](j) = 0;
+
+
+ // fill cell matrix and vector if required
+ if (assemble_matrix && assemble_rhs)
+ equation.assemble (cell_matrix, cell_vectors, fe_values,
+ Triangulation<dim>::cell_iterator(tria,
+ present_level,
+ present_index));
+ else
+ if (assemble_matrix)
+ equation.assemble (cell_matrix, fe_values,
+ Triangulation<dim>::cell_iterator(tria,
+ present_level,
+ present_index));
+ else
+ if (assemble_rhs)
+ equation.assemble (cell_vectors, fe_values,
+ Triangulation<dim>::cell_iterator(tria,
+ present_level,
+ present_index));
+ else
+ Assert (false, ExcNoAssemblingRequired());
+
+
+ // get indices of dofs
+ vector<int> dofs;
+ dof_indices (dofs);
+
+ if (assemble_matrix)
+ // distribute cell matrix
+ for (unsigned int i=0; i<dof_handler->get_selected_fe().total_dofs; ++i)
+ for (unsigned int j=0; j<dof_handler->get_selected_fe().total_dofs; ++j)
+ problem->system_matrix.set(dofs[i], dofs[j], cell_matrix(i,j));
+
+ if (assemble_rhs)
+ // distribute cell vector
+ for (unsigned int vec=0; vec<cell_vectors.size(); ++vec)
+ for (unsigned int j=0; j<dof_handler->get_selected_fe().total_dofs; ++j)
+ (*problem->right_hand_sides[vec])(dofs[j]) = cell_vectors[vec](j);
+};
+
+
+
+
+
+// explicit instantiations
+template class Equation<1>;
+template class Equation<2>;
+
+template class Assembler<1>;
+template class Assembler<2>;
--- /dev/null
+/* $Id$ */
+
+#include <numerics/assembler.h>
+#include <numerics/base.h>
+
+
+
+template <int dim>
+ProblemBase<dim>::ProblemBase (Triangulation<dim> *tria,
+ DoFHandler<dim> *dof) :
+ tria(tria), dof_handler(dof) {};
+
+
+
+
+template <int dim>
+void ProblemBase<dim>::assemble (const Equation<dim> &equation,
+ const Quadrature<dim> &quadrature) {
+ ConstraintMatrix constraints;
+
+ system_sparsity.reinit (dof_handler->n_dofs(),
+ dof_handler->n_dofs(),
+ dof_handler->max_coupling_between_dofs());
+
+ dof_handler->make_constraint_matrix (constraints);
+ dof_handler->make_sparsity_pattern (system_sparsity);
+ constraints.condense (system_sparsity);
+
+ system_matrix.reinit (system_sparsity);
+
+ Assembler<dim>::AssemblerData data = {dof_handler,
+ true, true,
+ 1,
+ this,
+ &quadrature};
+
+ TriaActiveIterator<Assembler<dim> > assembler (tria,
+ tria->begin_active()->level(),
+ tria->begin_active()->index(),
+ &data);
+
+ do
+ {
+ assembler->assemble (equation);
+ }
+ while ((++assembler).state() == valid);
+};
--- /dev/null
+/* $Id$ */
+
+#include <basic/data_io.h>
+#include <grid/dof.h>
+#include <grid/dof_accessor.h>
+#include <grid/tria_iterator.h>
+#include <grid/tria.h>
+#include <iostream.h>
+#include <algo.h>
+#include <time.h>
+
+
+extern TriaActiveIterator<1,DoFCellAccessor<1> > __dummy566; // wait for gcc2.8
+extern TriaActiveIterator<2,DoFCellAccessor<2> > __dummy567;
+
+
+template <int dim>
+DataOut<dim>::DataOut () :
+ dofs(0) {};
+
+
+
+template <int dim>
+void DataOut<dim>::attach_dof_handler (DoFHandler<dim> &d) {
+ dofs = &d;
+};
+
+
+
+template <int dim>
+void DataOut<dim>::add_data_vector (dVector &vec,
+ String &name,
+ String &units) {
+ DataEntry new_entry = {&vec, name, units};
+ data.push_back (new_entry);
+};
+
+
+
+template <int dim>
+void DataOut<dim>::clear_data_vectors () {
+ data.erase (data.begin(), data.end());
+};
+
+
+
+template <int dim>
+void DataOut<dim>::write_ucd (ostream &out) const {
+ Assert (dofs != 0, ExcNoDoFHandlerSelected());
+ Assert (dofs->get_selected_fe().dofs_per_vertex==1,
+ ExcIncorrectDofsPerVertex());
+ Assert ((1<=dim) && (dim<=3), ExcNotImplemented());
+
+ DoFHandler<dim>::active_cell_iterator cell,
+ endc = dofs->end();
+ unsigned int n_vertex_dofs;
+
+ // first loop over all cells to
+ // find out how many degrees of
+ // freedom there are located on
+ // vertices
+ if (true)
+ {
+ // block this to have local
+ // variables destroyed after
+ // use
+ vector<bool> is_vertex_dof (dofs->n_dofs(), false);
+ for (cell=dofs->begin_active(); cell!=endc; ++cell)
+ for (unsigned int vertex=0; vertex<(1<<dim); ++vertex)
+ is_vertex_dof[cell->vertex_dof_index(vertex,0)] = true;
+
+ n_vertex_dofs = 0;
+ for (unsigned i=0; i!=is_vertex_dof.size(); ++i)
+ if (is_vertex_dof[i] == true)
+ ++n_vertex_dofs;
+ };
+
+
+ // write preamble
+ if (true)
+ {
+ // block this to have local
+ // variables destroyed after
+ // use
+ time_t time1= time (0);
+ tm *time = localtime(&time1);
+ out << "# This file was generated by the deal.II library." << endl
+ << "# Date = "
+ << time->tm_year+1900 << "/"
+ << time->tm_mon+1 << "/"
+ << time->tm_mday << endl
+ << "# Time = "
+ << time->tm_hour << ":" << time->tm_min << ":" << time->tm_sec << endl
+ << "#" << endl
+ << "# For a description of the UCD format see the AVS Developer's guide."
+ << endl;
+ };
+
+ // start with ucd data
+ out << n_vertex_dofs << ' '
+ << dofs->get_tria().n_active_cells() << ' '
+ << data.size() << ' '
+ << 0 << ' ' // no cell data
+ << 0 // no model data
+ << endl;
+
+ // write used nodes
+ if (true)
+ {
+ // note if a given vertex was
+ // already written
+ vector<bool> already_written (dofs->n_dofs(), false);
+ // write vertices
+ for (cell=dofs->begin_active(); cell!=endc; ++cell)
+ for (unsigned int vertex=0; vertex<(1<<dim); ++vertex)
+ if (already_written[cell->vertex_dof_index(vertex,0)]==false)
+ {
+ out << cell->vertex_dof_index(vertex,0) // vertex index
+ << " ";
+ for (unsigned int d=0; d<dim; ++d) // vertex coordinates
+ out << cell->vertex(vertex)(d) << ' ';
+ for (unsigned int d=dim; d<3; ++d)
+ out << 0 << ' ';
+ out << endl;
+
+ already_written[cell->vertex_dof_index(vertex,0)] = true;
+ };
+ };
+
+ // write cells. Enumerate cells
+ // consecutively (doesn't matter since
+ // we do not use cell data)
+ if (true)
+ {
+ unsigned int c;
+ for (cell=dofs->begin_active(), c=0; cell!=endc; ++cell, ++c)
+ {
+ out << c << ' '
+ << 1 << " "; // material id (unused)
+ switch (dim)
+ {
+ case 1: out << "line "; break;
+ case 2: out << "quad "; break;
+ case 3: out << "hex "; break;
+ };
+ for (unsigned int vertex=0; vertex<(1<<dim); ++vertex)
+ out << cell->vertex_dof_index(vertex,0) << ' ';
+ out << endl;
+ };
+ };
+
+ // if data given: write data, else
+ // only write grid
+ if (data.size() != 0)
+ {
+ out << data.size() << " "; // number of vectors
+ for (unsigned int i=0; i!=data.size(); ++i)
+ out << 1 << ' '; // number of components;
+ // only 1 supported presently
+ out << endl;
+
+ for (unsigned int i=0; i<data.size(); ++i)
+ out << data[i].name << ',' << data[i].units << endl;
+
+ for (cell=dofs->begin_active(); cell!=endc; ++cell)
+ for (unsigned int vertex=0; vertex<(1<<dim); ++vertex)
+ {
+ out << cell->vertex_dof_index(vertex,0) << " ";
+ for (unsigned int i=0; i!=data.size(); ++i)
+ out << (*data[i].data)(cell->vertex_dof_index(vertex,0)) << ' ';
+ out << endl;
+ };
+ };
+ // no cell data
+ // no model data
+};
+
+
+
+template <int dim>
+void DataOut<dim>::write_gnuplot (ostream &out) const {
+ Assert (dofs != 0, ExcNoDoFHandlerSelected());
+ Assert ((1<=dim) && (dim<=3), ExcNotImplemented());
+
+ if (dim==1)
+ Assert (dofs->get_selected_fe().dofs_per_vertex==1,
+ ExcIncorrectDofsPerVertex());
+
+ DoFHandler<dim>::active_cell_iterator cell;
+ DoFHandler<dim>::active_cell_iterator endc = dofs->end();
+
+ for (cell=dofs->begin_active(); cell!=endc; ++cell)
+ {
+ switch (dim)
+ {
+ case 1:
+ // one dimension: write
+ // left vertex, right vertex
+ // and data values
+ for (unsigned int vertex=0; vertex<2; ++vertex)
+ {
+ out << cell->vertex(vertex)
+ << " ";
+ for (unsigned int i=0; i!=data.size(); ++i)
+ out << (*data[i].data)(cell->vertex_dof_index(vertex,0)) << ' ';
+ out << endl;
+ };
+
+ break;
+
+ case 2:
+ // two dimension: output
+ // grid
+ for (unsigned int vertex=0; vertex<4; ++vertex)
+ out << cell->vertex(vertex) << endl;
+ out << cell->vertex(0) << endl << endl;
+
+ break;
+
+ case 3:
+ Assert (false, ExcNotImplemented());
+ };
+ };
+};
+
+
+
+
+//explicite instantiations
+template class DataOut<1>;
+template class DataOut<2>;
--- /dev/null
+# $Id$
+
+CXX=c++
+CXXFLAGS.g= -DDEBUG -g -Wall -I../include
+CXXFLAGS = -O3 -I../include
+
+LIBS.g = -L../lib -lbasic.g -lgrid.g -lfe.g -lnumerics.g -ldeal.g
+LIBS = -L../lib -lbasic -lgrid -lfe -lnumerics -ldeal
+
+ifeq ($(shell uname),SunOS)
+CXXFLAGS := -V2.7.2.3 $(CXXFLAGS)
+CXXFLAGS.g:= -V2.7.2.3 $(CXXFLAGS.g)
+endif
+
+
+cc-files = grid/grid_test.cc
+o-files = $(cc-files:.cc=.o)
+h-files = $(wildcard ../include/*.h)
+
+examples: grid/grid_test dof/dof_test
+
+
+grid/grid_test: grid/grid_test.o ../lib/libgrid.a
+ $(CXX) $(CXXFLAGS) -o $@ $< $(LIBS)
+
+dof/dof_test: dof/dof_test.o ../lib/libgrid.g.a ../lib/libdeal.g.a
+ $(CXX) $(CXXFLAGS.g) -o $@ $< $(LIBS.g) -lg++
+
+
+run: run_grid_test run_dof_test
+
+run_grid_test:
+ cd grid ; grid_test 4 ; mv grid.1 grid.4
+ cd grid ; grid_test 3 ; mv grid.1 grid.3
+ cd grid ; grid_test 2 ; mv grid.1 grid.2
+ cd grid ; grid_test 1
+ cd grid ; gnuplot make_ps
+
+run_dof_test:
+ cd dof ; dof_test dof_test.prm
+ cd dof ; gnuplot make_ps
+
+clean:
+ cd grid ; rm -f grid.[1234] *.eps *.o *~ grid_test
+ cd dof ; rm -f grid.* sparsity.* *.o *~ dof_test
+
+
+#Rule to generate the dependency file. This file is
+#automagically remade whenever needed, i.e. whenever
+#one of the cc-/h-files changed. Make detects whether
+#to remake this file upon inclusion at the bottom
+#of this file.
+Makefile.dep: $(cc-files) $(h-files)
+ $(CXX) -I../include -M $(cc-files) > Makefile.dep
+
+include Makefile.dep
--- /dev/null
+grid_test.o: grid/grid_test.cc ../include/grid/tria_iterator.h \
+ /usr/local/include/g++/iterator.h /usr/local/include/g++/function.h \
+ /usr/local/include/g++/stl_config.h \
+ /usr/local/include/g++/stl_relops.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/stddef.h \
+ /usr/local/include/g++/stl_function.h \
+ /usr/local/include/g++/iostream.h /usr/local/include/g++/streambuf.h \
+ /usr/local/include/g++/libio.h /usr/local/lib/g++-include/_G_config.h \
+ /usr/local/include/g++/stl_iterator.h \
+ /usr/local/include/g++/type_traits.h \
+ /usr/local/include/g++/stl_construct.h \
+ /usr/local/lib/g++-include/new.h /usr/local/lib/g++-include/std/new.h \
+ /usr/local/lib/g++-include/std/cstddef.h \
+ /usr/local/include/g++/stl_raw_storage_iter.h \
+ ../include/basic/exceptions.h ../include/grid/point.h \
+ ../include/grid/tria_accessor.h ../include/grid/tria.h \
+ /usr/local/include/g++/vector.h /usr/local/include/g++/algobase.h \
+ /usr/local/include/g++/pair.h /usr/local/include/g++/stl_pair.h \
+ /usr/local/include/g++/stl_algobase.h /usr/include/string.h \
+ /usr/include/sys/feature_tests.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/limits.h \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/syslimits.h \
+ /usr/include/limits.h /usr/include/sys/isa_defs.h \
+ /usr/include/stdlib.h /usr/local/include/g++/stl_uninitialized.h \
+ /usr/local/include/g++/alloc.h /usr/local/include/g++/stl_alloc.h \
+ /usr/local/sparc-sun-solaris2.5.1/include/assert.h \
+ /usr/local/include/g++/stl_vector.h ../include/grid/tria_line.h \
+ ../include/grid/tria_quad.h ../include/grid/tria_boundary.h \
+ /usr/local/include/g++/cmath \
+ /usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.0/include/math.h \
+ /usr/include/math.h /usr/include/floatingpoint.h /usr/include/stdio.h \
+ /usr/include/sys/va_list.h /usr/include/sys/ieeefp.h \
+ /usr/local/include/g++/fstream.h
--- /dev/null
+/* $Id$ */
+
+
+#include <grid/dof.h>
+#include <grid/tria.h>
+#include <fe/fe_lib.h>
+#include <grid/tria_iterator.h>
+#include <grid/tria_accessor.h>
+#include "../../deal/dsmatrix.h"
+#include <basic/parameter_handler.h>
+#include <grid/dof_constraints.h>
+
+
+#include <fstream.h>
+#include <cmath>
+extern "C" {
+# include <stdlib.h>
+}
+
+extern TriaActiveIterator<1,CellAccessor<1> > x;
+extern TriaActiveIterator<2,CellAccessor<2> > y;
+
+
+
+// 1: continuous refinement of the unit square always in the middle
+// 2: refinement of the circle at the boundary
+// 2: refinement of a wiggled area at the boundary
+// 4: random refinement
+
+
+
+
+
+
+template <int dim>
+class Ball :
+ public StraightBoundary<dim> {
+ public:
+ virtual Point<dim> in_between (const PointArray &neighbors) const {
+ Point<dim> middle = StraightBoundary<dim>::in_between(neighbors);
+
+ for (int i=0; i<dim; ++i)
+ middle(i) -= .5;
+ middle /= (sqrt(middle.square())*sqrt(2));
+ for (int i=0; i<dim; ++i)
+ middle(i) += .5;
+
+ return middle;
+ };
+};
+
+
+template <int dim>
+class CurvedLine :
+ public StraightBoundary<dim> {
+ public:
+ virtual Point<dim> in_between (const PointArray &neighbors) const {
+ Point<dim> middle = StraightBoundary<dim>::in_between(neighbors);
+ double x=middle(0),
+ y=middle(1);
+
+ if (y<x)
+ if (y<1-x)
+ middle(1) = 0.04*sin(6*3.141592*middle(0));
+ else
+ middle(0) = 1+0.04*sin(6*3.141592*middle(1));
+
+ else
+ if (y<1-x)
+ middle(0) = 0.04*sin(6*3.141592*middle(1));
+ else
+ middle(1) = 1+0.04*sin(6*3.141592*middle(0));
+
+ return middle;
+ };
+};
+
+
+
+template <int dim>
+class TestCases : public MultipleParameterLoop::UserClass{
+ public:
+ TestCases ();
+
+ virtual void create_new (const unsigned int run_no);
+ virtual void declare_parameters (ParameterHandler &prm);
+ virtual void run (ParameterHandler &prm);
+
+ private:
+ Triangulation<dim> *tria;
+ DoFHandler<dim> *dof;
+};
+
+
+
+template <int dim>
+TestCases<dim>::TestCases () :
+ tria(0), dof(0) {};
+
+
+
+template <int dim>
+void TestCases<dim>::create_new (const unsigned int) {
+ if (tria != 0) delete tria;
+ if (dof != 0) delete dof;
+
+ tria = new Triangulation<dim>();
+ tria->create_unit_hypercube();
+
+ dof = new DoFHandler<dim> (tria);
+};
+
+
+
+template <int dim>
+void TestCases<dim>::declare_parameters (ParameterHandler &prm) {
+ if (dim>=2)
+ prm.declare_entry ("Test run", "zoom in", "zoom in\\|ball\\|curved line\\|random");
+ else
+ prm.declare_entry ("Test run", "zoom in", "zoom in\\|random");
+ prm.declare_entry ("Grid file", "grid.1");
+ prm.declare_entry ("Sparsity file", "sparsity.1");
+ prm.declare_entry ("Condensed sparsity file", "sparsity.c.1");
+};
+
+
+
+template <int dim>
+void TestCases<dim>::run (ParameterHandler &prm) {
+ cout << "Test case = " << prm.get ("Test run") << endl
+ << endl;
+
+ cout << " Making grid..." << endl;
+
+ String test = prm.get ("Test run");
+ unsigned int test_case;
+ if (test=="zoom in") test_case = 1;
+ else
+ if (test=="ball") test_case = 2;
+ else
+ if (test=="curved line") test_case = 3;
+ else
+ if (test=="random") test_case = 4;
+ else
+ cerr << "This test seems not to be implemented!" << endl;
+
+
+ switch (test_case)
+ {
+ case 1:
+ {
+ // refine first cell
+ tria->begin_active()->set_refine_flag();
+ tria->execute_refinement ();
+ // refine first active cell
+ // on coarsest level
+ tria->begin_active()->set_refine_flag ();
+ tria->execute_refinement ();
+
+ Triangulation<dim>::active_cell_iterator cell;
+ for (int i=0; i<17; ++i)
+ {
+ // refine the presently
+ // second last cell 17
+ // times
+ cell = tria->last_active(tria->n_levels()-1);
+ --cell;
+ cell->set_refine_flag ();
+ tria->execute_refinement ();
+ };
+
+// tria->refine_global (5);
+
+ break;
+ }
+
+ case 2:
+ case 3:
+ {
+ // set the boundary function
+ Boundary<dim> *boundary = (test_case==2 ?
+ new Ball<dim>() :
+ new CurvedLine<dim>());
+ tria->set_boundary (boundary);
+
+ // refine once
+ tria->begin_active()->set_refine_flag();
+ tria->execute_refinement ();
+
+ Triangulation<dim>::active_cell_iterator cell, endc;
+ for (int i=0; i<4; ++i)
+ {
+ cell = tria->begin_active();
+ endc = tria->end();
+
+ // refine all
+ // boundary cells
+ for (; cell!=endc; ++cell)
+ if (cell->at_boundary())
+ cell->set_refine_flag();
+
+ tria->execute_refinement();
+ };
+
+ break;
+ }
+
+ case 4:
+ {
+ // refine once
+ tria->begin_active()->set_refine_flag();
+ tria->execute_refinement ();
+
+ Triangulation<dim>::active_cell_iterator cell, endc;
+ for (int i=0; i<(dim==2 ? 12 : 20); ++i)
+ {
+ int n_levels = tria->n_levels();
+ cell = tria->begin_active();
+ endc = tria->end();
+
+ for (; cell!=endc; ++cell)
+ {
+ double r = rand()*1.0/RAND_MAX,
+ weight = 1.*
+ (cell->level()*cell->level()) /
+ (n_levels*n_levels);
+
+ if (r <= 0.5*weight)
+ cell->set_refine_flag ();
+ };
+
+ tria->execute_refinement ();
+ };
+ break;
+ }
+ };
+
+ // output the grid
+ cout << " Writing grid..." << endl;
+ ofstream out(prm.get("Grid file"));
+ tria->print_gnuplot (out);
+
+
+
+
+ cout << " Distributing degrees of freedom..." << endl;
+ FEQuadratic<dim> fe;
+ dof->distribute_dofs (fe);
+
+ cout << " Renumbering degrees of freedom..." << endl;
+ dof->renumber_dofs (Cuthill_McKee, false);
+
+ dSMatrixStruct sparsity (dof->n_dofs(),
+ dof->max_couplings_between_dofs());
+
+
+ dof->make_sparsity_pattern (sparsity);
+ int unconstrained_bandwidth = sparsity.bandwidth();
+
+ cout << " Writing sparsity pattern... (This may take a while)" << endl;
+ ofstream sparsity_out (prm.get("Sparsity file"));
+ sparsity.print_gnuplot (sparsity_out);
+
+
+
+ // computing constraints
+ cout << " Computing constraints..." << endl;
+ ConstraintMatrix constraints;
+ dof->make_constraint_matrix (constraints);
+ constraints.condense (sparsity);
+
+ cout << " Writing condensed sparsity pattern... (This may take a while)" << endl;
+ ofstream c_sparsity_out (prm.get("Condensed sparsity file"));
+ sparsity.print_gnuplot (c_sparsity_out);
+
+
+// DataOut<dim> dataout;
+// dataout.attach_dof_handler (*dof);
+// ofstream o("o.inp");
+// dataout.write_ucd (o);
+
+ cout << endl
+ << " Total number of cells = " << tria->n_cells() << endl
+ << " Total number of active cells = " << tria->n_active_cells() << endl
+ << " Number of DoFs = " << dof->n_dofs() << endl
+ << " Number of constraints = " << constraints.n_constraints() << endl
+ << " Unconstrained matrix bandwidth= " << unconstrained_bandwidth << endl
+ << " Constrained matrix bandwidth = " << sparsity.bandwidth()
+ << endl << endl;
+};
+
+
+
+int main (int argc, char **argv) {
+ if (argc!=2)
+ {
+ cout << "Usage: grid_test parameterfile" << endl << endl;
+ return 1;
+ };
+
+ TestCases<2> tests;
+ class MultipleParameterLoop input_data; //gcc2.7 does nonsense, wait for gcc2.8
+
+ tests.declare_parameters(input_data);
+ input_data.read_input (argv[1]);
+ input_data.loop (tests);
+
+ return 0;
+};
+
--- /dev/null
+set Test run = { zoom in | ball | curved line | random }
+set Grid file = grid.{{ zoom_in | ball | curved_line | random }}
+set Sparsity file = sparsity.{{ zoom_in | ball | curved_line | random }}
+set Condensed sparsity file = sparsity.c.{{ zoom_in | ball | curved_line | random }}
\ No newline at end of file
--- /dev/null
+set size 0.721,1
+set data style lines
+set noxtics
+set noytics
+set noxzeroaxis
+set noyzeroaxis
+set nokey
+set term postscript eps
+
+!echo " Making <grid.zoom_in.eps>"
+set output "grid.zoom_in.eps"
+plot "grid.zoom_in"
+
+!echo " Making <grid.ball.eps>"
+set output "grid.ball.eps"
+plot "grid.ball"
+
+!echo " Making <grid.curved_line.eps>"
+set output "grid.curved_line.eps"
+plot "grid.curved_line"
+
+!echo " Making <grid.random.eps>"
+set output "grid.random.eps"
+plot "grid.random"
+
+
+
+set data style dots
+
+!echo " Making <sparsity.zoom_in.eps>"
+set output "sparsity.zoom_in.eps"
+plot "sparsity.zoom_in"
+
+!echo " Making <sparsity.ball.eps>"
+set output "sparsity.ball.eps"
+plot "sparsity.ball"
+
+!echo " Making <sparsity.curved_line.eps>"
+set output "sparsity.curved_line.eps"
+plot "sparsity.curved_line"
+
+!echo " Making <sparsity.random.eps>"
+set output "sparsity.random.eps"
+plot "sparsity.random"
+
+
+
+!echo " Making <sparsity.c.zoom_in.eps>"
+set output "sparsity.c.zoom_in.eps"
+plot "sparsity.c.zoom_in"
+
+!echo " Making <sparsity.c.ball.eps>"
+set output "sparsity.c.ball.eps"
+plot "sparsity.c.ball"
+
+!echo " Making <sparsity.c.curved_line.eps>"
+set output "sparsity.c.curved_line.eps"
+plot "sparsity.c.curved_line"
+
+!echo " Making <sparsity.c.random.eps>"
+set output "sparsity.c.random.eps"
+plot "sparsity.c.random"
--- /dev/null
+/* $Id$ */
+
+#include <grid/tria_iterator.h>
+#include <grid/tria.h>
+#include <cmath>
+#include <fstream.h>
+extern "C" {
+# include <stdlib.h>
+}
+
+
+// 1: continuous refinement of the unit square always in the middle
+// 2: refinement of the circle at the boundary
+// 2: refinement of a wiggled area at the boundary
+// 4: random refinement
+
+
+
+
+
+
+template <int dim>
+class Ball :
+ public StraightBoundary<dim> {
+ public:
+ virtual Point<dim> in_between (const PointArray &neighbors) const {
+ Point<dim> middle = StraightBoundary<dim>::in_between(neighbors);
+
+ for (int i=0; i<dim; ++i)
+ middle(i) -= .5;
+ middle /= (sqrt(middle.square())*sqrt(2));
+ for (int i=0; i<dim; ++i)
+ middle(i) += .5;
+
+ return middle;
+ };
+};
+
+
+template <int dim>
+class CurvedLine :
+ public StraightBoundary<dim> {
+ public:
+ virtual Point<dim> in_between (const PointArray &neighbors) const {
+ Point<dim> middle = StraightBoundary<dim>::in_between(neighbors);
+ double x=middle(0),
+ y=middle(1);
+
+ if (y<x)
+ if (y<1-x)
+ middle(1) = 0.04*sin(6*3.141592*middle(0));
+ else
+ middle(0) = 1+0.04*sin(6*3.141592*middle(1));
+
+ else
+ if (y<1-x)
+ middle(0) = 0.04*sin(6*3.141592*middle(1));
+ else
+ middle(1) = 1+0.04*sin(6*3.141592*middle(0));
+
+ return middle;
+ };
+};
+
+
+
+// since gcc can't resolve "test<2>()", do template parameter
+// passing this way...
+template <int dim>
+void test (const int test_case, const Point<dim> &) {
+ Triangulation<dim> tria;
+ tria.create_unit_hypercube();
+
+ if ((dim==1) && ((test_case==2) || (test_case==3)))
+ {
+ cout << "Impossible for this dimension." << endl;
+ return;
+ };
+
+
+ switch (test_case)
+ {
+ case 1:
+ {
+ // we want to log the
+ // refinement history
+// ofstream history ("mesh.history");
+
+ // refine first cell
+ tria.begin_active()->set_refine_flag();
+// tria.save_refine_flags (history);
+ tria.execute_refinement ();
+
+ // refine first active cell
+ // on coarsest level
+ tria.begin_active()->set_refine_flag ();
+// tria.save_refine_flags (history);
+ tria.execute_refinement ();
+
+ Triangulation<dim>::active_cell_iterator cell;
+ for (int i=0; i<17; ++i)
+ {
+ // refine the presently
+ // second last cell 17
+ // times
+ cell = tria.last_active(tria.n_levels()-1);
+ --cell;
+ cell->set_refine_flag ();
+// tria.save_refine_flags (history);
+ tria.execute_refinement ();
+ };
+
+// tria.refine_global (5);
+
+ break;
+ }
+
+ case 2:
+ case 3:
+ {
+ // set the boundary function
+ Ball<dim> ball;
+ CurvedLine<dim> curved_line;
+ if (test_case==2)
+ tria.set_boundary (&ball);
+ else
+ tria.set_boundary (&curved_line);
+
+ // refine once
+ tria.begin_active()->set_refine_flag();
+ tria.execute_refinement ();
+
+ Triangulation<dim>::active_cell_iterator cell, endc;
+ for (int i=0; i<7; ++i)
+ {
+ cell = tria.begin_active();
+ endc = tria.end();
+
+ // refine all
+ // boundary cells
+ for (; cell!=endc; ++cell)
+ if (cell->at_boundary())
+ cell->set_refine_flag();
+
+ tria.execute_refinement();
+ };
+
+ break;
+ }
+
+ case 4:
+ {
+ // refine once
+ tria.begin_active()->set_refine_flag();
+ tria.execute_refinement ();
+
+ Triangulation<dim>::active_cell_iterator cell, endc;
+ for (int i=0; i<(dim==2 ? 13 : 30); ++i)
+ {
+ int n_levels = tria.n_levels();
+ cell = tria.begin_active();
+ endc = tria.end();
+
+ for (; cell!=endc; ++cell)
+ {
+ double r = rand()*1.0/RAND_MAX,
+ weight = 1.*
+ (cell->level()*cell->level()) /
+ (n_levels*n_levels);
+
+ if (r <= 0.5*weight)
+ cell->set_refine_flag ();
+ };
+
+ tria.execute_refinement ();
+ };
+ break;
+ }
+ };
+
+
+
+ // output the grid
+ ofstream out("grid.1");
+ tria.print_gnuplot (out);
+
+ cout << " Total number of cells = " << tria.n_cells() << endl
+ << " Total number of active cells = " << tria.n_active_cells() << endl;
+};
+
+
+
+int main (int argc, char **argv) {
+ if (argc!=2)
+ {
+ cout << "Usage: grid_test testcase" << endl << endl
+ << "Testcases:" << endl
+ << " 1: continuous refinement of the unit square always in the middle" << endl
+ << " 2: refinement of the circle at the boundary" << endl
+ << " 3: refinement of a wiggled area at the boundary" << endl
+ << " 4: random refinement" << endl << endl;
+ return 1;
+ };
+
+ test (argv[1][0]-'0', Point<2>());
+
+ return 0;
+};
--- /dev/null
+set size 0.721,1
+set data style lines
+set term postscript eps
+
+set output "grid.1.eps"
+plot "grid.1"
+
+set output "grid.2.eps"
+plot "grid.2"
+
+set output "grid.3.eps"
+plot "grid.3"
+
+set output "grid.4.eps"
+plot "grid.4"
+
--- /dev/null
+/* $Id$ */
+
+
+#include <grid/dof.h>
+#include <grid/tria.h>
+#include <fe/fe_lib.h>
+#include <grid/tria_iterator.h>
+#include <grid/tria_accessor.h>
+#include "../../deal/dsmatrix.h>
+#include <grid/dof_constraints.h>
+#include <basic/data_io.h>
+#include <numerics/problem_base.h>
+#include <numerics/problem_assembler.h>
+
+#include <fstream.h>
+#include <cmath>
+extern "C" {
+# include <stdlib.h>
+}
+
+extern TriaActiveIterator<1,CellAccessor<1> > x;
+extern TriaActiveIterator<2,CellAccessor<2> > y;
+
+
+void main () {
+ Triangulation<1> tria;
+ DoFHandler<1> dof(tria);
+ FELinear<1> fe;
+ ProblemBase<1> problem(&tria, &dof);
+ Quadrature<1> q;
+
+ tria.create_hypercube();
+ dof.distribute_dofs (fe);
+ problem.assemble (q);
+};