From 184639502b4ed7537aff1fa2954d279e2d7b2a29 Mon Sep 17 00:00:00 2001 From: Wolfgang Bangerth Date: Wed, 4 Mar 1998 17:21:25 +0000 Subject: [PATCH] Initial revision git-svn-id: https://svn.dealii.org/trunk@16 0785d39b-7218-0410-832d-ea1e28bc413d --- deal.II/base/include/base/parameter_handler.h | 1102 +++++++++ deal.II/base/include/base/quadrature.h | 62 + deal.II/base/include/base/quadrature_lib.h | 71 + deal.II/base/source/parameter_handler.cc | 848 +++++++ deal.II/base/source/quadrature_lib.cc | 131 ++ deal.II/deal.II/Attic/examples/Makefile | 56 + .../deal.II/Attic/examples/dof/dof_test.cc | 310 +++ .../deal.II/Attic/examples/dof/dof_test.prm | 4 + deal.II/deal.II/Attic/examples/dof/make_ps | 62 + .../deal.II/Attic/examples/grid/grid_test.cc | 208 ++ deal.II/deal.II/Attic/examples/grid/make_ps | 16 + .../deal.II/Attic/examples/poisson/poisson.cc | 35 + deal.II/deal.II/Conventions | 27 + deal.II/deal.II/Makefile | 34 + deal.II/deal.II/Todo | 45 + deal.II/deal.II/include/dofs/dof_accessor.h | 397 ++++ .../deal.II/include/dofs/dof_constraints.h | 296 +++ deal.II/deal.II/include/dofs/dof_handler.h | 996 ++++++++ deal.II/deal.II/include/fe/fe.h | 537 +++++ deal.II/deal.II/include/fe/fe_lib.lagrange.h | 62 + deal.II/deal.II/include/grid/exceptions.h | 405 ++++ deal.II/deal.II/include/grid/magic_numbers.h | 26 + deal.II/deal.II/include/grid/point.h | 360 +++ deal.II/deal.II/include/grid/tria.h | 1442 ++++++++++++ deal.II/deal.II/include/grid/tria_accessor.h | 861 +++++++ deal.II/deal.II/include/grid/tria_boundary.h | 80 + deal.II/deal.II/include/grid/tria_iterator.h | 744 ++++++ .../include/grid/tria_iterator.templates.h | 384 ++++ deal.II/deal.II/include/grid/tria_line.h | 90 + deal.II/deal.II/include/grid/tria_quad.h | 98 + deal.II/deal.II/include/numerics/assembler.h | 215 ++ deal.II/deal.II/include/numerics/base.h | 49 + deal.II/deal.II/include/numerics/data_io.h | 200 ++ deal.II/deal.II/source/Makefile | 26 + deal.II/deal.II/source/dofs/dof_accessor.cc | 321 +++ .../deal.II/source/dofs/dof_constraints.cc | 252 ++ deal.II/deal.II/source/dofs/dof_handler.cc | 1376 +++++++++++ deal.II/deal.II/source/fe/Makefile | 62 + deal.II/deal.II/source/fe/Makefile.dep | 176 ++ deal.II/deal.II/source/fe/fe.cc | 249 ++ deal.II/deal.II/source/fe/fe_lib.linear.cc | 238 ++ deal.II/deal.II/source/grid/Makefile | 62 + deal.II/deal.II/source/grid/Makefile.dep | 340 +++ deal.II/deal.II/source/grid/tria.cc | 2040 +++++++++++++++++ deal.II/deal.II/source/grid/tria_accessor.cc | 596 +++++ deal.II/deal.II/source/numerics/Makefile | 62 + deal.II/deal.II/source/numerics/assembler.cc | 177 ++ deal.II/deal.II/source/numerics/base.cc | 47 + deal.II/deal.II/source/numerics/data_io.cc | 231 ++ tests/big-tests/Makefile | 56 + tests/big-tests/Makefile.dep | 33 + tests/big-tests/dof/dof_test.cc | 310 +++ tests/big-tests/dof/dof_test.prm | 4 + tests/big-tests/dof/make_ps | 62 + tests/big-tests/grid/grid_test.cc | 208 ++ tests/big-tests/grid/make_ps | 16 + tests/big-tests/poisson/poisson.cc | 35 + 57 files changed, 17232 insertions(+) create mode 100644 deal.II/base/include/base/parameter_handler.h create mode 100644 deal.II/base/include/base/quadrature.h create mode 100644 deal.II/base/include/base/quadrature_lib.h create mode 100644 deal.II/base/source/parameter_handler.cc create mode 100644 deal.II/base/source/quadrature_lib.cc create mode 100644 deal.II/deal.II/Attic/examples/Makefile create mode 100644 deal.II/deal.II/Attic/examples/dof/dof_test.cc create mode 100644 deal.II/deal.II/Attic/examples/dof/dof_test.prm create mode 100644 deal.II/deal.II/Attic/examples/dof/make_ps create mode 100644 deal.II/deal.II/Attic/examples/grid/grid_test.cc create mode 100644 deal.II/deal.II/Attic/examples/grid/make_ps create mode 100644 deal.II/deal.II/Attic/examples/poisson/poisson.cc create mode 100644 deal.II/deal.II/Conventions create mode 100644 deal.II/deal.II/Makefile create mode 100644 deal.II/deal.II/Todo create mode 100644 deal.II/deal.II/include/dofs/dof_accessor.h create mode 100644 deal.II/deal.II/include/dofs/dof_constraints.h create mode 100644 deal.II/deal.II/include/dofs/dof_handler.h create mode 100644 deal.II/deal.II/include/fe/fe.h create mode 100644 deal.II/deal.II/include/fe/fe_lib.lagrange.h create mode 100644 deal.II/deal.II/include/grid/exceptions.h create mode 100644 deal.II/deal.II/include/grid/magic_numbers.h create mode 100644 deal.II/deal.II/include/grid/point.h create mode 100644 deal.II/deal.II/include/grid/tria.h create mode 100644 deal.II/deal.II/include/grid/tria_accessor.h create mode 100644 deal.II/deal.II/include/grid/tria_boundary.h create mode 100644 deal.II/deal.II/include/grid/tria_iterator.h create mode 100644 deal.II/deal.II/include/grid/tria_iterator.templates.h create mode 100644 deal.II/deal.II/include/grid/tria_line.h create mode 100644 deal.II/deal.II/include/grid/tria_quad.h create mode 100644 deal.II/deal.II/include/numerics/assembler.h create mode 100644 deal.II/deal.II/include/numerics/base.h create mode 100644 deal.II/deal.II/include/numerics/data_io.h create mode 100644 deal.II/deal.II/source/Makefile create mode 100644 deal.II/deal.II/source/dofs/dof_accessor.cc create mode 100644 deal.II/deal.II/source/dofs/dof_constraints.cc create mode 100644 deal.II/deal.II/source/dofs/dof_handler.cc create mode 100644 deal.II/deal.II/source/fe/Makefile create mode 100644 deal.II/deal.II/source/fe/Makefile.dep create mode 100644 deal.II/deal.II/source/fe/fe.cc create mode 100644 deal.II/deal.II/source/fe/fe_lib.linear.cc create mode 100644 deal.II/deal.II/source/grid/Makefile create mode 100644 deal.II/deal.II/source/grid/Makefile.dep create mode 100644 deal.II/deal.II/source/grid/tria.cc create mode 100644 deal.II/deal.II/source/grid/tria_accessor.cc create mode 100644 deal.II/deal.II/source/numerics/Makefile create mode 100644 deal.II/deal.II/source/numerics/assembler.cc create mode 100644 deal.II/deal.II/source/numerics/base.cc create mode 100644 deal.II/deal.II/source/numerics/data_io.cc create mode 100644 tests/big-tests/Makefile create mode 100644 tests/big-tests/Makefile.dep create mode 100644 tests/big-tests/dof/dof_test.cc create mode 100644 tests/big-tests/dof/dof_test.prm create mode 100644 tests/big-tests/dof/make_ps create mode 100644 tests/big-tests/grid/grid_test.cc create mode 100644 tests/big-tests/grid/make_ps create mode 100644 tests/big-tests/poisson/poisson.cc diff --git a/deal.II/base/include/base/parameter_handler.h b/deal.II/base/include/base/parameter_handler.h new file mode 100644 index 0000000000..6a4dd3bd25 --- /dev/null +++ b/deal.II/base/include/base/parameter_handler.h @@ -0,0 +1,1102 @@ +/********************** 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 MultipleParameterLoop; + + +#include +#include +#include + +#ifdef DEBUG +# define _G_NO_NRV // don't use GNU's named return values in debug modes +# include // because if we did we'd harvest tons of warnings. +# undef _G_NO_NRV +#else +# include +#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 + #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 + Equation 2 = Navier-Stokes + Output file= out + subsection Equation 1 + Matrix type = Sparse + subsection Linear solver + Maximum number of iterations = 40 <20> + Solver = CG + subsection Equation 2 + Matrix type = Full + subsection Linear solver + Maximum number of iterations = 100 <20> + Solver = 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, less > entries; + map > subsections; + }; + + /** + * Path of presently selected subsections; + * empty list means top level + */ + vector 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 &Path, const String &Name, const String &Value); + + /** + * Split the entry value into the different + * branches. + */ + void split_different_values (); + + /** + * Path to variant entry. + */ + vector 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 different_values; + + /** + * Store whether this entry is a variant + * entry or an array. + */ + MultipleEntryType type; + }; + + /** + * List of variant entry values. + */ + vector 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 ****************************/ diff --git a/deal.II/base/include/base/quadrature.h b/deal.II/base/include/base/quadrature.h new file mode 100644 index 0000000000..fbe09067ed --- /dev/null +++ b/deal.II/base/include/base/quadrature.h @@ -0,0 +1,62 @@ +/*---------------------------- quadrature.h ---------------------------*/ +/* */ +#ifndef __quadrature_H +#define __quadrature_H +/*---------------------------- quadrature.h ---------------------------*/ + + +#include +#include + + + +/** + Base class for quadrature formulae in arbitrary dimensions. + */ +template +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 & 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 > quadrature_points; + + /** + * List of weights of the quadrature points. + * To be filled by the constructors of + * derived classes. + */ + vector weights; +}; + + + + + +/*---------------------------- quadrature.h ---------------------------*/ +/* end of #ifndef __quadrature_H */ +#endif +/*---------------------------- quadrature.h ---------------------------*/ diff --git a/deal.II/base/include/base/quadrature_lib.h b/deal.II/base/include/base/quadrature_lib.h new file mode 100644 index 0000000000..5d3a147ea7 --- /dev/null +++ b/deal.II/base/include/base/quadrature_lib.h @@ -0,0 +1,71 @@ +/*---------------------------- quadrature_lib.h ---------------------------*/ +/* */ +#ifndef __quadrature_lib_H +#define __quadrature_lib_H +/*---------------------------- quadrature_lib.h ---------------------------*/ + + +#include + + +template +class QGauss2 : public Quadrature { + public: + QGauss2 (); +}; + + + +template +class QGauss2x4 : public Quadrature { + public: + QGauss2x4 (); +}; + + + +template +class QGauss4 : public Quadrature { + public: + QGauss4 (); +}; + + + +template +class QGauss8 : public Quadrature { + public: + QGauss8 (); +}; + + + +template +class QMidpoint : public Quadrature { + public: + QMidpoint (); +}; + + + +template +class QSimpson : public Quadrature { + public: + QSimpson (); +}; + + + +template +class QTrapez : public Quadrature { + public: + QTrapez (); +}; + + + + +/*---------------------------- quadrature_lib.h ---------------------------*/ +/* end of #ifndef __quadrature_lib_H */ +#endif +/*---------------------------- quadrature_lib.h ---------------------------*/ diff --git a/deal.II/base/source/parameter_handler.cc b/deal.II/base/source/parameter_handler.cc new file mode 100644 index 0000000000..9471f0caf1 --- /dev/null +++ b/deal.II/base/source/parameter_handler.cc @@ -0,0 +1,848 @@ +/* $Id$ */ + +#include +#include +#include + +extern "C" { +#include +} + + + +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 >::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, less >::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, less >::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 >::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; ientries.find(entry_name) == pd->entries.end()) + { + cerr << "Line " << lineno + << ": No such entry was declared:" << endl + << " " << entry_name << endl + << " " << 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::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::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 >::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 0) + for (vector::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, less >::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 >::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::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 &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; +}; + + diff --git a/deal.II/base/source/quadrature_lib.cc b/deal.II/base/source/quadrature_lib.cc new file mode 100644 index 0000000000..92dd78e099 --- /dev/null +++ b/deal.II/base/source/quadrature_lib.cc @@ -0,0 +1,131 @@ +/* $Id$ */ + +#include + + + +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 (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 (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 (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 (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 (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 (xpts[i])); + weights.push_back (wts[i]); + }; +}; diff --git a/deal.II/deal.II/Attic/examples/Makefile b/deal.II/deal.II/Attic/examples/Makefile new file mode 100644 index 0000000000..00f5f90ea4 --- /dev/null +++ b/deal.II/deal.II/Attic/examples/Makefile @@ -0,0 +1,56 @@ +# $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 diff --git a/deal.II/deal.II/Attic/examples/dof/dof_test.cc b/deal.II/deal.II/Attic/examples/dof/dof_test.cc new file mode 100644 index 0000000000..6320aa04e2 --- /dev/null +++ b/deal.II/deal.II/Attic/examples/dof/dof_test.cc @@ -0,0 +1,310 @@ +/* $Id$ */ + + +#include +#include +#include +#include +#include +#include "../../deal/dsmatrix.h" +#include +#include + + +#include +#include +extern "C" { +# include +} + +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 +class Ball : + public StraightBoundary { + public: + virtual Point in_between (const PointArray &neighbors) const { + Point middle = StraightBoundary::in_between(neighbors); + + for (int i=0; i +class CurvedLine : + public StraightBoundary { + public: + virtual Point in_between (const PointArray &neighbors) const { + Point middle = StraightBoundary::in_between(neighbors); + double x=middle(0), + y=middle(1); + + if (y +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 *tria; + DoFHandler *dof; +}; + + + +template +TestCases::TestCases () : + tria(0), dof(0) {}; + + + +template +void TestCases::create_new (const unsigned int) { + if (tria != 0) delete tria; + if (dof != 0) delete dof; + + tria = new Triangulation(); + tria->create_unit_hypercube(); + + dof = new DoFHandler (tria); +}; + + + +template +void TestCases::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 +void TestCases::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::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 *boundary = (test_case==2 ? + new Ball() : + new CurvedLine()); + tria->set_boundary (boundary); + + // refine once + tria->begin_active()->set_refine_flag(); + tria->execute_refinement (); + + Triangulation::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::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 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 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; +}; + diff --git a/deal.II/deal.II/Attic/examples/dof/dof_test.prm b/deal.II/deal.II/Attic/examples/dof/dof_test.prm new file mode 100644 index 0000000000..eac9d72a6b --- /dev/null +++ b/deal.II/deal.II/Attic/examples/dof/dof_test.prm @@ -0,0 +1,4 @@ +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 diff --git a/deal.II/deal.II/Attic/examples/dof/make_ps b/deal.II/deal.II/Attic/examples/dof/make_ps new file mode 100644 index 0000000000..5c6280e614 --- /dev/null +++ b/deal.II/deal.II/Attic/examples/dof/make_ps @@ -0,0 +1,62 @@ +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 " +set output "grid.zoom_in.eps" +plot "grid.zoom_in" + +!echo " Making " +set output "grid.ball.eps" +plot "grid.ball" + +!echo " Making " +set output "grid.curved_line.eps" +plot "grid.curved_line" + +!echo " Making " +set output "grid.random.eps" +plot "grid.random" + + + +set data style dots + +!echo " Making " +set output "sparsity.zoom_in.eps" +plot "sparsity.zoom_in" + +!echo " Making " +set output "sparsity.ball.eps" +plot "sparsity.ball" + +!echo " Making " +set output "sparsity.curved_line.eps" +plot "sparsity.curved_line" + +!echo " Making " +set output "sparsity.random.eps" +plot "sparsity.random" + + + +!echo " Making " +set output "sparsity.c.zoom_in.eps" +plot "sparsity.c.zoom_in" + +!echo " Making " +set output "sparsity.c.ball.eps" +plot "sparsity.c.ball" + +!echo " Making " +set output "sparsity.c.curved_line.eps" +plot "sparsity.c.curved_line" + +!echo " Making " +set output "sparsity.c.random.eps" +plot "sparsity.c.random" diff --git a/deal.II/deal.II/Attic/examples/grid/grid_test.cc b/deal.II/deal.II/Attic/examples/grid/grid_test.cc new file mode 100644 index 0000000000..62c0fa1990 --- /dev/null +++ b/deal.II/deal.II/Attic/examples/grid/grid_test.cc @@ -0,0 +1,208 @@ +/* $Id$ */ + +#include +#include +#include +#include +extern "C" { +# include +} + + +// 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 +class Ball : + public StraightBoundary { + public: + virtual Point in_between (const PointArray &neighbors) const { + Point middle = StraightBoundary::in_between(neighbors); + + for (int i=0; i +class CurvedLine : + public StraightBoundary { + public: + virtual Point in_between (const PointArray &neighbors) const { + Point middle = StraightBoundary::in_between(neighbors); + double x=middle(0), + y=middle(1); + + if (y()", do template parameter +// passing this way... +template +void test (const int test_case, const Point &) { + Triangulation 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::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 ball; + CurvedLine 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::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::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; +}; diff --git a/deal.II/deal.II/Attic/examples/grid/make_ps b/deal.II/deal.II/Attic/examples/grid/make_ps new file mode 100644 index 0000000000..a0ed968360 --- /dev/null +++ b/deal.II/deal.II/Attic/examples/grid/make_ps @@ -0,0 +1,16 @@ +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" + diff --git a/deal.II/deal.II/Attic/examples/poisson/poisson.cc b/deal.II/deal.II/Attic/examples/poisson/poisson.cc new file mode 100644 index 0000000000..47c8848dba --- /dev/null +++ b/deal.II/deal.II/Attic/examples/poisson/poisson.cc @@ -0,0 +1,35 @@ +/* $Id$ */ + + +#include +#include +#include +#include +#include +#include "../../deal/dsmatrix.h> +#include +#include +#include +#include + +#include +#include +extern "C" { +# include +} + +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); +}; diff --git a/deal.II/deal.II/Conventions b/deal.II/deal.II/Conventions new file mode 100644 index 0000000000..936837b7ac --- /dev/null +++ b/deal.II/deal.II/Conventions @@ -0,0 +1,27 @@ +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 ;-) diff --git a/deal.II/deal.II/Makefile b/deal.II/deal.II/Makefile new file mode 100644 index 0000000000..f27275c9d6 --- /dev/null +++ b/deal.II/deal.II/Makefile @@ -0,0 +1,34 @@ +# $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 diff --git a/deal.II/deal.II/Todo b/deal.II/deal.II/Todo new file mode 100644 index 0000000000..eedc186366 --- /dev/null +++ b/deal.II/deal.II/Todo @@ -0,0 +1,45 @@ +Replace the declaration of vector 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 -> SubstructAccessor + QuadAccessor -> SubstructAccessor + and deriving CellAccessor from SubstructAccessor + 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! diff --git a/deal.II/deal.II/include/dofs/dof_accessor.h b/deal.II/deal.II/include/dofs/dof_accessor.h new file mode 100644 index 0000000000..87d4791d7f --- /dev/null +++ b/deal.II/deal.II/include/dofs/dof_accessor.h @@ -0,0 +1,397 @@ +/*---------------------------- dof_iterator.h ---------------------------*/ +/* $Id$ */ +#ifndef __dof_iterator_H +#define __dof_iterator_H +/*---------------------------- dof_iterator.h ---------------------------*/ + + +template class Triangulation; +template class DoFHandler; +template class vector; + + +#include + + + + +/** + Define the basis for accessors to the degrees of freedom. + */ +template +class DoFAccessor { + public: + /** + * Constructor + */ + DoFAccessor () : dof_handler(0) { + Assert (false, ExcInvalidObject()); + }; + + /** + * This should be the default constructor. + */ + DoFAccessor (DoFHandler *dof_handler) : + dof_handler(dof_handler) {}; + + /** + * Reset the DoF handler pointer. + */ + void set_dof_handler (DoFHandler *dh) { + dof_handler = dh; + }; + + /** + * Exception for child classes + */ + DeclException0 (ExcInvalidObject); + + protected: + /** + * Store the address of the #DoFHandler# object + * to be accessed. + */ + DoFHandler *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# cannot + itself be derived from #CellAccessor# 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#, 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 +class DoFLineAccessor : public BaseClass, public DoFAccessor { + public: + /** + * Default constructor, unused thus + * not implemented. + */ + DoFLineAccessor (); + + /** + * Constructor. The #local_data# + * argument is assumed to be a pointer + * to a #DoFHandler# object. + */ + DoFLineAccessor (Triangulation *tria, + const int level, + const int index, + const void *local_data) : + BaseClass(tria,level,index), + DoFAccessor ((DoFHandler*)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 > child (const unsigned int) const; + + /** + * Implement the copy operator needed + * for the iterator classes. + */ + void copy_from (const DoFLineAccessor &a); +}; + + + + + + +/** + Grant access to the degrees of freedom located on quads. + @see DoFLineAccessor + */ +template +class DoFQuadAccessor : public BaseClass, public DoFAccessor { + public: + /** + * Default constructor, unused thus + * not implemented. + */ + DoFQuadAccessor (); + + /** + * Constructor. The #local_data# + * argument is assumed to be a pointer + * to a #DoFHandler# object. + */ + DoFQuadAccessor (Triangulation *tria, + const int level, + const int index, + const void *local_data) : + BaseClass (tria,level,index), + DoFAccessor ((DoFHandler*)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 > > 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 > child (const unsigned int) const; + + /** + * Implement the copy operator needed + * for the iterator classes. + */ + void copy_from (const DoFQuadAccessor &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 +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#. 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# 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# class). + */ +template +class DoFCellAccessor : public DoFSubstructAccessor { + public: + /** + * Constructor + */ + DoFCellAccessor (Triangulation *tria, + const int level, + const int index, + const void *local_data) : + DoFSubstructAccessor (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 > 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 > 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 &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 ---------------------------*/ diff --git a/deal.II/deal.II/include/dofs/dof_constraints.h b/deal.II/deal.II/include/dofs/dof_constraints.h new file mode 100644 index 0000000000..6dda0b669c --- /dev/null +++ b/deal.II/deal.II/include/dofs/dof_constraints.h @@ -0,0 +1,296 @@ +/*---------------------------- dof_constraints.h ---------------------------*/ +/* $Id$ */ +#ifndef __dof_constraints_H +#define __dof_constraints_H +/*---------------------------- dof_constraints.h ---------------------------*/ + + +#include +#include +#include + + + +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 > 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 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 ---------------------------*/ diff --git a/deal.II/deal.II/include/dofs/dof_handler.h b/deal.II/deal.II/include/dofs/dof_handler.h new file mode 100644 index 0000000000..1d40095d09 --- /dev/null +++ b/deal.II/deal.II/include/dofs/dof_handler.h @@ -0,0 +1,996 @@ +/*---------------------------- dof.h ---------------------------*/ +/* $Id$ */ +#ifndef __dof_H +#define __dof_H +/*---------------------------- dof.h ---------------------------*/ + +#include +#include +#include + + + + +template class TriaAccessor; +template class LineAccessor; +template class QuadAccessor; +template class CellAccessor; + +template class DoFLineAccessor; +template class DoFQuadAccessor; +template class DoFCellAccessor; + + +template class TriaRawIterator; +template class TriaIterator; +template class TriaActiveIterator; + +template 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 +class DoFLevel; + + + + + +/** + Store the indices of the degrees of freedom which are located on the lines. + + {\bf Information for all #DoFLevel# classes} + + The #DoFLevel# 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# 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 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 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 +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 +class DoFHandler : public DoFDimensionInfo { + public: + /** + * Constructor. Take #tria# as the + * triangulation to work on. + */ + DoFHandler (Triangulation *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 &); + + /** + * 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 &starting_points = vector()); + + /** + * 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 &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 &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 & get_selected_fe () const; + + /** + * Return a constant reference to the + * triangulation underlying this object. + */ + const Triangulation & 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 &); + + /** + * 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 &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 &); + + /** + * 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 *tria; + + /** + * Space to store the DoF numbers for the + * different levels. Analogous to the + * #levels[]# tree of the \Ref{Triangulation} + * objects. + */ + vector*> levels; + + /** + * Store a copy of the finite element given + * latest for the distribution of dofs. + */ + FiniteElement *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 vertex_dofs; + + + friend class DoFLineAccessor >; + friend class DoFLineAccessor >; + friend class DoFQuadAccessor >; + friend class DoFQuadAccessor >; +}; + + +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 ---------------------------*/ diff --git a/deal.II/deal.II/include/fe/fe.h b/deal.II/deal.II/include/fe/fe.h new file mode 100644 index 0000000000..11e070f68c --- /dev/null +++ b/deal.II/deal.II/include/fe/fe.h @@ -0,0 +1,537 @@ +/*---------------------------- fe.h ---------------------------*/ +/* $Id$ */ +#ifndef __fe_H +#define __fe_H +/*---------------------------- fe.h ---------------------------*/ + +#include "../deal/dfmatrix.h" +#include +#include +#include + + + +// forward declarations +template class FiniteElement; +template 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 +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 &, + const Quadrature &); + + /** + * 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 & 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::cell_iterator &, + const FiniteElement &); + + /** + * 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 > > 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 > > unit_shape_gradients; + + /** + * Store an array of the weights of the + * quadrature points. This array is + * set up upon construction. + */ + vector weights; + + /** + * Store an array of weights times the + * Jacobi determinant at the quadrature + * points. This function is reset each time + * #reinit# is called. + */ + vector 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 > 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 > unit_quadrature_points; + + /** + * Store the jacobi matrices at the + * different quadrature points. This field + * is set each time #reinit# is called. + */ + vector jacobi_matrices; +}; + + + + +/** + Base class for finite elements in arbitrary dimensions. + */ +template +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& 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 shape_grad (const unsigned int i, + const Point& 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::cell_iterator &cell, + const vector > &unit_points, + vector &jacobians, + vector > &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 &) 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< +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 ---------------------------*/ diff --git a/deal.II/deal.II/include/fe/fe_lib.lagrange.h b/deal.II/deal.II/include/fe/fe_lib.lagrange.h new file mode 100644 index 0000000000..28731171ca --- /dev/null +++ b/deal.II/deal.II/include/fe/fe_lib.lagrange.h @@ -0,0 +1,62 @@ +/*---------------------------- fe_lib.h ---------------------------*/ +/* $Id$ */ +#ifndef __fe_lib_H +#define __fe_lib_H +/*---------------------------- fe_lib.h ---------------------------*/ + + +#include + + + +/** + Define a (bi-, tri-, etc)linear finite element in #dim# space dimensions. + */ +template +class FELinear : public FiniteElement { + public: + FELinear (); + virtual double shape_value(const unsigned int i, + const Point& p) const; + virtual Point shape_grad(const unsigned int i, + const Point& p) const; +}; + + + + +/** + Define a (bi-, tri-, etc)quadratic finite element in #dim# space dimensions. + */ +template +class FEQuadratic : public FiniteElement { + public: + FEQuadratic (); + virtual double shape_value(const unsigned int i, + const Point& p) const; + virtual Point shape_grad(const unsigned int i, + const Point& p) const; +}; + + + + +/** + Define a (bi-, tri-, etc)cubic finite element in #dim# space dimensions. + */ +template +class FECubic : public FiniteElement { + public: + FECubic (); + virtual double shape_value(const unsigned int i, + const Point& p) const; + virtual Point shape_grad(const unsigned int i, + const Point& p) const; +}; + + + +/*---------------------------- fe_lib.h ---------------------------*/ +/* end of #ifndef __fe_lib_H */ +#endif +/*---------------------------- fe_lib.h ---------------------------*/ diff --git a/deal.II/deal.II/include/grid/exceptions.h b/deal.II/deal.II/include/grid/exceptions.h new file mode 100644 index 0000000000..d59a48796e --- /dev/null +++ b/deal.II/deal.II/include/grid/exceptions.h @@ -0,0 +1,405 @@ +/*---------------------------- exceptions.h ---------------------------*/ +/* $Id$ */ +#ifndef __exceptions_H +#define __exceptions_H +/*---------------------------- exceptions.h ---------------------------*/ + + +#include + + + +#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 +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 (nm, 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 of file . + The violated condition was: + i +#include + + +/** + 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 &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 gradient_of_f (const Point &x)#. #Point#s have all + functionality for this, e.g. scalar products, addition etc. + */ +template +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 &); + + /** + * 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 & operator = (const Point &); + + /** + * Test for equality of two points. + */ + bool operator ==(const Point &) const; + /** + * Test for inequality of two points. + */ + bool operator !=(const Point &) const; + + /** + * Add two point vectors. If possible, use + * #operator +=# instead since this does not + * need to copy a point at least once. + */ + Point operator + (const Point &) const; + /** + * Subtract two point vectors. If possible, use + * #operator +=# instead since this does not + * need to copy a point at least once. + */ + Point operator - (const Point &) const; + + /** + * Add another vector, i.e. move this point by + * the given offset. + */ + Point & operator += (const Point &); + /** + * Subtract another vector. + */ + Point & operator -= (const Point &); + + /** + * Scale the vector by #factor#, i.e. multiply + * all coordinates by #factor#. + */ + Point & operator *= (const double &factor); + /** + * Scale the vector by #1/factor#. + */ + Point & operator /= (const double &factor); + + /** + * Returns the scalar product of two vectors. + */ + double operator * (const Point &) 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 &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 +//ostream & operator << (ostream &out, const Point &p); + + + + + + + +/*------------------------------- Inline functions: Point ---------------------------*/ + + +template +inline +Point::Point () { + Assert (dim>0, ExcDimTooSmall(dim)); + + for (int i=0; i::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 +inline +Point::Point (const Point &p) { + for (int i=0; i +inline +double Point::operator () (const int index) const { + Assert ((index>=0) && (index +inline +double & Point::operator () (const int index) { + Assert ((index>=0) && (index +inline +Point & Point::operator = (const Point &p) { + for (int i=0; i +inline +bool Point::operator == (const Point &p) const { + for (int i=0; i +inline +bool Point::operator != (const Point &p) const { + return !((*this) == p); +}; + + +template +inline +Point Point::operator + (const Point &p) const { + return (Point(*this) += p); +}; + + +template +inline +Point Point::operator - (const Point &p) const { + return (Point(*this) -= p); +}; + + +template +inline +Point & Point::operator += (const Point &p) { + for (int i=0; i +inline +Point & Point::operator -= (const Point &p) { + for (int i=0; i +inline +Point & Point::operator *= (const double &s) { + for (int i=0; i +inline +Point & Point::operator /= (const double &s) { + for (int i=0; i +inline +double Point::operator * (const Point &p) const { + double q=0; + for (int i=0; i +inline +double Point::square () const { + double q=0; + for (int i=0; i &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 ---------------------------*/ diff --git a/deal.II/deal.II/include/grid/tria.h b/deal.II/deal.II/include/grid/tria.h new file mode 100644 index 0000000000..f2a1f73a00 --- /dev/null +++ b/deal.II/deal.II/include/grid/tria.h @@ -0,0 +1,1442 @@ +/*---------------------------- tria.h ---------------------------*/ +/* $Id$ */ +#ifndef __tria_H +#define __tria_H +/*---------------------------- tria.h ---------------------------*/ + +#include +#include +#include +#include +#include "tria_boundary.h" + + +//#ifdef __GNUC__ +//# include +//class vector : +//public bit_vector {}; +//#endif + + +//forward declaration needed + +template class TriaAccessor; +template class LineAccessor; +template class QuadAccessor; +template class CellAccessor; + + +template class TriaRawIterator; +template class TriaIterator; +template class TriaActiveIterator; + +template 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 +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 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 > 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::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 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 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 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 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 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 children; + + /** + * Same as for #LineData::used#. + */ + vector used; + + /** + * Same as for #LineData::used#. + */ + vector 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 +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 Triangulation::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 Triangulation::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 + void Triangulation::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 +class Triangulation : public TriaDimensionInfo { + 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 *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# objects + * storing the data on the different + * levels. + * + * Usage is like #levels[3]->quads#. + */ + vector*> levels; + + /** + * Array of the vertices of this + * triangulation. + */ + vector > vertices; + + /** + * Array storing a bit-pattern which + * vertices are used. + */ + vector vertices_used; + + /** + * Pointer to a boundary object. + */ + const Boundary *boundary; + + + // Friendship includes local classes. + friend class TriaAccessor; + friend class LineAccessor; + friend class QuadAccessor; + + 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; +}; + + + + + + +/*---------------------------- tria.h ---------------------------*/ +/* end of #ifndef __tria_H */ +#endif +/*---------------------------- tria.h ---------------------------*/ + + + + diff --git a/deal.II/deal.II/include/grid/tria_accessor.h b/deal.II/deal.II/include/grid/tria_accessor.h new file mode 100644 index 0000000000..4d23f76416 --- /dev/null +++ b/deal.II/deal.II/include/grid/tria_accessor.h @@ -0,0 +1,861 @@ +/*---------------------------- tria_accessor.h ---------------------------*/ +/* $Id$ */ +#ifndef __tria_accessor_H +#define __tria_accessor_H +/*---------------------------- tria_accessor.h ---------------------------*/ + + +#include + + +// forward declaration needed +class Line; +class Quad; +template class Point; + + +template class TriaAccessor; +template class LineAccessor; +template class QuadAccessor; +template class CellAccessor; + +template class DoFCellAccessor; +template class DoFLineAccessor; + +template class TriaRawIterator; +template class TriaIterator; +template class TriaActiveIterator; + +template 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 +class TriaAccessor { + protected: + /** + * Constructor. Protected, thus + * only callable from friend + * classes. + */ + TriaAccessor (Triangulation *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 *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 +class LineAccessor : public TriaAccessor { + public: + /** + * Constructor. + */ + LineAccessor (Triangulation *parent = 0, + const int level = -1, + const int index = -1, + const void *local_data = 0) : + TriaAccessor (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 & 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 > 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 +class QuadAccessor : public TriaAccessor { + public: + /** + * Constructor. + */ + QuadAccessor (Triangulation *parent = 0, + const int level = -1, + const int index = -1, + const void *local_data = 0) : + TriaAccessor (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 & vertex (const unsigned int i) const; + + /** + * Return a pointer to the #i#th line + * bounding this #Quad#. + */ + TriaIterator > 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 > 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 +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 ---------------------------*/ diff --git a/deal.II/deal.II/include/grid/tria_boundary.h b/deal.II/deal.II/include/grid/tria_boundary.h new file mode 100644 index 0000000000..4bf0245e90 --- /dev/null +++ b/deal.II/deal.II/include/grid/tria_boundary.h @@ -0,0 +1,80 @@ +/*---------------------------- boundary-function.h ---------------------------*/ +/* $Id$ */ +#ifndef __tria_boundary_H +#define __tria_boundary_H +/*---------------------------- boundary-function.h ---------------------------*/ + +#include + +/** + 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#. + + 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#, which places + the new point right into the middle of the given points. + */ +template +class Boundary { + public: + /** + * Typedef an array of the needed number + * of old points. + */ + typedef const Point* PointArray[1<<(dim-1)]; + + /** + * This function calculates the position + * of the new vertex. + */ + virtual Point in_between (const PointArray &neighbors) const = 0; +}; + + + + + +/** + Specialisation of \Ref{Boundary}, 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 +class StraightBoundary : public Boundary { + public: + /** + * This function calculates the position + * of the new vertex. + */ + virtual Point in_between (const PointArray &neighbors) const { + Point 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 ---------------------------*/ diff --git a/deal.II/deal.II/include/grid/tria_iterator.h b/deal.II/deal.II/include/grid/tria_iterator.h new file mode 100644 index 0000000000..8686317690 --- /dev/null +++ b/deal.II/deal.II/include/grid/tria_iterator.h @@ -0,0 +1,744 @@ +/*---------------------------- tria-iterator.h ---------------------------*/ +/* $Id$ */ +#ifndef __tria_iterator_H +#define __tria_iterator_H +/*---------------------------- tria-iterator.h ---------------------------*/ + + + +#include +#include +#include +#include +#include + + + + + +// forward declaration needed +template 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*#, + 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 +class TriaRawIterator : public bidirectional_iterator { + 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 *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 +class TriaIterator : public TriaRawIterator { + public: + /** + * Empty constructor. Such an object + * is not usable! + */ + TriaIterator (); + + /** + * Copy constructor. + */ + TriaIterator (const TriaIterator &); + + /** + * 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 &); + + /** + * 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 *parent, + const int level, + const int index, + const void *local_data=0); + + /** + * Assignment operator. + */ + TriaIterator & + operator = (const TriaIterator &); + + /** + * Cross assignment operator. This + * assignment is only valid if the + * given iterator points to a used + * element. + */ + TriaIterator & + operator = (const TriaRawIterator &); + + /**@name Advancement of iterators*/ + /*@{*/ + /** + * Prefix #++# operator: #++i#. This + * operator advances the iterator to + * the next used element and returns + * a reference to #*this#. + */ + TriaIterator & 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 operator ++ (int); + + /** + * Prefix #--# operator: #--i#. This + * operator advances the iterator to + * the previous used element and returns + * a reference to #*this#. + */ + TriaIterator & operator -- (); + + /** + * Postfix #--# operator: #i--#. + */ + TriaIterator 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 +class TriaActiveIterator : public TriaIterator { + public: + /** + * Empty constructor. Such an object + * is not usable! + */ + TriaActiveIterator (); + + /** + * Copy constructor. + */ + TriaActiveIterator (const TriaActiveIterator &); + + /** + * 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 &); + + /** + * 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 &); + + /** + * 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 *parent, + const int level, + const int index, + const void *local_data=0); + + /** + * Assignment operator. + */ + TriaActiveIterator & + operator = (const TriaActiveIterator &); + + /** + * Cross assignment operator. This + * assignment is only valid if the + * given iterator points to an active + * element or past the end. + */ + TriaActiveIterator & + operator = (const TriaRawIterator &); + + /** + * Cross assignment operator. This + * assignment is only valid if the + * given iterator points to an active + * element or past the end. + */ + TriaActiveIterator & + operator = (const TriaIterator &); + + /** + * Prefix #++# operator: #++i#. This + * operator advances the iterator to + * the next active element and returns + * a reference to #*this#. + */ + TriaActiveIterator & 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 operator ++ (int); + + /** + * Prefix #--# operator: #--i#. This + * operator advances the iterator to + * the previous active element and + * returns a reference to #*this#. + */ + TriaActiveIterator & operator -- (); + + /** + * Postfix #--# operator: #i--#. + */ + TriaActiveIterator operator -- (int); + /*@}*/ + + /** + * Exception + */ + DeclException0 (ExcAssignmentOfInactiveObject); +}; + + + + +template +inline +IteratorState TriaRawIterator::state () const { + return accessor.state (); +}; + + + +template +inline +TriaRawIterator & +TriaRawIterator::operator ++ () { + Assert (state() == valid, ExcAdvanceInvalidObject()); + + ++accessor; + return *this; +}; + + + +template +inline +TriaRawIterator & +TriaRawIterator::operator -- () { + Assert (state() == valid, ExcAdvanceInvalidObject()); + + --accessor; + return *this; +}; + + + +template +inline +ostream & operator << (ostream &out, const TriaRawIterator &i) { + i.print(out); + return out; +}; + +template +inline +ostream & operator << (ostream &out, const TriaIterator &i) { + i.print(out); + return out; +}; + +template +inline +ostream & operator << (ostream &out, const TriaActiveIterator &i) { + i.print(out); + return out; +}; + + + +/*---------------------------- tria-iterator.h ---------------------------*/ +/* end of #ifndef __tria_iterator_H */ +#endif +/*---------------------------- tria-iterator.h ---------------------------*/ + + diff --git a/deal.II/deal.II/include/grid/tria_iterator.templates.h b/deal.II/deal.II/include/grid/tria_iterator.templates.h new file mode 100644 index 0000000000..4e053c84ac --- /dev/null +++ b/deal.II/deal.II/include/grid/tria_iterator.templates.h @@ -0,0 +1,384 @@ +/* $Id$ */ + +#include +#include + + +/* 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 +TriaRawIterator::TriaRawIterator () : + accessor (0, -2, -2, 0) {}; + + + +template +TriaRawIterator::TriaRawIterator (const TriaRawIterator &i) : + accessor (i.accessor) {}; + + + +template +TriaRawIterator::TriaRawIterator (Triangulation *parent, + const int level, + const int index, + const void *local_data) : + accessor (parent, level, index, local_data) {}; + + + +template +TriaRawIterator & +TriaRawIterator::operator = (const TriaRawIterator &i) { + accessor.copy_from (i.accessor); + + return *this; +}; + + + +template +bool +TriaRawIterator::operator == (const TriaRawIterator &i) const { + return accessor == i.accessor; +}; + + + +template +bool +TriaRawIterator::operator != (const TriaRawIterator &i) const { + return accessor != i.accessor; +}; + + + +template +TriaRawIterator TriaRawIterator::operator ++ (int) { + TriaRawIterator tmp(*this); + this->operator++ (); + + return tmp; +}; + + + +template +TriaRawIterator TriaRawIterator::operator -- (int) { + TriaRawIterator tmp(*this); + this->operator-- (); + + return tmp; +}; + + + + +/*----------------------- functions: TriaIterator ---------------*/ + + +template +TriaIterator::TriaIterator () : + TriaRawIterator () {}; + + +template +TriaIterator:: +TriaIterator (const TriaIterator &i) : + TriaRawIterator ((TriaRawIterator)i) {}; + + + +template +TriaIterator:: +TriaIterator (const TriaRawIterator &i) : + TriaRawIterator (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 +TriaIterator::TriaIterator (Triangulation *parent, + const int level, + const int index, + const void *local_data) : + TriaRawIterator (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 +TriaIterator & +TriaIterator::operator = (const TriaIterator &i) { + accessor.copy_from (i.accessor); + return *this; +}; + + +template +TriaIterator & +TriaIterator::operator = (const TriaRawIterator &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 +TriaIterator & TriaIterator::operator ++ () { + while (TriaRawIterator::operator++(), + (state() == valid)) + if (accessor.used() == true) + return *this; + return *this; +}; + + + +template +TriaIterator TriaIterator::operator ++ (int) { + TriaIterator tmp(*this); + this->operator++ (); + + return tmp; +}; + + + +template +TriaIterator & TriaIterator::operator -- () { + while (TriaRawIterator::operator--(), + (state() == valid)) + if (accessor.used() == true) + return *this; + return *this; +}; + + +template +TriaIterator TriaIterator::operator -- (int) { + TriaIterator tmp(*this); + this->operator-- (); + + return tmp; +}; + + + +/*----------------------- functions: TriaActiveIterator ---------------*/ + + +template +TriaActiveIterator::TriaActiveIterator () : + TriaIterator () {}; + + + +template +TriaActiveIterator:: +TriaActiveIterator (const TriaActiveIterator &i) : + TriaIterator ((TriaIterator) i) {}; + + + +template +TriaActiveIterator:: +TriaActiveIterator (const TriaRawIterator &i) : + TriaIterator (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 +TriaActiveIterator:: +TriaActiveIterator (const TriaIterator &i) : + TriaIterator (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 +TriaActiveIterator::TriaActiveIterator (Triangulation *parent, + const int level, + const int index, + const void *local_data) : + TriaIterator (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 +TriaActiveIterator & +TriaActiveIterator::operator = (const TriaActiveIterator &i) { + accessor.copy_from (i.accessor); + return *this; +}; + + + +template +TriaActiveIterator & +TriaActiveIterator::operator = (const TriaRawIterator &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 +TriaActiveIterator & +TriaActiveIterator::operator = (const TriaIterator &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 +TriaActiveIterator & TriaActiveIterator::operator ++ () { + while (TriaIterator::operator++(), + (state() == valid)) + if (accessor.has_children() == false) + return *this; + return *this; +}; + + + +template +TriaActiveIterator TriaActiveIterator::operator ++ (int) { + TriaActiveIterator tmp(*this); + this->operator++ (); + + return tmp; +}; + + + +template +TriaActiveIterator & TriaActiveIterator::operator -- () { + while (TriaIterator::operator--(), + (state() == valid)) + if (accessor.has_children() == false) + return *this; + return *this; +}; + + + +template +TriaActiveIterator TriaActiveIterator::operator -- (int) { + TriaActiveIterator tmp(*this); + this->operator-- (); + + return tmp; +}; + + + + + + + + + diff --git a/deal.II/deal.II/include/grid/tria_line.h b/deal.II/deal.II/include/grid/tria_line.h new file mode 100644 index 0000000000..8d001c7bf2 --- /dev/null +++ b/deal.II/deal.II/include/grid/tria_line.h @@ -0,0 +1,90 @@ +/*---------------------------- tria_line.h ---------------------------*/ +/* $Id$ */ +#ifndef __tria_line_H +#define __tria_line_H +/*---------------------------- tria_line.h ---------------------------*/ + +#include + + +/** + 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 ---------------------------*/ diff --git a/deal.II/deal.II/include/grid/tria_quad.h b/deal.II/deal.II/include/grid/tria_quad.h new file mode 100644 index 0000000000..f42f0f0875 --- /dev/null +++ b/deal.II/deal.II/include/grid/tria_quad.h @@ -0,0 +1,98 @@ +/*---------------------------- tria_quad.h ---------------------------*/ +/* $Id$ */ +#ifndef __tria_quad_H +#define __tria_quad_H +/*---------------------------- tria_quad.h ---------------------------*/ + + +#include + +/** + #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 ---------------------------*/ diff --git a/deal.II/deal.II/include/numerics/assembler.h b/deal.II/deal.II/include/numerics/assembler.h new file mode 100644 index 0000000000..0d6282aad9 --- /dev/null +++ b/deal.II/deal.II/include/numerics/assembler.h @@ -0,0 +1,215 @@ +/*---------------------------- problem_assembler.h ---------------------------*/ +/* $Id$ */ +#ifndef __problem_assembler_H +#define __problem_assembler_H +/*---------------------------- problem_assembler.h ---------------------------*/ + +#include +#include +#include +#include +#include + + +// forward declarations +class dFMatrix; +class dVector; +template 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 +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 &rhs, + const FEValues &fe_values, + const Triangulation::cell_iterator &cell) const; + + /** + * Virtual function which only assembles + * the cell matrix on a given cell. + */ + virtual void assemble (dFMatrix &cell_matrix, + const FEValues &fe_values, + const Triangulation::cell_iterator &cell) const; + + /** + * Virtual function which only assembles + * the right hand side(s) on a given cell. + */ + virtual void assemble (vector &rhs, + const FEValues &fe_values, + const Triangulation::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 +class Assembler : public DoFCellAccessor { + 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 *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 *problem; + /** + * Pointer to a quadrature object to be + * used for this assemblage process. + */ + Quadrature *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 *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 &); + + /** + * 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 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 *problem; + + /** + * The finite element evaluated at the + * quadrature points. + */ + FEValues fe_values; +}; + + + + + +/*---------------------------- problem_assembler.h ---------------------------*/ +/* end of #ifndef __problem_assembler_H */ +#endif +/*---------------------------- problem_assembler.h ---------------------------*/ diff --git a/deal.II/deal.II/include/numerics/base.h b/deal.II/deal.II/include/numerics/base.h new file mode 100644 index 0000000000..3d4a0df33b --- /dev/null +++ b/deal.II/deal.II/include/numerics/base.h @@ -0,0 +1,49 @@ +/*---------------------------- problem_base.h ---------------------------*/ +/* $Id$ */ +#ifndef __problem_base_H +#define __problem_base_H +/*---------------------------- problem_base.h ---------------------------*/ + + +#include "../deal/dsmatrix.h" + + +// forward declaration +template class Triangulation; +template class DoFHandler; +template class FiniteElement; +template class Quadrature; + + + + + +template +class ProblemBase { + public: + ProblemBase (Triangulation *tria, + DoFHandler *dof_handler); + + virtual void assemble (const Equation &equation, + const Quadrature &q); + + protected: + Triangulation *tria; + DoFHandler *dof_handler; + + dSMatrix system_matrix; + dSMatrixStruct system_sparsity; + + vector right_hand_sides; + dVector solution; + + friend class Assembler; +}; + + + + +/*---------------------------- problem_base.h ---------------------------*/ +/* end of #ifndef __problem_base_H */ +#endif +/*---------------------------- problem_base.h ---------------------------*/ diff --git a/deal.II/deal.II/include/numerics/data_io.h b/deal.II/deal.II/include/numerics/data_io.h new file mode 100644 index 0000000000..8925a7241f --- /dev/null +++ b/deal.II/deal.II/include/numerics/data_io.h @@ -0,0 +1,200 @@ +/*---------------------------- io.h ---------------------------*/ +/* */ +#ifndef __data_io_H +#define __data_io_H +/*---------------------------- io.h ---------------------------*/ + +#include +#include + +#ifdef DEBUG +# define _G_NO_NRV // don't use GNU's named return values in debug modes +# include // because if we did we'd harvest tons of warnings. +# undef _G_NO_NRV +#else +# include +#endif + + +template +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::write_gnuplot()# somehow + duplicates the functionality of the #Triangulation::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 +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 &); + + /** + * Add a data vector together with its + * name and the physical unit + * (e.g. meter, kelvin, etc). By default, + * "" 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=""); + + /** + * 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 *dofs; + + /** + * List of data elements. + */ + vector data; +}; + + + + + +/*---------------------------- io.h ---------------------------*/ +/* end of #ifndef __data_io_H */ +#endif +/*---------------------------- io.h ---------------------------*/ diff --git a/deal.II/deal.II/source/Makefile b/deal.II/deal.II/source/Makefile new file mode 100644 index 0000000000..893b848a49 --- /dev/null +++ b/deal.II/deal.II/source/Makefile @@ -0,0 +1,26 @@ +# $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 diff --git a/deal.II/deal.II/source/dofs/dof_accessor.cc b/deal.II/deal.II/source/dofs/dof_accessor.cc new file mode 100644 index 0000000000..8252274496 --- /dev/null +++ b/deal.II/deal.II/source/dofs/dof_accessor.cc @@ -0,0 +1,321 @@ +/* $Id$ */ + + +#include +#include +#include +#include +#include + + +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 DoFLineAccessor::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 (iselected_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 +void DoFLineAccessor::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 (iselected_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 DoFLineAccessor::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 (iselected_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 +void DoFLineAccessor::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 (iselected_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 +TriaIterator > +DoFLineAccessor::child (const unsigned int i) const { + TriaIterator > 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 +void DoFLineAccessor::copy_from (const DoFLineAccessor &a) { + BaseClass::copy_from (a); + set_dof_handler (a.dof_handler); +}; + + + +/*------------------------- Functions: DoFQuadAccessor -----------------------*/ + + +template +int DoFQuadAccessor::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 (iselected_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 +void DoFQuadAccessor::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 (iselected_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 DoFQuadAccessor::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 (iselected_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 +void DoFQuadAccessor::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 (iselected_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 +TriaIterator > > +DoFQuadAccessor::line (const unsigned int i) const { + Assert (i<4, ExcInvalidIndex (i, 0, 4)); + + return TriaIterator > > + ( + tria, + present_level, + line_index (i), + dof_handler + ); +}; + + + +template +TriaIterator > +DoFQuadAccessor::child (const unsigned int i) const { + TriaIterator > 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 +void DoFQuadAccessor::copy_from (const DoFQuadAccessor &a) { + Assert (a.dof_handler != 0, ExcInvalidObject()); + + BaseClass::copy_from (a); + set_dof_handler (a.dof_handler); +}; + + + +/*------------------------- Functions: DoFCellAccessor -----------------------*/ + +template +TriaIterator > +DoFCellAccessor::neighbor (const unsigned int i) const { + TriaIterator > 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 +TriaIterator > +DoFCellAccessor::child (const unsigned int i) const { + TriaIterator > 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 &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; dget_selected_fe().dofs_per_vertex; ++d) + dof_indices.push_back (vertex_dof_index(vertex,d)); + for (unsigned int d=0; dget_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 &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; dget_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; dget_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> >; + diff --git a/deal.II/deal.II/source/dofs/dof_constraints.cc b/deal.II/deal.II/source/dofs/dof_constraints.cc new file mode 100644 index 0000000000..5a605d070d --- /dev/null +++ b/deal.II/deal.II/source/dofs/dof_constraints.cc @@ -0,0 +1,252 @@ +/* $Id$ */ + + +#include +#include +#include "../deal/dsmatrix.h" +#include + + + + +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::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::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(); + 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 new_line; + + new_line.reserve (uncondensed.n_rows()); + + vector::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::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::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 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 +#include +#include +#include +#include +#include +#include "../deal/dsmatrix.h" +#include +#include + + +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 +DoFHandler::DoFHandler (Triangulation *tria) : + tria(tria), + selected_fe (0), + used_dofs (0) {}; + + +template +DoFHandler::~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 +unsigned int DoFHandler::n_dofs () const { + return used_dofs; +}; + + + +template +const Triangulation & DoFHandler::get_tria () const { + return *tria; +}; + + + +template +const FiniteElement & DoFHandler::get_selected_fe () const { + return *selected_fe; +}; + + + +template +void DoFHandler::distribute_dofs (const FiniteElement &fe) { + Assert (tria->n_levels() > 0, ExcInvalidTriangulation()); + + reserve_space (fe); + if (selected_fe != 0) delete selected_fe; + selected_fe = new FiniteElement(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; dset_vertex_dof_index (0, d, neighbor->vertex_dof_index (1, d)); + else + for (unsigned int d=0; dset_vertex_dof_index (1, d, neighbor->vertex_dof_index (0, d)); + + // next neighbor + continue; + }; + }; + + // otherwise: create dofs newly + for (unsigned int d=0; dset_vertex_dof_index (v, d, next_free_dof++); + }; + + // dofs of line + for (unsigned int d=0; dset_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; dset_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; dset_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; dset_dof_index (d, next_free_dof++); + + + // note that this cell has been processed + cell->set_user_flag (); + + return next_free_dof; +}; + + + + +template +void DoFHandler::renumber_dofs (const RenumberingMethod method, + bool use_constraints, + const vector &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 new_number(sparsity.n_rows(), -1); + + // store the indices of the dofs renumbered + // in the last round. Default to starting + // points + vector last_round_dofs (starting_points); + // delete disallowed elements + for (unsigned int i=0; i=n_dofs)) + last_round_dofs[i] = -1; + remove_if (last_round_dofs.begin(), last_round_dofs.end(), + bind2nd(equal_to(), 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 next_round_dofs; + + // find all neighbors of the + // dofs numbered in the last + // round + for (unsigned int i=0; i::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 > dofs_by_coordination; + + // find coordination number for + // each of these dofs + for (vector::iterator s=next_round_dofs.begin(); + s!=next_round_dofs.end(); ++s) + { + unsigned int coordination = 0; + for (int j=sparsity.rowstart[*s]; j new_entry (coordination, *s); + dofs_by_coordination.insert (new_entry); + }; + + //// + multimap >::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::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 &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::iterator i=vertex_dofs.begin(); i!=vertex_dofs.end(); ++i) + if (*i != -1) + *i = new_numbers[*i]; + + for (unsigned int level=0; level::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 &new_numbers) { + for (vector::iterator i=vertex_dofs.begin(); i!=vertex_dofs.end(); ++i) + if (*i != -1) + *i = new_numbers[*i]; + + for (unsigned int level=0; level::iterator i=levels[level]->line_dofs.begin(); + i!=levels[level]->line_dofs.end(); ++i) + if (*i != -1) + *i = new_numbers[*i]; + for (vector::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 dofs_on_mother; + vector 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; ddofs_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; ddofs_per_line; ++d) + dofs_on_this_cell[dof_number++] = cell->dof_index (d); + + // make sparsity pattern for this cell + for (unsigned int i=0; itotal_dofs; ++i) + for (unsigned int j=0; jtotal_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; ddofs_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; ddofs_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; ddofs_per_quad; ++d) + dofs_on_this_cell[dof_number++] = cell->dof_index (d); + + // make sparsity pattern for this cell + for (unsigned int i=0; itotal_dofs; ++i) + for (unsigned int j=0; jtotal_dofs; ++j) + sparsity.add (dofs_on_this_cell[i], + dofs_on_this_cell[j]); + }; + + delete[] dofs_on_this_cell; +}; + + + +template +void DoFHandler::make_transfer_matrix (const DoFHandler &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<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 +void DoFHandler::make_transfer_matrix (const DoFHandler &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 +void DoFHandler::transfer_cell (const TriaIterator > &old_cell, + const TriaIterator > &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<child(child), new_cell->child(child), + transfer_pattern); + else + if (new_cell->active() && old_cell->active()) + // both cells have no children + { + vector 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; jactive() && old_cell->active()) + // new cell has children, old one has not + { + cell_iterator child[1<child(c); + Assert (child[c]->active(), + ExcOnlyOnelevelTransferImplemented()); + }; + + // numbers of old dofs + vector 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< 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; ktotal_dofs; ++k) + for (unsigned int j=0; jtotal_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<child(c); + Assert (child[c]->active(), + ExcOnlyOnelevelTransferImplemented()); + }; + + // numbers of new dofs + vector 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< 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; ktotal_dofs; ++k) + for (unsigned int j=0; jtotal_dofs; ++j) + if (selected_fe->restrict(c)(k,j) != 0.) + transfer_pattern.add (new_dof_indices[k], + child_dof_indices[j]); + }; + }; +}; + + + +template +void DoFHandler::transfer_cell (const TriaIterator > &old_cell, + const TriaIterator > &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<child(child), new_cell->child(child), + transfer_matrix); + else + if (new_cell->active() && old_cell->active()) + // both cells have no children + { + vector 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; jactive() && old_cell->active()) + // new cell has children, old one has not + { + cell_iterator child[1<child(c); + Assert (child[c]->active(), + ExcOnlyOnelevelTransferImplemented()); + }; + + // numbers of old dofs + vector 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< 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; ktotal_dofs; ++k) + for (unsigned int j=0; jtotal_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<child(c); + Assert (child[c]->active(), + ExcOnlyOnelevelTransferImplemented()); + }; + + // numbers of new dofs + vector 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< 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; ktotal_dofs; ++k) + for (unsigned int j=0; jtotal_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; ivertices.size()); + vertex_dofs.insert (vertex_dofs.end(), + tria->vertices.size(), + -1); + + for (unsigned int i=0; in_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; ivertices.size()); + vertex_dofs.insert (vertex_dofs.end(), + tria->vertices.size(), + -1); + + for (unsigned int i=0; in_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>; + + + diff --git a/deal.II/deal.II/source/fe/Makefile b/deal.II/deal.II/source/fe/Makefile new file mode 100644 index 0000000000..aa2591854a --- /dev/null +++ b/deal.II/deal.II/source/fe/Makefile @@ -0,0 +1,62 @@ +# $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 diff --git a/deal.II/deal.II/source/fe/Makefile.dep b/deal.II/deal.II/source/fe/Makefile.dep new file mode 100644 index 0000000000..9866009022 --- /dev/null +++ b/deal.II/deal.II/source/fe/Makefile.dep @@ -0,0 +1,176 @@ +../../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 diff --git a/deal.II/deal.II/source/fe/fe.cc b/deal.II/deal.II/source/fe/fe.cc new file mode 100644 index 0000000000..501a17d0b4 --- /dev/null +++ b/deal.II/deal.II/source/fe/fe.cc @@ -0,0 +1,249 @@ +/* $Id$ */ + +#include +#include + + + +/*------------------------------- FEValues -------------------------------*/ + + +template +FEValues::FEValues (const FiniteElement &fe, + const Quadrature &quadrature) : + shape_values(fe.total_dofs, quadrature.n_quad_points), + shape_gradients(fe.total_dofs, + vector >(quadrature.n_quad_points)), + unit_shape_gradients(fe.total_dofs, + vector >(quadrature.n_quad_points)), + weights(quadrature.n_quad_points, 0), + JxW_values(quadrature.n_quad_points, 0), + quadrature_points(quadrature.n_quad_points, Point()), + unit_quadrature_points(quadrature.n_quad_points, Point()), + jacobi_matrices (quadrature.n_quad_points) +{ + for (unsigned int i=0; i +double FEValues::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 +const Point & +FEValues::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::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 +FiniteElementBase::FiniteElementBase (const FiniteElementBase &f) : + total_dofs(f.total_dofs), + interface_constraints (f.interface_constraints) +{ + for (unsigned int i=0; i<(1< +const dFMatrix & +FiniteElementBase::restrict (const unsigned int child) const { + Assert (child<(1< +const dFMatrix & +FiniteElementBase::prolongate (const unsigned int child) const { + Assert (child<(1< +const dFMatrix & +FiniteElementBase::constraints () const { + return interface_constraints; +}; + + + +template +bool FiniteElementBase::operator == (const FiniteElementBase &f) const { + return ((total_dofs == f.total_dofs) && + (interface_constraints == f.interface_constraints)); +}; + + + +template +double FiniteElementBase::shape_value (const unsigned int, + const Point &) const { + Assert (false, ExcPureFunctionCalled()); + return 0; +}; + + + +template +Point FiniteElementBase::shape_grad (const unsigned int, + const Point &) const { + Assert (false, ExcPureFunctionCalled()); + return Point(); +}; + + + +void FiniteElementBase<1>::fill_fe_values (const Triangulation<1>::cell_iterator &, + const vector > &, + vector &, + vector > &) const { + Assert (false, ExcPureFunctionCalled()); +}; + + + +void FiniteElementBase<2>::fill_fe_values (const Triangulation<2>::cell_iterator &, + const vector > &, + vector &, + vector > &) 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>; diff --git a/deal.II/deal.II/source/fe/fe_lib.linear.cc b/deal.II/deal.II/source/fe/fe_lib.linear.cc new file mode 100644 index 0000000000..a56521b238 --- /dev/null +++ b/deal.II/deal.II/source/fe/fe_lib.linear.cc @@ -0,0 +1,238 @@ +/* $Id$ */ + +#include + + + +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 +FELinear<1>::shape_grad(const unsigned int i, + const Point<1>&) const +{ + Assert((i(-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 +FELinear<2>::shape_grad(const unsigned int i, + const Point<2>& p) const +{ + Assert((i (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) {}; + diff --git a/deal.II/deal.II/source/grid/Makefile b/deal.II/deal.II/source/grid/Makefile new file mode 100644 index 0000000000..aa2591854a --- /dev/null +++ b/deal.II/deal.II/source/grid/Makefile @@ -0,0 +1,62 @@ +# $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 diff --git a/deal.II/deal.II/source/grid/Makefile.dep b/deal.II/deal.II/source/grid/Makefile.dep new file mode 100644 index 0000000000..93da71b1d0 --- /dev/null +++ b/deal.II/deal.II/source/grid/Makefile.dep @@ -0,0 +1,340 @@ +../../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 diff --git a/deal.II/deal.II/source/grid/tria.cc b/deal.II/deal.II/source/grid/tria.cc new file mode 100644 index 0000000000..1b4aa3cccf --- /dev/null +++ b/deal.II/deal.II/source/grid/tria.cc @@ -0,0 +1,2040 @@ +/* $Id$ */ + +#include +#include +#include +#include +#include + + + +template +Triangulation::Triangulation () { + static StraightBoundary default_boundary; + boundary = &default_boundary; + + levels.push_back (new TriangulationLevel); +}; + + +template +Triangulation::~Triangulation () { + for (unsigned int i=0; i +void Triangulation::set_boundary (const Boundary *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 +void Triangulation::set_all_refine_flags () { + active_cell_iterator cell = begin_active(), + endc = end(); + + for (; cell != endc; ++cell) + cell->set_refine_flag (); +}; + + + +template +void Triangulation::refine_global (const unsigned int times) { + for (unsigned int i=0; i +void Triangulation::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; irefine_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 +void Triangulation::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> 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 +void Triangulation::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; iuser_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 +void Triangulation::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> 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 +void Triangulation::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; iuser_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::load_user_flags_quad (istream &) { + Assert (false, ExcFunctionNotUseful()); +}; + + + +template +void Triangulation::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> 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 (levellines.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 (levellines.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 (levelquads.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*)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*)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*)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 +unsigned int Triangulation::n_cells () const { + unsigned int n=0; + for (unsigned int l=0; l::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 +unsigned int Triangulation::n_active_cells () const { + unsigned int n=0; + for (unsigned int l=0; l::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 +unsigned int Triangulation::n_lines () const { + unsigned int n=0; + for (unsigned int l=0; l +unsigned int Triangulation::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 +unsigned int Triangulation::n_active_lines () const { + unsigned int n=0; + for (unsigned int l=0; l +unsigned int Triangulation::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 +unsigned int Triangulation::n_quads () const { + unsigned int n=0; + for (unsigned int l=0; l::n_quads (const unsigned int) const { + Assert (false, ExcFunctionNotUseful()); + return 0; +}; + + + +template +unsigned int Triangulation::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 +unsigned int Triangulation::n_active_quads () const { + unsigned int n=0; + for (unsigned int l=0; l::n_active_quads (const unsigned int) const { + Assert (false, ExcFunctionNotUseful()); + return 0; +}; + + + +template +unsigned int Triangulation::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 +unsigned int Triangulation::n_levels () const { + return levels.size(); +}; + + + +unsigned int Triangulation<1>::max_adjacent_cells () const { + return 2; +}; + + + +template +unsigned int Triangulation::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<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 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<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< +void Triangulation::print_gnuplot (ostream &out) const { + for (unsigned int i=0; i +void Triangulation::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(), 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(), 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; levelmonitor_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(), 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(), 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(), 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; levelmonitor_memory (2); +#endif +}; + + + + +template +void Triangulation::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); + 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::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::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>; + diff --git a/deal.II/deal.II/source/grid/tria_accessor.cc b/deal.II/deal.II/source/grid/tria_accessor.cc new file mode 100644 index 0000000000..353d2a457d --- /dev/null +++ b/deal.II/deal.II/source/grid/tria_accessor.cc @@ -0,0 +1,596 @@ +/* $Id$ */ + +#include +#include +#include +#include + +/* Note: explicit instantiations at the end of the different sections! */ + + + +/*------------------------ Functions: LineAccessor ---------------------------*/ + +template +void TriaAccessor::copy_from (const TriaAccessor &a) { + present_level = a.present_level; + present_index = a.present_index; + tria = a.tria; +}; + + + +template +bool TriaAccessor::operator == (const TriaAccessor &a) const { + return ((present_level == a.present_level) && + (present_index == a.present_index) && + (tria == a.tria)); +}; + + + +template +bool TriaAccessor::operator != (const TriaAccessor &a) const { + return ((present_level != a.present_level) || + (present_index != a.present_index) || + (tria != a.tria)); +}; + + + +template +int TriaAccessor::level () const { + return present_level; +}; + + + +template +int TriaAccessor::index () const { + return present_index; +}; + + + + +template +IteratorState TriaAccessor::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 +void LineAccessor::set (const Line &line) const { + tria->levels[present_level]->lines.lines[present_index] = line; +}; + + + +template +int LineAccessor::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 +Point & +LineAccessor::vertex (const unsigned int i) const { + return tria->vertices[vertex_index(i)]; +}; + + + +template +bool LineAccessor::used () const { + Assert (state() == valid, ExcDereferenceInvalidObject()); + return tria->levels[present_level]->lines.used[present_index]; +}; + + + +template +void LineAccessor::set_used_flag () const { + Assert (state() == valid, ExcDereferenceInvalidObject()); + tria->levels[present_level]->lines.used[present_index] = true; +}; + + + +template +void LineAccessor::clear_used_flag () const { + Assert (state() == valid, ExcDereferenceInvalidObject()); + tria->levels[present_level]->lines.used[present_index] = false; +}; + + +template +bool LineAccessor::user_flag_set () const { + Assert (used(), ExcRefineCellNotActive()); + return tria->levels[present_level]->lines.user_flags[present_index]; +}; + + + +template +void LineAccessor::set_user_flag () const { + Assert (used(), ExcCellNotUsed()); + tria->levels[present_level]->lines.user_flags[present_index] = true; +}; + + + +template +void LineAccessor::clear_user_flag () const { + Assert (used(), ExcCellNotUsed()); + tria->levels[present_level]->lines.user_flags[present_index] = false; +}; + + + +template +TriaIterator > +LineAccessor::child (const unsigned int i) const { + Assert (i<2, ExcInvalidIndex(i,0,1)); + + TriaIterator > 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 LineAccessor::child_index (unsigned int i) const { + Assert (i<2, ExcInvalidIndex(i,0,1)); + return tria->levels[present_level]->lines.children[present_index]+i; +}; + + + + +template +void LineAccessor::set_children (const int index) const { + Assert (used(), ExcRefineCellNotUsed()); + tria->levels[present_level]->lines.children[present_index] = index; +}; + + + +template +void LineAccessor::clear_children () const { + set_children (-1); +}; + + + +template +bool LineAccessor::has_children () const { + Assert (state() == valid, ExcDereferenceInvalidObject()); + return (tria->levels[present_level]->lines.children[present_index] != -1); +} + + + +template +void LineAccessor::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 +void LineAccessor::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 +void QuadAccessor::set (const Quad &quad) const { + tria->levels[present_level]->quads.quads[present_index] = quad; +}; + + + +template +int QuadAccessor::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 +Point & +QuadAccessor::vertex (const unsigned int i) const { + return tria->vertices[vertex_index(i)]; +}; + + + +template +bool QuadAccessor::used () const { + Assert (state() == valid, ExcDereferenceInvalidObject()); + return tria->levels[present_level]->quads.used[present_index]; +}; + + + +template +void QuadAccessor::set_used_flag () const { + Assert (state() == valid, ExcDereferenceInvalidObject()); + tria->levels[present_level]->quads.used[present_index] = true; +}; + + + +template +void QuadAccessor::clear_used_flag () const { + Assert (state() == valid, ExcDereferenceInvalidObject()); + tria->levels[present_level]->quads.used[present_index] = false; +}; + + + + +template +bool QuadAccessor::user_flag_set () const { + Assert (used(), ExcRefineCellNotActive()); + return tria->levels[present_level]->quads.user_flags[present_index]; +}; + + + +template +void QuadAccessor::set_user_flag () const { + Assert (used(), ExcCellNotUsed()); + tria->levels[present_level]->quads.user_flags[present_index] = true; +}; + + + +template +void QuadAccessor::clear_user_flag () const { + Assert (used(), ExcCellNotUsed()); + tria->levels[present_level]->quads.user_flags[present_index] = false; +}; + + + + +template +TriaIterator > +QuadAccessor::line (const unsigned int i) const { + return + TriaIterator > + ( + tria, + present_level, + line_index (i) + ); +}; + + + +template +unsigned int QuadAccessor::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 +TriaIterator > +QuadAccessor::child (const unsigned int i) const { + Assert (i<4, ExcInvalidIndex(i,0,3)); + + TriaIterator<2,QuadAccessor > 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 QuadAccessor::child_index (unsigned int i) const { + Assert (i<4, ExcInvalidIndex(i,0,3)); + return tria->levels[present_level]->quads.children[present_index]+i; +}; + + + +template +void QuadAccessor::set_children (const int index) const { + Assert (used(), ExcRefineCellNotUsed()); + tria->levels[present_level]->quads.children[present_index] = index; +}; + + + +template +void QuadAccessor::clear_children () const { + set_children (-1); +}; + + + +template +bool QuadAccessor::has_children () const { + Assert (state() == valid, ExcDereferenceInvalidObject()); + return (tria->levels[present_level]->quads.children[present_index] != -1); +}; + + + +template +void QuadAccessor::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 +void QuadAccessor::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 ---------------------*/ + +template +int CellAccessor::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 CellAccessor::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 +void CellAccessor::set_neighbor (const unsigned int i, + const TriaIterator > &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 +bool CellAccessor::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 +bool CellAccessor::refine_flag_set () const { + Assert (used() && active(), ExcRefineCellNotActive()); + return tria->levels[present_level]->refine_flags[present_index]; +}; + + + +template +void CellAccessor::set_refine_flag () const { + Assert (used() && active(), ExcRefineCellNotActive()); + tria->levels[present_level]->refine_flags[present_index] = true; +}; + + + +template +void CellAccessor::clear_refine_flag () const { + Assert (used() && active(), ExcRefineCellNotActive()); + tria->levels[present_level]->refine_flags[present_index] = false; +}; + + + +template +TriaIterator > +CellAccessor::neighbor (const unsigned int i) const { + TriaIterator > q (tria, neighbor_level (i), neighbor_index (i)); + +#ifdef DEBUG + if (q.state() != past_the_end) + Assert (q->used(), ExcUnusedCellAsNeighbor()); +#endif + return q; +}; + + + +template +TriaIterator > +CellAccessor::child (const unsigned int i) const { + TriaIterator > q (tria, present_level+1, child_index (i)); + +#ifdef DEBUG + if (q.state() != past_the_end) + Assert (q->used(), ExcUnusedCellAsChild()); +#endif + return q; +}; + + + +template +bool CellAccessor::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> >; + + diff --git a/deal.II/deal.II/source/numerics/Makefile b/deal.II/deal.II/source/numerics/Makefile new file mode 100644 index 0000000000..aa2591854a --- /dev/null +++ b/deal.II/deal.II/source/numerics/Makefile @@ -0,0 +1,62 @@ +# $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 diff --git a/deal.II/deal.II/source/numerics/assembler.cc b/deal.II/deal.II/source/numerics/assembler.cc new file mode 100644 index 0000000000..1c15331c86 --- /dev/null +++ b/deal.II/deal.II/source/numerics/assembler.cc @@ -0,0 +1,177 @@ +/* $Id$ */ + +#include +#include +#include +#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 +Equation::Equation (const unsigned int n_equations) : + n_eq(n_equations) {}; + + + +void Equation<1>::assemble (dFMatrix &, + vector &, + const FEValues<1> &, + const Triangulation<1>::cell_iterator &) const { + Assert (false, ExcPureVirtualFunctionCalled()); +}; + + + +void Equation<2>::assemble (dFMatrix &, + vector &, + 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 &, + const FEValues<1> &, + const Triangulation<1>::cell_iterator &) const { + Assert (false, ExcPureVirtualFunctionCalled()); +}; + + + +void Equation<2>::assemble (vector &, + const FEValues<2> &, + const Triangulation<2>::cell_iterator &) const { + Assert (false, ExcPureVirtualFunctionCalled()); +}; + + + + +template +Assembler::Assembler (Triangulation *tria, + const int level, + const int index, + const void *local_data) : + DoFCellAccessor (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; iright_hand_sides[i]->n() == dof_handler->n_dofs(), + ExcInvalidData()); +}; + + + +template +void Assembler::assemble (const Equation &equation) { + // re-init fe values for this cell + fe_values.reinit (Triangulation::cell_iterator (tria, + present_level, + present_index), + dof_handler->get_selected_fe()); + + if (assemble_matrix) + // clear cell matrix + for (unsigned int i=0; iget_selected_fe().total_dofs; ++i) + for (unsigned int j=0; jget_selected_fe().total_dofs; ++j) + cell_matrix(i,j) = 0; + + + if (assemble_rhs) + // clear cell vector + for (unsigned int vec=0; vecget_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::cell_iterator(tria, + present_level, + present_index)); + else + if (assemble_matrix) + equation.assemble (cell_matrix, fe_values, + Triangulation::cell_iterator(tria, + present_level, + present_index)); + else + if (assemble_rhs) + equation.assemble (cell_vectors, fe_values, + Triangulation::cell_iterator(tria, + present_level, + present_index)); + else + Assert (false, ExcNoAssemblingRequired()); + + + // get indices of dofs + vector dofs; + dof_indices (dofs); + + if (assemble_matrix) + // distribute cell matrix + for (unsigned int i=0; iget_selected_fe().total_dofs; ++i) + for (unsigned int j=0; jget_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; vecget_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>; diff --git a/deal.II/deal.II/source/numerics/base.cc b/deal.II/deal.II/source/numerics/base.cc new file mode 100644 index 0000000000..99e86bce36 --- /dev/null +++ b/deal.II/deal.II/source/numerics/base.cc @@ -0,0 +1,47 @@ +/* $Id$ */ + +#include +#include + + + +template +ProblemBase::ProblemBase (Triangulation *tria, + DoFHandler *dof) : + tria(tria), dof_handler(dof) {}; + + + + +template +void ProblemBase::assemble (const Equation &equation, + const Quadrature &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::AssemblerData data = {dof_handler, + true, true, + 1, + this, + &quadrature}; + + TriaActiveIterator > assembler (tria, + tria->begin_active()->level(), + tria->begin_active()->index(), + &data); + + do + { + assembler->assemble (equation); + } + while ((++assembler).state() == valid); +}; diff --git a/deal.II/deal.II/source/numerics/data_io.cc b/deal.II/deal.II/source/numerics/data_io.cc new file mode 100644 index 0000000000..b7aa92856a --- /dev/null +++ b/deal.II/deal.II/source/numerics/data_io.cc @@ -0,0 +1,231 @@ +/* $Id$ */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +extern TriaActiveIterator<1,DoFCellAccessor<1> > __dummy566; // wait for gcc2.8 +extern TriaActiveIterator<2,DoFCellAccessor<2> > __dummy567; + + +template +DataOut::DataOut () : + dofs(0) {}; + + + +template +void DataOut::attach_dof_handler (DoFHandler &d) { + dofs = &d; +}; + + + +template +void DataOut::add_data_vector (dVector &vec, + String &name, + String &units) { + DataEntry new_entry = {&vec, name, units}; + data.push_back (new_entry); +}; + + + +template +void DataOut::clear_data_vectors () { + data.erase (data.begin(), data.end()); +}; + + + +template +void DataOut::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::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 is_vertex_dof (dofs->n_dofs(), false); + for (cell=dofs->begin_active(); cell!=endc; ++cell) + for (unsigned int vertex=0; vertex<(1<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 already_written (dofs->n_dofs(), false); + // write vertices + for (cell=dofs->begin_active(); cell!=endc; ++cell) + for (unsigned int vertex=0; vertex<(1<vertex_dof_index(vertex,0)]==false) + { + out << cell->vertex_dof_index(vertex,0) // vertex index + << " "; + for (unsigned int d=0; dvertex(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<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; ibegin_active(); cell!=endc; ++cell) + for (unsigned int vertex=0; vertex<(1<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 +void DataOut::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::active_cell_iterator cell; + DoFHandler::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>; diff --git a/tests/big-tests/Makefile b/tests/big-tests/Makefile new file mode 100644 index 0000000000..00f5f90ea4 --- /dev/null +++ b/tests/big-tests/Makefile @@ -0,0 +1,56 @@ +# $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 diff --git a/tests/big-tests/Makefile.dep b/tests/big-tests/Makefile.dep new file mode 100644 index 0000000000..1ce93aa62f --- /dev/null +++ b/tests/big-tests/Makefile.dep @@ -0,0 +1,33 @@ +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 diff --git a/tests/big-tests/dof/dof_test.cc b/tests/big-tests/dof/dof_test.cc new file mode 100644 index 0000000000..6320aa04e2 --- /dev/null +++ b/tests/big-tests/dof/dof_test.cc @@ -0,0 +1,310 @@ +/* $Id$ */ + + +#include +#include +#include +#include +#include +#include "../../deal/dsmatrix.h" +#include +#include + + +#include +#include +extern "C" { +# include +} + +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 +class Ball : + public StraightBoundary { + public: + virtual Point in_between (const PointArray &neighbors) const { + Point middle = StraightBoundary::in_between(neighbors); + + for (int i=0; i +class CurvedLine : + public StraightBoundary { + public: + virtual Point in_between (const PointArray &neighbors) const { + Point middle = StraightBoundary::in_between(neighbors); + double x=middle(0), + y=middle(1); + + if (y +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 *tria; + DoFHandler *dof; +}; + + + +template +TestCases::TestCases () : + tria(0), dof(0) {}; + + + +template +void TestCases::create_new (const unsigned int) { + if (tria != 0) delete tria; + if (dof != 0) delete dof; + + tria = new Triangulation(); + tria->create_unit_hypercube(); + + dof = new DoFHandler (tria); +}; + + + +template +void TestCases::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 +void TestCases::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::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 *boundary = (test_case==2 ? + new Ball() : + new CurvedLine()); + tria->set_boundary (boundary); + + // refine once + tria->begin_active()->set_refine_flag(); + tria->execute_refinement (); + + Triangulation::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::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 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 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; +}; + diff --git a/tests/big-tests/dof/dof_test.prm b/tests/big-tests/dof/dof_test.prm new file mode 100644 index 0000000000..eac9d72a6b --- /dev/null +++ b/tests/big-tests/dof/dof_test.prm @@ -0,0 +1,4 @@ +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 diff --git a/tests/big-tests/dof/make_ps b/tests/big-tests/dof/make_ps new file mode 100644 index 0000000000..5c6280e614 --- /dev/null +++ b/tests/big-tests/dof/make_ps @@ -0,0 +1,62 @@ +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 " +set output "grid.zoom_in.eps" +plot "grid.zoom_in" + +!echo " Making " +set output "grid.ball.eps" +plot "grid.ball" + +!echo " Making " +set output "grid.curved_line.eps" +plot "grid.curved_line" + +!echo " Making " +set output "grid.random.eps" +plot "grid.random" + + + +set data style dots + +!echo " Making " +set output "sparsity.zoom_in.eps" +plot "sparsity.zoom_in" + +!echo " Making " +set output "sparsity.ball.eps" +plot "sparsity.ball" + +!echo " Making " +set output "sparsity.curved_line.eps" +plot "sparsity.curved_line" + +!echo " Making " +set output "sparsity.random.eps" +plot "sparsity.random" + + + +!echo " Making " +set output "sparsity.c.zoom_in.eps" +plot "sparsity.c.zoom_in" + +!echo " Making " +set output "sparsity.c.ball.eps" +plot "sparsity.c.ball" + +!echo " Making " +set output "sparsity.c.curved_line.eps" +plot "sparsity.c.curved_line" + +!echo " Making " +set output "sparsity.c.random.eps" +plot "sparsity.c.random" diff --git a/tests/big-tests/grid/grid_test.cc b/tests/big-tests/grid/grid_test.cc new file mode 100644 index 0000000000..62c0fa1990 --- /dev/null +++ b/tests/big-tests/grid/grid_test.cc @@ -0,0 +1,208 @@ +/* $Id$ */ + +#include +#include +#include +#include +extern "C" { +# include +} + + +// 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 +class Ball : + public StraightBoundary { + public: + virtual Point in_between (const PointArray &neighbors) const { + Point middle = StraightBoundary::in_between(neighbors); + + for (int i=0; i +class CurvedLine : + public StraightBoundary { + public: + virtual Point in_between (const PointArray &neighbors) const { + Point middle = StraightBoundary::in_between(neighbors); + double x=middle(0), + y=middle(1); + + if (y()", do template parameter +// passing this way... +template +void test (const int test_case, const Point &) { + Triangulation 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::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 ball; + CurvedLine 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::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::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; +}; diff --git a/tests/big-tests/grid/make_ps b/tests/big-tests/grid/make_ps new file mode 100644 index 0000000000..a0ed968360 --- /dev/null +++ b/tests/big-tests/grid/make_ps @@ -0,0 +1,16 @@ +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" + diff --git a/tests/big-tests/poisson/poisson.cc b/tests/big-tests/poisson/poisson.cc new file mode 100644 index 0000000000..47c8848dba --- /dev/null +++ b/tests/big-tests/poisson/poisson.cc @@ -0,0 +1,35 @@ +/* $Id$ */ + + +#include +#include +#include +#include +#include +#include "../../deal/dsmatrix.h> +#include +#include +#include +#include + +#include +#include +extern "C" { +# include +} + +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); +}; -- 2.39.5